Commit | Line | Data |
---|---|---|
b61776fb SM |
1 | /* |
2 | * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #include "../command.h" | |
9 | #include "common/argpar/argpar.h" | |
10 | #include <lttng/lttng.h> | |
11 | #include <stdio.h> | |
12 | ||
13 | #ifdef LTTNG_EMBED_HELP | |
14 | static const char help_msg[] = | |
15 | #include <lttng-remove-trigger.1.h> | |
16 | ; | |
17 | #endif | |
18 | ||
19 | enum { | |
20 | OPT_HELP, | |
21 | OPT_LIST_OPTIONS, | |
481c5310 | 22 | OPT_OWNER_UID, |
b61776fb SM |
23 | }; |
24 | ||
25 | static const | |
26 | struct argpar_opt_descr remove_trigger_options[] = { | |
27 | { OPT_HELP, 'h', "help", false }, | |
28 | { OPT_LIST_OPTIONS, '\0', "list-options", false }, | |
481c5310 | 29 | { OPT_OWNER_UID, '\0', "owner-uid", true }, |
b61776fb SM |
30 | ARGPAR_OPT_DESCR_SENTINEL, |
31 | }; | |
32 | ||
33 | static | |
34 | bool assign_string(char **dest, const char *src, const char *opt_name) | |
35 | { | |
36 | bool ret; | |
37 | ||
38 | if (*dest) { | |
39 | ERR("Duplicate option '%s' given.", opt_name); | |
40 | goto error; | |
41 | } | |
42 | ||
43 | *dest = strdup(src); | |
44 | if (!*dest) { | |
45 | ERR("Failed to allocate '%s' string.", opt_name); | |
46 | goto error; | |
47 | } | |
48 | ||
49 | ret = true; | |
50 | goto end; | |
51 | ||
52 | error: | |
53 | ret = false; | |
54 | ||
55 | end: | |
56 | return ret; | |
57 | } | |
58 | ||
59 | int cmd_remove_trigger(int argc, const char **argv) | |
60 | { | |
61 | int ret; | |
62 | struct argpar_parse_ret argpar_parse_ret = {}; | |
e80b7150 | 63 | const char *name = NULL; |
b61776fb SM |
64 | int i; |
65 | struct lttng_triggers *triggers = NULL; | |
66 | unsigned int triggers_count; | |
67 | enum lttng_trigger_status trigger_status; | |
68 | const struct lttng_trigger *trigger_to_remove = NULL; | |
481c5310 | 69 | char *owner_uid = NULL; |
b61776fb SM |
70 | long long uid; |
71 | ||
72 | argpar_parse_ret = argpar_parse(argc - 1, argv + 1, | |
73 | remove_trigger_options, true); | |
74 | if (!argpar_parse_ret.items) { | |
75 | ERR("%s", argpar_parse_ret.error); | |
76 | goto error; | |
77 | } | |
78 | ||
79 | for (i = 0; i < argpar_parse_ret.items->n_items; i++) { | |
80 | const struct argpar_item *item = | |
81 | argpar_parse_ret.items->items[i]; | |
82 | ||
83 | if (item->type == ARGPAR_ITEM_TYPE_OPT) { | |
84 | const struct argpar_item_opt *item_opt = | |
85 | (const struct argpar_item_opt *) item; | |
86 | ||
87 | switch (item_opt->descr->id) { | |
88 | case OPT_HELP: | |
89 | SHOW_HELP(); | |
90 | ret = 0; | |
91 | goto end; | |
92 | case OPT_LIST_OPTIONS: | |
93 | list_cmd_options_argpar(stdout, | |
94 | remove_trigger_options); | |
95 | ret = 0; | |
96 | goto end; | |
481c5310 | 97 | case OPT_OWNER_UID: |
b61776fb | 98 | { |
481c5310 SM |
99 | if (!assign_string(&owner_uid, item_opt->arg, |
100 | "--owner-uid")) { | |
b61776fb SM |
101 | goto error; |
102 | } | |
103 | break; | |
104 | } | |
105 | default: | |
106 | abort(); | |
107 | } | |
108 | } else { | |
109 | const struct argpar_item_non_opt *item_non_opt = | |
110 | (const struct argpar_item_non_opt *) item; | |
111 | ||
e80b7150 | 112 | if (name) { |
b61776fb SM |
113 | ERR("Unexpected argument '%s'", item_non_opt->arg); |
114 | goto error; | |
115 | } | |
116 | ||
e80b7150 | 117 | name = item_non_opt->arg; |
b61776fb SM |
118 | } |
119 | } | |
120 | ||
e80b7150 SM |
121 | if (!name) { |
122 | ERR("Missing `name` argument."); | |
b61776fb SM |
123 | goto error; |
124 | } | |
125 | ||
481c5310 | 126 | if (owner_uid) { |
b61776fb SM |
127 | char *end; |
128 | ||
129 | errno = 0; | |
481c5310 SM |
130 | uid = strtol(owner_uid, &end, 10); |
131 | if (end == owner_uid || *end != '\0' || errno != 0) { | |
132 | ERR("Failed to parse `%s` as an integer.", owner_uid); | |
b61776fb SM |
133 | } |
134 | } else { | |
135 | uid = geteuid(); | |
136 | } | |
137 | ||
138 | ret = lttng_list_triggers(&triggers); | |
139 | if (ret != LTTNG_OK) { | |
140 | ERR("Failed to get the list of triggers."); | |
141 | goto error; | |
142 | } | |
143 | ||
144 | trigger_status = lttng_triggers_get_count(triggers, &triggers_count); | |
145 | assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); | |
146 | ||
147 | for (i = 0; i < triggers_count; i++) { | |
148 | const struct lttng_trigger *trigger; | |
149 | const char *trigger_name; | |
150 | uid_t trigger_uid; | |
151 | ||
152 | trigger = lttng_triggers_get_at_index(triggers, i); | |
153 | trigger_status = lttng_trigger_get_name(trigger, &trigger_name); | |
0efb2ad7 JG |
154 | switch (trigger_status) { |
155 | case LTTNG_TRIGGER_STATUS_OK: | |
156 | break; | |
157 | case LTTNG_TRIGGER_STATUS_UNSET: | |
158 | /* Don't compare against anonymous triggers. */ | |
159 | continue; | |
160 | default: | |
161 | abort(); | |
162 | } | |
b61776fb SM |
163 | |
164 | trigger_status = lttng_trigger_get_owner_uid( | |
165 | trigger, &trigger_uid); | |
166 | assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); | |
167 | ||
e80b7150 | 168 | if (trigger_uid == uid && strcmp(trigger_name, name) == 0) { |
b61776fb SM |
169 | trigger_to_remove = trigger; |
170 | break; | |
171 | } | |
172 | } | |
173 | ||
174 | if (!trigger_to_remove) { | |
e80b7150 | 175 | ERR("Couldn't find trigger with name `%s`.", name); |
b61776fb SM |
176 | goto error; |
177 | } | |
178 | ||
179 | ret = lttng_unregister_trigger(trigger_to_remove); | |
180 | if (ret != 0) { | |
e80b7150 | 181 | ERR("Failed to unregister trigger `%s`.", name); |
b61776fb SM |
182 | goto error; |
183 | } | |
184 | ||
e80b7150 | 185 | MSG("Removed trigger `%s`.", name); |
b61776fb SM |
186 | |
187 | ret = 0; | |
188 | goto end; | |
189 | ||
190 | error: | |
191 | ret = 1; | |
192 | ||
193 | end: | |
194 | argpar_parse_ret_fini(&argpar_parse_ret); | |
195 | lttng_triggers_destroy(triggers); | |
481c5310 | 196 | free(owner_uid); |
b61776fb SM |
197 | |
198 | return ret; | |
199 | } |