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