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 | ||
c9e313bc | 8 | #include "../command.hpp" |
b61776fb | 9 | #include "common/argpar/argpar.h" |
c9e313bc SM |
10 | #include "common/argpar-utils/argpar-utils.hpp" |
11 | #include "common/mi-lttng.hpp" | |
b61776fb SM |
12 | #include <lttng/lttng.h> |
13 | #include <stdio.h> | |
14 | ||
15 | #ifdef LTTNG_EMBED_HELP | |
16 | static const char help_msg[] = | |
17 | #include <lttng-remove-trigger.1.h> | |
18 | ; | |
19 | #endif | |
20 | ||
21 | enum { | |
22 | OPT_HELP, | |
23 | OPT_LIST_OPTIONS, | |
481c5310 | 24 | OPT_OWNER_UID, |
b61776fb SM |
25 | }; |
26 | ||
27 | static const | |
28 | struct argpar_opt_descr remove_trigger_options[] = { | |
29 | { OPT_HELP, 'h', "help", false }, | |
30 | { OPT_LIST_OPTIONS, '\0', "list-options", false }, | |
481c5310 | 31 | { OPT_OWNER_UID, '\0', "owner-uid", true }, |
b61776fb SM |
32 | ARGPAR_OPT_DESCR_SENTINEL, |
33 | }; | |
34 | ||
35 | static | |
36 | bool assign_string(char **dest, const char *src, const char *opt_name) | |
37 | { | |
38 | bool ret; | |
39 | ||
40 | if (*dest) { | |
41 | ERR("Duplicate option '%s' given.", opt_name); | |
42 | goto error; | |
43 | } | |
44 | ||
45 | *dest = strdup(src); | |
46 | if (!*dest) { | |
47 | ERR("Failed to allocate '%s' string.", opt_name); | |
48 | goto error; | |
49 | } | |
50 | ||
51 | ret = true; | |
52 | goto end; | |
53 | ||
54 | error: | |
55 | ret = false; | |
56 | ||
57 | end: | |
58 | return ret; | |
59 | } | |
60 | ||
61 | int cmd_remove_trigger(int argc, const char **argv) | |
62 | { | |
523c4f8c | 63 | enum lttng_error_code ret_code; |
b61776fb | 64 | int ret; |
d50d200a SM |
65 | struct argpar_iter *argpar_iter = NULL; |
66 | const struct argpar_item *argpar_item = NULL; | |
e80b7150 | 67 | const char *name = NULL; |
b61776fb SM |
68 | int i; |
69 | struct lttng_triggers *triggers = NULL; | |
70 | unsigned int triggers_count; | |
71 | enum lttng_trigger_status trigger_status; | |
72 | const struct lttng_trigger *trigger_to_remove = NULL; | |
481c5310 | 73 | char *owner_uid = NULL; |
b61776fb | 74 | long long uid; |
523c4f8c JR |
75 | struct mi_writer *mi_writer = NULL; |
76 | ||
77 | if (lttng_opt_mi) { | |
78 | mi_writer = mi_lttng_writer_create( | |
79 | fileno(stdout), lttng_opt_mi); | |
80 | if (!mi_writer) { | |
81 | ret = CMD_ERROR; | |
82 | goto error; | |
83 | } | |
84 | ||
85 | /* Open command element. */ | |
86 | ret = mi_lttng_writer_command_open(mi_writer, | |
87 | mi_lttng_element_command_remove_trigger); | |
88 | if (ret) { | |
89 | ret = CMD_ERROR; | |
90 | goto error; | |
91 | } | |
92 | ||
93 | /* Open output element. */ | |
94 | ret = mi_lttng_writer_open_element( | |
95 | mi_writer, mi_lttng_element_command_output); | |
96 | if (ret) { | |
97 | ret = CMD_ERROR; | |
98 | goto error; | |
99 | } | |
100 | } | |
b61776fb | 101 | |
d50d200a SM |
102 | argc--; |
103 | argv++; | |
104 | ||
105 | argpar_iter = argpar_iter_create(argc, argv, remove_trigger_options); | |
106 | if (!argpar_iter) { | |
107 | ERR("Failed to allocate an argpar iter."); | |
b61776fb SM |
108 | goto error; |
109 | } | |
110 | ||
d50d200a SM |
111 | while (true) { |
112 | enum parse_next_item_status status; | |
113 | ||
35c4b2b3 | 114 | status = parse_next_item(argpar_iter, &argpar_item, 1, argv, |
ef9ff9cb SM |
115 | true, NULL, NULL); |
116 | if (status == PARSE_NEXT_ITEM_STATUS_ERROR || | |
117 | status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) { | |
d50d200a SM |
118 | goto error; |
119 | } else if (status == PARSE_NEXT_ITEM_STATUS_END) { | |
120 | break; | |
121 | } | |
122 | ||
123 | assert(status == PARSE_NEXT_ITEM_STATUS_OK); | |
b61776fb | 124 | |
d50d200a SM |
125 | if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) { |
126 | const struct argpar_opt_descr *descr = | |
127 | argpar_item_opt_descr(argpar_item); | |
128 | const char *arg = argpar_item_opt_arg(argpar_item); | |
b61776fb | 129 | |
d50d200a | 130 | switch (descr->id) { |
b61776fb SM |
131 | case OPT_HELP: |
132 | SHOW_HELP(); | |
133 | ret = 0; | |
134 | goto end; | |
135 | case OPT_LIST_OPTIONS: | |
136 | list_cmd_options_argpar(stdout, | |
137 | remove_trigger_options); | |
138 | ret = 0; | |
139 | goto end; | |
481c5310 | 140 | case OPT_OWNER_UID: |
b61776fb | 141 | { |
d50d200a | 142 | if (!assign_string(&owner_uid, arg, |
481c5310 | 143 | "--owner-uid")) { |
b61776fb SM |
144 | goto error; |
145 | } | |
146 | break; | |
147 | } | |
148 | default: | |
149 | abort(); | |
150 | } | |
151 | } else { | |
d50d200a | 152 | const char *arg = argpar_item_non_opt_arg(argpar_item); |
b61776fb | 153 | |
e80b7150 | 154 | if (name) { |
d50d200a | 155 | ERR("Unexpected argument '%s'", arg); |
b61776fb SM |
156 | goto error; |
157 | } | |
158 | ||
d50d200a | 159 | name = arg; |
b61776fb SM |
160 | } |
161 | } | |
162 | ||
e80b7150 SM |
163 | if (!name) { |
164 | ERR("Missing `name` argument."); | |
b61776fb SM |
165 | goto error; |
166 | } | |
167 | ||
481c5310 | 168 | if (owner_uid) { |
b61776fb SM |
169 | char *end; |
170 | ||
171 | errno = 0; | |
481c5310 SM |
172 | uid = strtol(owner_uid, &end, 10); |
173 | if (end == owner_uid || *end != '\0' || errno != 0) { | |
174 | ERR("Failed to parse `%s` as an integer.", owner_uid); | |
b61776fb SM |
175 | } |
176 | } else { | |
177 | uid = geteuid(); | |
178 | } | |
179 | ||
180 | ret = lttng_list_triggers(&triggers); | |
181 | if (ret != LTTNG_OK) { | |
182 | ERR("Failed to get the list of triggers."); | |
183 | goto error; | |
184 | } | |
185 | ||
186 | trigger_status = lttng_triggers_get_count(triggers, &triggers_count); | |
a0377dfe | 187 | LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK); |
b61776fb SM |
188 | |
189 | for (i = 0; i < triggers_count; i++) { | |
190 | const struct lttng_trigger *trigger; | |
191 | const char *trigger_name; | |
192 | uid_t trigger_uid; | |
193 | ||
194 | trigger = lttng_triggers_get_at_index(triggers, i); | |
195 | trigger_status = lttng_trigger_get_name(trigger, &trigger_name); | |
0efb2ad7 JG |
196 | switch (trigger_status) { |
197 | case LTTNG_TRIGGER_STATUS_OK: | |
198 | break; | |
199 | case LTTNG_TRIGGER_STATUS_UNSET: | |
200 | /* Don't compare against anonymous triggers. */ | |
201 | continue; | |
202 | default: | |
203 | abort(); | |
204 | } | |
b61776fb SM |
205 | |
206 | trigger_status = lttng_trigger_get_owner_uid( | |
207 | trigger, &trigger_uid); | |
a0377dfe | 208 | LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK); |
b61776fb | 209 | |
e80b7150 | 210 | if (trigger_uid == uid && strcmp(trigger_name, name) == 0) { |
b61776fb SM |
211 | trigger_to_remove = trigger; |
212 | break; | |
213 | } | |
214 | } | |
215 | ||
216 | if (!trigger_to_remove) { | |
e80b7150 | 217 | ERR("Couldn't find trigger with name `%s`.", name); |
b61776fb SM |
218 | goto error; |
219 | } | |
220 | ||
221 | ret = lttng_unregister_trigger(trigger_to_remove); | |
222 | if (ret != 0) { | |
e80b7150 | 223 | ERR("Failed to unregister trigger `%s`.", name); |
b61776fb SM |
224 | goto error; |
225 | } | |
226 | ||
523c4f8c JR |
227 | if (lttng_opt_mi) { |
228 | ret_code = lttng_trigger_mi_serialize( | |
229 | trigger_to_remove, mi_writer, NULL); | |
230 | if (ret_code != LTTNG_OK) { | |
231 | goto error; | |
232 | } | |
233 | } | |
e80b7150 | 234 | MSG("Removed trigger `%s`.", name); |
b61776fb SM |
235 | |
236 | ret = 0; | |
237 | goto end; | |
238 | ||
239 | error: | |
240 | ret = 1; | |
241 | ||
242 | end: | |
523c4f8c | 243 | /* Mi closing. */ |
fc63f82b | 244 | if (lttng_opt_mi && mi_writer) { |
523c4f8c JR |
245 | /* Close output element. */ |
246 | int mi_ret = mi_lttng_writer_close_element(mi_writer); | |
247 | if (mi_ret) { | |
248 | ret = 1; | |
249 | goto cleanup; | |
250 | } | |
251 | ||
252 | mi_ret = mi_lttng_writer_write_element_bool(mi_writer, | |
253 | mi_lttng_element_command_success, ret ? 0 : 1); | |
254 | if (mi_ret) { | |
255 | ret = 1; | |
256 | goto cleanup; | |
257 | } | |
258 | ||
259 | /* Command element close. */ | |
260 | mi_ret = mi_lttng_writer_command_close(mi_writer); | |
261 | if (mi_ret) { | |
262 | ret = 1; | |
263 | goto cleanup; | |
264 | } | |
265 | } | |
266 | ||
267 | cleanup: | |
d50d200a SM |
268 | argpar_item_destroy(argpar_item); |
269 | argpar_iter_destroy(argpar_iter); | |
b61776fb | 270 | lttng_triggers_destroy(triggers); |
481c5310 | 271 | free(owner_uid); |
b61776fb | 272 | |
523c4f8c JR |
273 | if (mi_writer && mi_lttng_writer_destroy(mi_writer)) { |
274 | /* Preserve original error code. */ | |
275 | ret = ret ? ret : CMD_ERROR; | |
276 | } | |
b61776fb SM |
277 | return ret; |
278 | } |