Add --enable-embedded-help option to embed --help messages in binaries
[lttng-tools.git] / src / bin / lttng / commands / track-untrack.c
CommitLineData
ccf10263
MD
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2015 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
ccf10263
MD
19#define _LGPL_SOURCE
20#include <ctype.h>
21#include <popt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <unistd.h>
3ecec76a 28#include <assert.h>
ccf10263
MD
29
30#include <urcu/list.h>
31
32#include <common/mi-lttng.h>
33
34#include "../command.h"
35
36enum cmd_type {
37 CMD_TRACK,
38 CMD_UNTRACK,
39};
40
41static char *opt_session_name;
42static int opt_kernel;
43static int opt_userspace;
44static int opt_all;
45static char *opt_pid_string;
46static int opt_pid;
47
48enum {
49 OPT_HELP = 1,
50 OPT_LIST_OPTIONS,
51 OPT_SESSION,
52 OPT_PID,
53};
54
55static struct poptOption long_options[] = {
56 /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */
57 { "help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0, },
58 { "session", 's', POPT_ARG_STRING, &opt_session_name, OPT_SESSION, 0, 0, },
59 { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0, },
60 { "userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0, },
61 { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_pid_string, OPT_PID, 0, 0, },
62 { "all", 'a', POPT_ARG_VAL, &opt_all, 1, 0, 0, },
63 { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, 0, 0, },
64 { 0, 0, 0, 0, 0, 0, 0, },
65};
66
ccf10263
MD
67static
68int parse_pid_string(const char *_pid_string,
69 int all, int **_pid_list, int *nr_pids)
70{
71 const char *one_pid_str;
72 char *iter;
73 int retval = CMD_SUCCESS;
74 int count = 0;
75 int *pid_list = NULL;
76 char *pid_string = NULL;
44c1a903 77 char *endptr;
ccf10263
MD
78
79 if (all && _pid_string) {
80 ERR("An empty PID string is expected with --all");
81 retval = CMD_ERROR;
82 goto error;
83 }
84 if (!all && !_pid_string) {
85 ERR("Please specify --all with an empty PID string");
86 retval = CMD_ERROR;
87 goto error;
88 }
89 if (all) {
03ea8167 90 pid_list = zmalloc(sizeof(*pid_list));
ccf10263
MD
91 if (!pid_list) {
92 ERR("Out of memory");
93 retval = CMD_ERROR;
94 goto error;
95 }
96 /* Empty PID string means all PIDs */
97 count = 1;
98 pid_list[0] = -1;
99 goto assign;
100 }
101
102 pid_string = strdup(_pid_string);
103 if (!pid_string) {
104 ERR("Out of memory");
105 retval = CMD_ERROR;
106 goto error;
107 }
108
109 /* Count */
110 one_pid_str = strtok_r(pid_string, ",", &iter);
111 while (one_pid_str != NULL) {
112 unsigned long v;
113
44c1a903
JR
114 errno = 0;
115 v = strtoul(one_pid_str, &endptr, 10);
ccf10263 116 if ((v == 0 && errno == EINVAL)
44c1a903
JR
117 || (v == ULONG_MAX && errno == ERANGE)
118 || (*one_pid_str != '\0' && *endptr != '\0')){
ccf10263
MD
119 ERR("Error parsing PID %s", one_pid_str);
120 retval = CMD_ERROR;
121 goto error;
122 }
44c1a903 123
ccf10263
MD
124 if ((long) v > INT_MAX || (int) v < 0) {
125 ERR("Invalid PID value %ld", (long) v);
126 retval = CMD_ERROR;
127 goto error;
128 }
129 count++;
130
131 /* For next loop */
132 one_pid_str = strtok_r(NULL, ",", &iter);
133 }
134
135 free(pid_string);
136 /* Identity of delimiter has been lost in first pass. */
137 pid_string = strdup(_pid_string);
138 if (!pid_string) {
139 ERR("Out of memory");
140 retval = CMD_ERROR;
141 goto error;
142 }
143
144 /* Allocate */
145 pid_list = zmalloc(count * sizeof(*pid_list));
146 if (!pid_list) {
147 ERR("Out of memory");
148 retval = CMD_ERROR;
149 goto error;
150 }
151
5cfbc08c 152 /* Reparse string and populate the pid list. */
ccf10263
MD
153 count = 0;
154 one_pid_str = strtok_r(pid_string, ",", &iter);
155 while (one_pid_str != NULL) {
156 unsigned long v;
157
158 v = strtoul(one_pid_str, NULL, 10);
159 pid_list[count++] = (int) v;
160
161 /* For next loop */
162 one_pid_str = strtok_r(NULL, ",", &iter);
163 }
164
165assign:
166 *nr_pids = count;
167 *_pid_list = pid_list;
168 goto end; /* SUCCESS */
169
170 /* ERROR */
171error:
172 free(pid_list);
173end:
174 free(pid_string);
175 return retval;
176}
177
178static
c51da673 179enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str,
ccf10263
MD
180 const char *session_name, const char *pid_string,
181 int all, struct mi_writer *writer)
182{
c51da673
JG
183 int ret, success = 1 , i;
184 enum cmd_error_code retval = CMD_SUCCESS;
ccf10263
MD
185 int *pid_list = NULL;
186 int nr_pids;
187 struct lttng_domain dom;
188 struct lttng_handle *handle = NULL;
669d25b6 189 int (*cmd_func)(struct lttng_handle *handle, int pid);
ccf10263
MD
190
191 switch (cmd_type) {
192 case CMD_TRACK:
669d25b6 193 cmd_func = lttng_track_pid;
ccf10263
MD
194 break;
195 case CMD_UNTRACK:
669d25b6 196 cmd_func = lttng_untrack_pid;
ccf10263
MD
197 break;
198 default:
199 ERR("Unknown command");
200 retval = CMD_ERROR;
201 goto end;
202 }
203
204 memset(&dom, 0, sizeof(dom));
205 if (opt_kernel) {
206 dom.type = LTTNG_DOMAIN_KERNEL;
207 } else if (opt_userspace) {
208 dom.type = LTTNG_DOMAIN_UST;
209 } else {
3ecec76a
PP
210 /* Checked by the caller. */
211 assert(0);
ccf10263
MD
212 }
213
214 ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids);
215 if (ret != CMD_SUCCESS) {
216 ERR("Error parsing PID string");
ccf10263
MD
217 retval = CMD_ERROR;
218 goto end;
219 }
220
221 handle = lttng_create_handle(session_name, &dom);
222 if (handle == NULL) {
223 retval = CMD_ERROR;
224 goto end;
225 }
226
227 if (writer) {
ebbf5ab7
JR
228 /* Open process element */
229 ret = mi_lttng_targets_open(writer);
ccf10263
MD
230 if (ret) {
231 retval = CMD_ERROR;
232 goto end;
233 }
234 }
235
ccf10263
MD
236 for (i = 0; i < nr_pids; i++) {
237 DBG("%s PID %d", cmd_str, pid_list[i]);
669d25b6 238 ret = cmd_func(handle, pid_list[i]);
ccf10263 239 if (ret) {
b93a4a13
MJ
240 switch (-ret) {
241 case LTTNG_ERR_PID_TRACKED:
242 WARN("PID %i already tracked in session %s",
243 pid_list[i], session_name);
244 success = 1;
245 retval = CMD_SUCCESS;
246 break;
247 case LTTNG_ERR_PID_NOT_TRACKED:
248 WARN("PID %i not tracked in session %s",
249 pid_list[i], session_name);
250 success = 1;
251 retval = CMD_SUCCESS;
252 break;
253 default:
254 ERR("%s", lttng_strerror(ret));
255 success = 0;
256 retval = CMD_ERROR;
257 break;
258 }
ebbf5ab7 259 } else {
b93a4a13
MJ
260 MSG("PID %i %sed in session %s",
261 pid_list[i], cmd_str, session_name);
ebbf5ab7
JR
262 success = 1;
263 }
264
265 /* Mi */
266 if (writer) {
267 ret = mi_lttng_pid_target(writer, pid_list[i], 1);
268 if (ret) {
269 retval = CMD_ERROR;
270 goto end;
271 }
272
273 ret = mi_lttng_writer_write_element_bool(writer,
274 mi_lttng_element_success, success);
275 if (ret) {
276 retval = CMD_ERROR;
277 goto end;
278 }
279
280 ret = mi_lttng_writer_close_element(writer);
281 if (ret) {
282 retval = CMD_ERROR;
283 goto end;
284 }
ccf10263
MD
285 }
286 }
287
288 if (writer) {
ebbf5ab7 289 /* Close targets element */
ccf10263
MD
290 ret = mi_lttng_writer_close_element(writer);
291 if (ret) {
292 retval = CMD_ERROR;
293 goto end;
294 }
295 }
296
ccf10263
MD
297end:
298 if (handle) {
299 lttng_destroy_handle(handle);
300 }
301 free(pid_list);
302 return retval;
303}
304
305static
306const char *get_mi_element_command(enum cmd_type cmd_type)
307{
308 switch (cmd_type) {
309 case CMD_TRACK:
310 return mi_lttng_element_command_track;
311 case CMD_UNTRACK:
312 return mi_lttng_element_command_untrack;
313 default:
314 return NULL;
315 }
316}
317
318/*
319 * Add/remove tracker to/from session.
320 */
321static
322int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str,
4fc83d94 323 int argc, const char **argv, const char *help_msg)
ccf10263 324{
c51da673
JG
325 int opt, ret = 0;
326 enum cmd_error_code command_ret = CMD_SUCCESS;
ccf10263
MD
327 int success = 1;
328 static poptContext pc;
329 char *session_name = NULL;
330 struct mi_writer *writer = NULL;
331
332 if (argc < 1) {
c51da673 333 command_ret = CMD_ERROR;
ccf10263
MD
334 goto end;
335 }
336
337 pc = poptGetContext(NULL, argc, argv, long_options, 0);
338 poptReadDefaultConfig(pc, 0);
339
340 while ((opt = poptGetNextOpt(pc)) != -1) {
341 switch (opt) {
342 case OPT_HELP:
4ba92f18 343 SHOW_HELP();
ccf10263
MD
344 goto end;
345 case OPT_LIST_OPTIONS:
346 list_cmd_options(stdout, long_options);
347 goto end;
348 case OPT_SESSION:
349 case OPT_PID:
350 opt_pid = 1;
351 break;
352 default:
c51da673 353 command_ret = CMD_UNDEFINED;
ccf10263
MD
354 goto end;
355 }
356 }
357
3ecec76a
PP
358 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
359 if (ret) {
360 ret = CMD_ERROR;
ccf10263
MD
361 goto end;
362 }
363
364 if (!opt_session_name) {
365 session_name = get_session_name();
366 if (session_name == NULL) {
c51da673 367 command_ret = CMD_ERROR;
ccf10263
MD
368 goto end;
369 }
370 } else {
371 session_name = opt_session_name;
372 }
373
374 /* Currently only PID tracker is supported */
375 if (!opt_pid) {
376 ERR("Please specify at least one tracker with its expected arguments");
c51da673 377 command_ret = CMD_ERROR;
ccf10263
MD
378 goto end;
379 }
380
381 /* Mi check */
382 if (lttng_opt_mi) {
383 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
384 if (!writer) {
c51da673 385 command_ret = CMD_ERROR;
ccf10263
MD
386 goto end;
387 }
388 }
389
390 if (writer) {
391 /* Open command element */
392 ret = mi_lttng_writer_command_open(writer,
393 get_mi_element_command(cmd_type));
394 if (ret) {
c51da673 395 command_ret = CMD_ERROR;
ccf10263
MD
396 goto end;
397 }
398
399 /* Open output element */
400 ret = mi_lttng_writer_open_element(writer,
401 mi_lttng_element_command_output);
402 if (ret) {
c51da673 403 command_ret = CMD_ERROR;
ccf10263
MD
404 goto end;
405 }
406 }
407
408 command_ret = track_untrack_pid(cmd_type,
409 cmd_str, session_name, opt_pid_string,
410 opt_all, writer);
c51da673 411 if (command_ret != CMD_SUCCESS) {
ccf10263
MD
412 success = 0;
413 }
414
415 /* Mi closing */
416 if (writer) {
417 /* Close output element */
418 ret = mi_lttng_writer_close_element(writer);
419 if (ret) {
c51da673 420 command_ret = CMD_ERROR;
ccf10263
MD
421 goto end;
422 }
423
424 /* Success ? */
425 ret = mi_lttng_writer_write_element_bool(writer,
426 mi_lttng_element_command_success, success);
427 if (ret) {
c51da673 428 command_ret = CMD_ERROR;
ccf10263
MD
429 goto end;
430 }
431
432 /* Command element close */
433 ret = mi_lttng_writer_command_close(writer);
434 if (ret) {
c51da673 435 command_ret = CMD_ERROR;
ccf10263
MD
436 goto end;
437 }
438 }
439
440end:
441 if (!opt_session_name) {
442 free(session_name);
443 }
444
445 /* Mi clean-up */
446 if (writer && mi_lttng_writer_destroy(writer)) {
447 /* Preserve original error code */
c51da673 448 command_ret = CMD_ERROR;
ccf10263
MD
449 }
450
ccf10263 451 poptFreeContext(pc);
c51da673 452 return (int) command_ret;
ccf10263
MD
453}
454
455int cmd_track(int argc, const char **argv)
456{
4fc83d94
PP
457 static const char *help_msg =
458#ifdef LTTNG_EMBED_HELP
459#include <lttng-track.1.h>
460#else
461 NULL
462#endif
463 ;
464
465 return cmd_track_untrack(CMD_TRACK, "track", argc, argv, help_msg);
ccf10263
MD
466}
467
468int cmd_untrack(int argc, const char **argv)
469{
4fc83d94
PP
470 static const char *help_msg =
471#ifdef LTTNG_EMBED_HELP
472#include <lttng-untrack.1.h>
473#else
474 NULL
475#endif
476 ;
477
478 return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv, help_msg);
ccf10263 479}
This page took 0.0637 seconds and 5 git commands to generate.