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" | |
ea76a8bb | 10 | #include "common/argpar-utils/argpar-utils.h" |
27692bb8 | 11 | #include "common/mi-lttng.h" |
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 | { | |
27692bb8 | 63 | enum lttng_error_code ret_code; |
b61776fb | 64 | int ret; |
ea76a8bb SM |
65 | struct argpar_iter *argpar_iter = NULL; |
66 | const struct argpar_item *argpar_item = NULL; | |
7401db0d | 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; |
27692bb8 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 | |
ea76a8bb 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 | ||
ea76a8bb SM |
111 | while (true) { |
112 | enum parse_next_item_status status; | |
113 | ||
5f5ce3e6 | 114 | status = parse_next_item(argpar_iter, &argpar_item, 1, argv, |
ea76a8bb SM |
115 | true, NULL); |
116 | if (status == PARSE_NEXT_ITEM_STATUS_ERROR) { | |
117 | goto error; | |
118 | } else if (status == PARSE_NEXT_ITEM_STATUS_END) { | |
119 | break; | |
120 | } | |
121 | ||
122 | assert(status == PARSE_NEXT_ITEM_STATUS_OK); | |
b61776fb | 123 | |
ea76a8bb SM |
124 | if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) { |
125 | const struct argpar_opt_descr *descr = | |
126 | argpar_item_opt_descr(argpar_item); | |
127 | const char *arg = argpar_item_opt_arg(argpar_item); | |
b61776fb | 128 | |
ea76a8bb | 129 | switch (descr->id) { |
b61776fb SM |
130 | case OPT_HELP: |
131 | SHOW_HELP(); | |
132 | ret = 0; | |
133 | goto end; | |
134 | case OPT_LIST_OPTIONS: | |
135 | list_cmd_options_argpar(stdout, | |
136 | remove_trigger_options); | |
137 | ret = 0; | |
138 | goto end; | |
481c5310 | 139 | case OPT_OWNER_UID: |
b61776fb | 140 | { |
ea76a8bb | 141 | if (!assign_string(&owner_uid, arg, |
481c5310 | 142 | "--owner-uid")) { |
b61776fb SM |
143 | goto error; |
144 | } | |
145 | break; | |
146 | } | |
147 | default: | |
148 | abort(); | |
149 | } | |
150 | } else { | |
ea76a8bb | 151 | const char *arg = argpar_item_non_opt_arg(argpar_item); |
b61776fb | 152 | |
7401db0d | 153 | if (name) { |
ea76a8bb | 154 | ERR("Unexpected argument '%s'", arg); |
b61776fb SM |
155 | goto error; |
156 | } | |
157 | ||
ea76a8bb | 158 | name = arg; |
b61776fb SM |
159 | } |
160 | } | |
161 | ||
7401db0d SM |
162 | if (!name) { |
163 | ERR("Missing `name` argument."); | |
b61776fb SM |
164 | goto error; |
165 | } | |
166 | ||
481c5310 | 167 | if (owner_uid) { |
b61776fb SM |
168 | char *end; |
169 | ||
170 | errno = 0; | |
481c5310 SM |
171 | uid = strtol(owner_uid, &end, 10); |
172 | if (end == owner_uid || *end != '\0' || errno != 0) { | |
173 | ERR("Failed to parse `%s` as an integer.", owner_uid); | |
b61776fb SM |
174 | } |
175 | } else { | |
176 | uid = geteuid(); | |
177 | } | |
178 | ||
179 | ret = lttng_list_triggers(&triggers); | |
180 | if (ret != LTTNG_OK) { | |
181 | ERR("Failed to get the list of triggers."); | |
182 | goto error; | |
183 | } | |
184 | ||
185 | trigger_status = lttng_triggers_get_count(triggers, &triggers_count); | |
186 | assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); | |
187 | ||
188 | for (i = 0; i < triggers_count; i++) { | |
189 | const struct lttng_trigger *trigger; | |
190 | const char *trigger_name; | |
191 | uid_t trigger_uid; | |
192 | ||
193 | trigger = lttng_triggers_get_at_index(triggers, i); | |
194 | trigger_status = lttng_trigger_get_name(trigger, &trigger_name); | |
0efb2ad7 JG |
195 | switch (trigger_status) { |
196 | case LTTNG_TRIGGER_STATUS_OK: | |
197 | break; | |
198 | case LTTNG_TRIGGER_STATUS_UNSET: | |
199 | /* Don't compare against anonymous triggers. */ | |
200 | continue; | |
201 | default: | |
202 | abort(); | |
203 | } | |
b61776fb SM |
204 | |
205 | trigger_status = lttng_trigger_get_owner_uid( | |
206 | trigger, &trigger_uid); | |
207 | assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); | |
208 | ||
7401db0d | 209 | if (trigger_uid == uid && strcmp(trigger_name, name) == 0) { |
b61776fb SM |
210 | trigger_to_remove = trigger; |
211 | break; | |
212 | } | |
213 | } | |
214 | ||
215 | if (!trigger_to_remove) { | |
7401db0d | 216 | ERR("Couldn't find trigger with name `%s`.", name); |
b61776fb SM |
217 | goto error; |
218 | } | |
219 | ||
220 | ret = lttng_unregister_trigger(trigger_to_remove); | |
221 | if (ret != 0) { | |
7401db0d | 222 | ERR("Failed to unregister trigger `%s`.", name); |
b61776fb SM |
223 | goto error; |
224 | } | |
225 | ||
27692bb8 JR |
226 | if (lttng_opt_mi) { |
227 | ret_code = lttng_trigger_mi_serialize( | |
228 | trigger_to_remove, mi_writer, NULL); | |
229 | if (ret_code != LTTNG_OK) { | |
230 | goto error; | |
231 | } | |
232 | } | |
7401db0d | 233 | MSG("Removed trigger `%s`.", name); |
b61776fb SM |
234 | |
235 | ret = 0; | |
236 | goto end; | |
237 | ||
238 | error: | |
239 | ret = 1; | |
240 | ||
241 | end: | |
27692bb8 | 242 | /* Mi closing. */ |
9ec21c2a | 243 | if (lttng_opt_mi && mi_writer) { |
27692bb8 JR |
244 | /* Close output element. */ |
245 | int mi_ret = mi_lttng_writer_close_element(mi_writer); | |
246 | if (mi_ret) { | |
247 | ret = 1; | |
248 | goto cleanup; | |
249 | } | |
250 | ||
251 | mi_ret = mi_lttng_writer_write_element_bool(mi_writer, | |
252 | mi_lttng_element_command_success, ret ? 0 : 1); | |
253 | if (mi_ret) { | |
254 | ret = 1; | |
255 | goto cleanup; | |
256 | } | |
257 | ||
258 | /* Command element close. */ | |
259 | mi_ret = mi_lttng_writer_command_close(mi_writer); | |
260 | if (mi_ret) { | |
261 | ret = 1; | |
262 | goto cleanup; | |
263 | } | |
264 | } | |
265 | ||
266 | cleanup: | |
ea76a8bb SM |
267 | argpar_item_destroy(argpar_item); |
268 | argpar_iter_destroy(argpar_iter); | |
b61776fb | 269 | lttng_triggers_destroy(triggers); |
481c5310 | 270 | free(owner_uid); |
b61776fb | 271 | |
27692bb8 JR |
272 | if (mi_writer && mi_lttng_writer_destroy(mi_writer)) { |
273 | /* Preserve original error code. */ | |
274 | ret = ret ? ret : CMD_ERROR; | |
275 | } | |
b61776fb SM |
276 | return ret; |
277 | } |