Wrap main functions to handle uncaught exceptions
[lttng-tools.git] / src / bin / lttng / commands / disable_channels.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include "../command.hpp"
10
11 #include <common/mi-lttng.hpp>
12
13 #include <lttng/domain-internal.hpp>
14
15 #include <popt.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 static int opt_kernel;
24 static char *opt_session_name;
25 static int opt_userspace;
26
27 #ifdef LTTNG_EMBED_HELP
28 static const char help_msg[] =
29 #include <lttng-disable-channel.1.h>
30 ;
31 #endif
32
33 enum {
34 OPT_HELP = 1,
35 OPT_USERSPACE,
36 OPT_LIST_OPTIONS,
37 };
38
39 static struct lttng_handle *handle;
40 static struct mi_writer *writer;
41
42 static struct poptOption long_options[] = {
43 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
44 { "help", 'h', POPT_ARG_NONE, nullptr, OPT_HELP, nullptr, nullptr },
45 { "session", 's', POPT_ARG_STRING, &opt_session_name, 0, nullptr, nullptr },
46 { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr },
47 { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
48 { "list-options", 0, POPT_ARG_NONE, nullptr, OPT_LIST_OPTIONS, nullptr, nullptr },
49 { nullptr, 0, 0, nullptr, 0, nullptr, nullptr }
50 };
51
52 static int mi_partial_channel_print(char *channel_name, unsigned int enabled, int success)
53 {
54 int ret;
55
56 LTTNG_ASSERT(writer);
57 LTTNG_ASSERT(channel_name);
58
59 /* Open channel element */
60 ret = mi_lttng_writer_open_element(writer, config_element_channel);
61 if (ret) {
62 goto end;
63 }
64
65 /* Name */
66 ret = mi_lttng_writer_write_element_string(writer, config_element_name, channel_name);
67 if (ret) {
68 goto end;
69 }
70
71 /* Enabled ? */
72 ret = mi_lttng_writer_write_element_bool(writer, config_element_enabled, enabled);
73 if (ret) {
74 goto end;
75 }
76
77 /* Success ? */
78 ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_success, success);
79 if (ret) {
80 goto end;
81 }
82
83 /* Closing channel element */
84 ret = mi_lttng_writer_close_element(writer);
85
86 end:
87 return ret;
88 }
89
90 /*
91 * Disabling channel using the lttng API.
92 */
93 static int disable_channels(char *session_name, char *channel_list)
94 {
95 int ret = CMD_SUCCESS;
96 /* Normal case for disable channed is enabled = false */
97 bool warn = false, success, enabled = false;
98 char *channel_name;
99 struct lttng_domain dom;
100
101 memset(&dom, 0, sizeof(dom));
102
103 /* Create lttng domain */
104 if (opt_kernel) {
105 dom.type = LTTNG_DOMAIN_KERNEL;
106 } else if (opt_userspace) {
107 dom.type = LTTNG_DOMAIN_UST;
108 } else {
109 /* Checked by the caller. */
110 abort();
111 }
112
113 handle = lttng_create_handle(session_name, &dom);
114 if (handle == nullptr) {
115 ret = -1;
116 goto error;
117 }
118
119 /* Prepare MI */
120 if (lttng_opt_mi) {
121 /* open a channels element */
122 ret = mi_lttng_writer_open_element(writer, config_element_channels);
123 if (ret) {
124 ret = CMD_ERROR;
125 goto error;
126 }
127 }
128
129 /* Strip channel list */
130 channel_name = strtok(channel_list, ",");
131 while (channel_name != nullptr) {
132 DBG("Disabling channel %s", channel_name);
133
134 ret = lttng_disable_channel(handle, channel_name);
135 if (ret < 0) {
136 ERR("Channel %s: %s (session %s)",
137 channel_name,
138 lttng_strerror(ret),
139 session_name);
140 warn = true;
141
142 /*
143 * Mi:
144 * We assume that if an error occurred the channel is still active.
145 * This might not be the case but is a good assumption.
146 * The client should look at the stderr stream
147 * for more informations.
148 */
149 enabled = true;
150 success = false;
151
152 } else {
153 MSG("%s channel %s disabled for session %s",
154 lttng_domain_type_str(dom.type),
155 channel_name,
156 session_name);
157 enabled = false;
158 success = true;
159 }
160
161 /* Print the channel */
162 if (lttng_opt_mi) {
163 ret = mi_partial_channel_print(channel_name, enabled, success);
164 if (ret) {
165 ret = CMD_ERROR;
166 goto error;
167 }
168 }
169
170 /* Next channel */
171 channel_name = strtok(nullptr, ",");
172 }
173
174 ret = CMD_SUCCESS;
175
176 /* Close Mi */
177 if (lttng_opt_mi) {
178 /* Close channels element */
179 ret = mi_lttng_writer_close_element(writer);
180 if (ret) {
181 ret = CMD_ERROR;
182 goto error;
183 }
184 }
185
186 error:
187 /* Bypass the warning if a more important error happened */
188 if (!ret && warn) {
189 ret = CMD_WARNING;
190 }
191
192 lttng_destroy_handle(handle);
193
194 return ret;
195 }
196
197 /*
198 * cmd_disable_channels
199 *
200 * Disable channel to trace session
201 */
202 int cmd_disable_channels(int argc, const char **argv)
203 {
204 int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
205 static poptContext pc;
206 char *session_name = nullptr;
207 char *channel_list = nullptr;
208 const char *arg_channel_list = nullptr;
209 const char *leftover = nullptr;
210
211 pc = poptGetContext(nullptr, argc, argv, long_options, 0);
212 poptReadDefaultConfig(pc, 0);
213
214 while ((opt = poptGetNextOpt(pc)) != -1) {
215 switch (opt) {
216 case OPT_HELP:
217 SHOW_HELP();
218 goto end;
219 case OPT_USERSPACE:
220 opt_userspace = 1;
221 break;
222 case OPT_LIST_OPTIONS:
223 list_cmd_options(stdout, long_options);
224 goto end;
225 default:
226 ret = CMD_UNDEFINED;
227 goto end;
228 }
229 }
230
231 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace, false);
232 if (ret) {
233 ret = CMD_ERROR;
234 goto end;
235 }
236
237 arg_channel_list = poptGetArg(pc);
238 if (arg_channel_list == nullptr) {
239 ERR("Missing channel name(s).");
240 ret = CMD_ERROR;
241 goto end;
242 }
243
244 channel_list = strdup(arg_channel_list);
245 if (channel_list == nullptr) {
246 PERROR("Failed to copy channel name");
247 ret = CMD_ERROR;
248 goto end;
249 }
250
251 leftover = poptGetArg(pc);
252 if (leftover) {
253 ERR("Unknown argument: %s", leftover);
254 ret = CMD_ERROR;
255 goto end;
256 }
257
258 if (!opt_session_name) {
259 session_name = get_session_name();
260 if (session_name == nullptr) {
261 ret = CMD_ERROR;
262 goto end;
263 }
264 } else {
265 session_name = opt_session_name;
266 }
267
268 /* Mi check */
269 if (lttng_opt_mi) {
270 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
271 if (!writer) {
272 ret = -LTTNG_ERR_NOMEM;
273 goto end;
274 }
275
276 /* Open command element */
277 ret = mi_lttng_writer_command_open(writer,
278 mi_lttng_element_command_disable_channel);
279 if (ret) {
280 ret = CMD_ERROR;
281 goto end;
282 }
283
284 /* Open output element */
285 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output);
286 if (ret) {
287 ret = CMD_ERROR;
288 goto end;
289 }
290 }
291
292 command_ret = disable_channels(session_name, channel_list);
293 if (command_ret) {
294 success = 0;
295 }
296
297 /* Mi closing */
298 if (lttng_opt_mi) {
299 /* Close output element */
300 ret = mi_lttng_writer_close_element(writer);
301 if (ret) {
302 ret = CMD_ERROR;
303 goto end;
304 }
305
306 /* Success ? */
307 ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_success, success);
308 if (ret) {
309 ret = CMD_ERROR;
310 goto end;
311 }
312
313 /* Command element close */
314 ret = mi_lttng_writer_command_close(writer);
315 if (ret) {
316 ret = CMD_ERROR;
317 goto end;
318 }
319 }
320
321 end:
322 /* Mi clean-up */
323 if (writer && mi_lttng_writer_destroy(writer)) {
324 /* Preserve original error code */
325 ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
326 }
327
328 if (!opt_session_name && session_name) {
329 free(session_name);
330 }
331
332 free(channel_list);
333
334 /* Overwrite ret if an error occurred in disable_channels */
335 ret = command_ret ? command_ret : ret;
336
337 poptFreeContext(pc);
338 return ret;
339 }
This page took 0.056219 seconds and 4 git commands to generate.