Run clang-format on the whole tree
[lttng-tools.git] / src / bin / lttng / commands / track-untrack.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
10 #define _LGPL_SOURCE
11 #include "../command.hpp"
12
13 #include <common/dynamic-array.hpp>
14 #include <common/dynamic-buffer.hpp>
15 #include <common/mi-lttng.hpp>
16 #include <common/optional.hpp>
17 #include <common/tracker.hpp>
18
19 #include <lttng/lttng.h>
20
21 #include <ctype.h>
22 #include <popt.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <urcu/list.h>
31
32 namespace {
33 struct process_attr_command_args {
34 enum lttng_process_attr process_attr;
35 /* Present in the user's command. */
36 bool requested;
37 bool all;
38 struct lttng_dynamic_pointer_array string_args;
39 };
40 } /* namespace */
41
42 enum cmd_type {
43 CMD_TRACK,
44 CMD_UNTRACK,
45 };
46
47 /* Offset OPT_ values by one since libpopt gives '0' a special meaning. */
48 enum {
49 OPT_PID = LTTNG_PROCESS_ATTR_PROCESS_ID + 1,
50 OPT_VPID = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID + 1,
51 OPT_UID = LTTNG_PROCESS_ATTR_USER_ID + 1,
52 OPT_VUID = LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID + 1,
53 OPT_GID = LTTNG_PROCESS_ATTR_GROUP_ID + 1,
54 OPT_VGID = LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1,
55 OPT_HELP,
56 OPT_LIST_OPTIONS,
57 OPT_SESSION,
58 OPT_ALL,
59 };
60
61 static char *opt_session_name;
62 static int opt_kernel;
63 static int opt_userspace;
64 static char *opt_str_arg;
65
66 static struct poptOption long_options[] = {
67 /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */
68 {
69 "help",
70 'h',
71 POPT_ARG_NONE,
72 0,
73 OPT_HELP,
74 0,
75 0,
76 },
77 {
78 "session",
79 's',
80 POPT_ARG_STRING,
81 &opt_session_name,
82 OPT_SESSION,
83 0,
84 0,
85 },
86 {
87 "kernel",
88 'k',
89 POPT_ARG_VAL,
90 &opt_kernel,
91 1,
92 0,
93 0,
94 },
95 {
96 "userspace",
97 'u',
98 POPT_ARG_VAL,
99 &opt_userspace,
100 1,
101 0,
102 0,
103 },
104 {
105 "pid",
106 'p',
107 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
108 &opt_str_arg,
109 OPT_PID,
110 0,
111 0,
112 },
113 {
114 "vpid",
115 0,
116 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
117 &opt_str_arg,
118 OPT_VPID,
119 0,
120 0,
121 },
122 {
123 "uid",
124 0,
125 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
126 &opt_str_arg,
127 OPT_UID,
128 0,
129 0,
130 },
131 {
132 "vuid",
133 0,
134 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
135 &opt_str_arg,
136 OPT_VUID,
137 0,
138 0,
139 },
140 {
141 "gid",
142 0,
143 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
144 &opt_str_arg,
145 OPT_GID,
146 0,
147 0,
148 },
149 {
150 "vgid",
151 0,
152 POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL,
153 &opt_str_arg,
154 OPT_VGID,
155 0,
156 0,
157 },
158 {
159 "all",
160 'a',
161 POPT_ARG_NONE,
162 0,
163 OPT_ALL,
164 0,
165 0,
166 },
167 {
168 "list-options",
169 0,
170 POPT_ARG_NONE,
171 NULL,
172 OPT_LIST_OPTIONS,
173 0,
174 0,
175 },
176 {
177 0,
178 0,
179 0,
180 0,
181 0,
182 0,
183 0,
184 },
185 };
186
187 static struct process_attr_command_args
188 process_attr_commands[LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1];
189
190 static void process_attr_command_init(struct process_attr_command_args *cmd,
191 enum lttng_process_attr process_attr)
192 {
193 cmd->process_attr = process_attr;
194 cmd->all = false;
195 lttng_dynamic_pointer_array_init(&cmd->string_args, free);
196 }
197
198 static void process_attr_command_fini(struct process_attr_command_args *cmd)
199 {
200 lttng_dynamic_pointer_array_reset(&cmd->string_args);
201 }
202
203 static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr)
204 {
205 switch (process_attr) {
206 case LTTNG_PROCESS_ATTR_PROCESS_ID:
207 return "Process ID";
208 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
209 return "Virtual process ID";
210 case LTTNG_PROCESS_ATTR_USER_ID:
211 return "User ID";
212 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
213 return "Virtual user ID";
214 case LTTNG_PROCESS_ATTR_GROUP_ID:
215 return "Group ID";
216 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
217 return "Virtual group ID";
218 default:
219 return "Unknown";
220 }
221 return NULL;
222 }
223
224 static bool ust_process_attr_supported(enum lttng_process_attr *process_attr)
225 {
226 bool supported;
227
228 switch (*process_attr) {
229 case LTTNG_PROCESS_ATTR_PROCESS_ID:
230 *process_attr = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
231 /* fall-through. */
232 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
233 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
234 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
235 supported = true;
236 break;
237 default:
238 ERR("The %s process attribute cannot be tracked in the user space domain.",
239 lttng_process_attr_to_string(*process_attr));
240 supported = false;
241 break;
242 }
243 return supported;
244 }
245
246 static const char *get_mi_element_command(enum cmd_type cmd_type)
247 {
248 switch (cmd_type) {
249 case CMD_TRACK:
250 return mi_lttng_element_command_track;
251 case CMD_UNTRACK:
252 return mi_lttng_element_command_untrack;
253 default:
254 abort();
255 }
256 }
257
258 static enum cmd_error_code run_command_all(enum cmd_type cmd_type,
259 const char *session_name,
260 enum lttng_domain_type domain_type,
261 enum lttng_process_attr process_attr,
262 struct mi_writer *writer)
263 {
264 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
265 const enum lttng_error_code handle_ret_code = lttng_session_get_tracker_handle(
266 session_name, domain_type, process_attr, &tracker_handle);
267 enum cmd_error_code cmd_ret = CMD_SUCCESS;
268 enum lttng_process_attr_tracker_handle_status status;
269
270 if (writer) {
271 const int ret = mi_lttng_all_process_attribute_value(writer, process_attr, true);
272 if (ret) {
273 cmd_ret = CMD_FATAL;
274 goto end;
275 }
276 }
277
278 if (handle_ret_code != LTTNG_OK) {
279 ERR("Session `%s` does not exist", session_name);
280 cmd_ret = CMD_FATAL;
281 goto end;
282 }
283
284 status = lttng_process_attr_tracker_handle_set_tracking_policy(
285 tracker_handle,
286 cmd_type == CMD_TRACK ? LTTNG_TRACKING_POLICY_INCLUDE_ALL :
287 LTTNG_TRACKING_POLICY_EXCLUDE_ALL);
288 switch (status) {
289 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
290 if (cmd_type == CMD_TRACK) {
291 MSG("%s tracking policy set to `include all`",
292 get_capitalized_process_attr_str(process_attr));
293 } else {
294 MSG("%s tracking policy set to `exclude all`",
295 get_capitalized_process_attr_str(process_attr));
296 }
297 break;
298 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
299 ERR("%s", lttng_strerror(-LTTNG_ERR_SESS_NOT_FOUND));
300 break;
301 default:
302 ERR("Unknown error encountered while setting tracking policy of %s tracker to `%s`",
303 lttng_process_attr_to_string(process_attr),
304 cmd_type == CMD_TRACK ? "include all" : "exclude all");
305 cmd_ret = CMD_FATAL;
306 break;
307 }
308 end:
309 if (writer) {
310 int ret = mi_lttng_writer_write_element_bool(
311 writer, mi_lttng_element_success, cmd_ret == CMD_SUCCESS);
312
313 if (ret) {
314 cmd_ret = CMD_FATAL;
315 } else {
316 ret = mi_lttng_writer_close_element(writer);
317 cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL;
318 }
319 }
320 lttng_process_attr_tracker_handle_destroy(tracker_handle);
321 return cmd_ret;
322 }
323
324 static enum cmd_error_code run_command_string(enum cmd_type cmd_type,
325 const char *session_name,
326 enum lttng_domain_type domain_type,
327 enum lttng_process_attr process_attr,
328 const char *_args,
329 struct mi_writer *writer)
330 {
331 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
332 const enum lttng_error_code handle_ret_code = lttng_session_get_tracker_handle(
333 session_name, domain_type, process_attr, &tracker_handle);
334 enum cmd_error_code cmd_ret = CMD_SUCCESS;
335 const char *one_value_str;
336 char *args = strdup(_args);
337 char *iter = args;
338 bool policy_set = false;
339
340 if (!args) {
341 ERR("%s", lttng_strerror(-LTTNG_ERR_NOMEM));
342 cmd_ret = CMD_FATAL;
343 goto end;
344 }
345
346 if (handle_ret_code != LTTNG_OK) {
347 ERR("%s", lttng_strerror(-handle_ret_code));
348 cmd_ret = CMD_FATAL;
349 goto end;
350 }
351
352 while ((one_value_str = strtok_r(iter, ",", &iter)) != NULL) {
353 const bool is_numerical_argument = isdigit(one_value_str[0]);
354 enum lttng_process_attr_tracker_handle_status status;
355 enum lttng_tracking_policy policy;
356 int ret;
357 char *prettified_arg;
358
359 if (!policy_set) {
360 status = lttng_process_attr_tracker_handle_get_tracking_policy(
361 tracker_handle, &policy);
362 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
363 break;
364 }
365
366 if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
367 status = lttng_process_attr_tracker_handle_set_tracking_policy(
368 tracker_handle, LTTNG_TRACKING_POLICY_INCLUDE_SET);
369 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
370 break;
371 }
372 }
373 policy_set = true;
374 }
375
376 if (is_numerical_argument) {
377 const unsigned long one_value_int = strtoul(one_value_str, NULL, 10);
378
379 if (writer) {
380 ret = mi_lttng_integral_process_attribute_value(
381 writer, process_attr, (int64_t) one_value_int, true);
382 if (ret) {
383 cmd_ret = CMD_FATAL;
384 goto end;
385 }
386 }
387
388 switch (process_attr) {
389 case LTTNG_PROCESS_ATTR_PROCESS_ID:
390 status = cmd_type == CMD_TRACK ?
391 lttng_process_attr_process_id_tracker_handle_add_pid(
392 tracker_handle, (pid_t) one_value_int) :
393 lttng_process_attr_process_id_tracker_handle_remove_pid(
394 tracker_handle, (pid_t) one_value_int);
395 break;
396 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
397 status = cmd_type == CMD_TRACK ?
398 lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
399 tracker_handle, (pid_t) one_value_int) :
400 lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
401 tracker_handle, (pid_t) one_value_int);
402 break;
403 case LTTNG_PROCESS_ATTR_USER_ID:
404 status = cmd_type == CMD_TRACK ?
405 lttng_process_attr_user_id_tracker_handle_add_uid(
406 tracker_handle, (uid_t) one_value_int) :
407 lttng_process_attr_user_id_tracker_handle_remove_uid(
408 tracker_handle, (uid_t) one_value_int);
409 break;
410 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
411 status = cmd_type == CMD_TRACK ?
412 lttng_process_attr_virtual_user_id_tracker_handle_add_uid(
413 tracker_handle, (uid_t) one_value_int) :
414 lttng_process_attr_virtual_user_id_tracker_handle_remove_uid(
415 tracker_handle, (uid_t) one_value_int);
416 break;
417 case LTTNG_PROCESS_ATTR_GROUP_ID:
418 status = cmd_type == CMD_TRACK ?
419 lttng_process_attr_group_id_tracker_handle_add_gid(
420 tracker_handle, (gid_t) one_value_int) :
421 lttng_process_attr_group_id_tracker_handle_remove_gid(
422 tracker_handle, (gid_t) one_value_int);
423 break;
424 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
425 status = cmd_type == CMD_TRACK ?
426 lttng_process_attr_virtual_group_id_tracker_handle_add_gid(
427 tracker_handle, (gid_t) one_value_int) :
428 lttng_process_attr_virtual_group_id_tracker_handle_remove_gid(
429 tracker_handle, (gid_t) one_value_int);
430 break;
431 default:
432 abort();
433 }
434
435 } else {
436 if (writer) {
437 ret = mi_lttng_string_process_attribute_value(
438 writer, process_attr, one_value_str, true);
439 if (ret) {
440 cmd_ret = CMD_FATAL;
441 goto end;
442 }
443 }
444
445 switch (process_attr) {
446 case LTTNG_PROCESS_ATTR_USER_ID:
447 status = cmd_type == CMD_TRACK ?
448 lttng_process_attr_user_id_tracker_handle_add_user_name(
449 tracker_handle, one_value_str) :
450 lttng_process_attr_user_id_tracker_handle_remove_user_name(
451 tracker_handle, one_value_str);
452 break;
453 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
454 status = cmd_type == CMD_TRACK ?
455 lttng_process_attr_virtual_user_id_tracker_handle_add_user_name(
456 tracker_handle, one_value_str) :
457 lttng_process_attr_virtual_user_id_tracker_handle_remove_user_name(
458 tracker_handle, one_value_str);
459 break;
460 case LTTNG_PROCESS_ATTR_GROUP_ID:
461 status = cmd_type == CMD_TRACK ?
462 lttng_process_attr_group_id_tracker_handle_add_group_name(
463 tracker_handle, one_value_str) :
464 lttng_process_attr_group_id_tracker_handle_remove_group_name(
465 tracker_handle, one_value_str);
466 break;
467 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
468 status = cmd_type == CMD_TRACK ?
469 lttng_process_attr_virtual_group_id_tracker_handle_add_group_name(
470 tracker_handle, one_value_str) :
471 lttng_process_attr_virtual_group_id_tracker_handle_remove_group_name(
472 tracker_handle, one_value_str);
473 break;
474 default:
475 ERR("%s is not a valid %s value; expected an integer",
476 one_value_str,
477 lttng_process_attr_to_string(process_attr));
478 cmd_ret = CMD_FATAL;
479 goto end;
480 }
481 }
482
483 ret = asprintf(
484 &prettified_arg, is_numerical_argument ? "%s" : "`%s`", one_value_str);
485 if (ret < 0) {
486 PERROR("Failed to format argument `%s`", one_value_str);
487 cmd_ret = CMD_FATAL;
488 goto end;
489 }
490
491 switch (status) {
492 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
493 if (cmd_type == CMD_TRACK) {
494 MSG("Added %s to the %s tracker inclusion set",
495 one_value_str,
496 lttng_process_attr_to_string(process_attr));
497 } else {
498 MSG("Removed %s from the %s tracker inclusion set",
499 one_value_str,
500 lttng_process_attr_to_string(process_attr));
501 }
502 break;
503 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
504 ERR("Session `%s` not found", session_name);
505 break;
506 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
507 WARN("%s is already in the %s inclusion set",
508 prettified_arg,
509 lttng_process_attr_to_string(process_attr));
510 break;
511 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
512 WARN("%s is not in the %s the inclusion set",
513 prettified_arg,
514 lttng_process_attr_to_string(process_attr));
515 break;
516 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND:
517 ERR("User %s was not found", prettified_arg);
518 cmd_ret = CMD_ERROR;
519 break;
520 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND:
521 ERR("Group %s was not found", prettified_arg);
522 cmd_ret = CMD_ERROR;
523 break;
524 default:
525 ERR("Unknown error encountered while %s %s %s %s tracker's inclusion set",
526 cmd_type == CMD_TRACK ? "adding" : "removing",
527 lttng_process_attr_to_string(process_attr),
528 prettified_arg,
529 cmd_type == CMD_TRACK ? "to" : "from");
530 cmd_ret = CMD_FATAL;
531 break;
532 }
533 free(prettified_arg);
534
535 if (writer) {
536 ret = mi_lttng_writer_write_element_bool(
537 writer, mi_lttng_element_success, cmd_ret == CMD_SUCCESS);
538
539 if (ret) {
540 cmd_ret = CMD_FATAL;
541 } else {
542 ret = mi_lttng_writer_close_element(writer);
543 cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL;
544 }
545 }
546 }
547 end:
548 free(args);
549 lttng_process_attr_tracker_handle_destroy(tracker_handle);
550 return cmd_ret;
551 }
552
553 static enum cmd_error_code run_command(enum cmd_type cmd_type,
554 const char *session_name,
555 const struct process_attr_command_args *command_args,
556 struct mi_writer *writer)
557 {
558 const enum lttng_domain_type domain_type = opt_kernel ? LTTNG_DOMAIN_KERNEL :
559 LTTNG_DOMAIN_UST;
560 enum cmd_error_code cmd_ret = CMD_SUCCESS;
561 unsigned int i;
562 const unsigned int string_arg_count =
563 lttng_dynamic_pointer_array_get_count(&command_args->string_args);
564 enum lttng_process_attr process_attr = command_args->process_attr;
565
566 if (opt_userspace) {
567 /*
568 * Check that this process attribute can be tracked
569 * in the user space domain. Backward-compatibility
570 * changes are be applied to process_attr as needed.
571 */
572 if (!ust_process_attr_supported(&process_attr)) {
573 cmd_ret = CMD_ERROR;
574 goto end;
575 }
576 }
577
578 if (writer) {
579 /* Open tracker and trackers elements */
580 const int ret = mi_lttng_process_attribute_tracker_open(writer, process_attr);
581 if (ret) {
582 cmd_ret = CMD_FATAL;
583 goto end;
584 }
585 }
586
587 if (command_args->all) {
588 cmd_ret =
589 run_command_all(cmd_type, session_name, domain_type, process_attr, writer);
590 } else {
591 bool error_occurred = false;
592
593 for (i = 0; i < string_arg_count; i++) {
594 const char *arg = (const char *) lttng_dynamic_pointer_array_get_pointer(
595 &command_args->string_args, i);
596
597 cmd_ret = run_command_string(
598 cmd_type, session_name, domain_type, process_attr, arg, writer);
599 if (cmd_ret != CMD_SUCCESS) {
600 error_occurred = true;
601 if (cmd_ret == CMD_FATAL) {
602 break;
603 }
604 goto end;
605 }
606 }
607 if (error_occurred) {
608 cmd_ret = CMD_ERROR;
609 }
610 }
611
612 if (writer) {
613 /* Close tracker and trackers elements */
614 const int ret = mi_lttng_close_multi_element(writer, 2);
615 if (ret) {
616 cmd_ret = CMD_FATAL;
617 goto end;
618 }
619 }
620 end:
621 return cmd_ret;
622 }
623
624 /*
625 * Add/remove tracker to/from session.
626 */
627 static int cmd_track_untrack(enum cmd_type cmd_type,
628 int argc,
629 const char **argv,
630 const char *help_msg __attribute__((unused)))
631 {
632 int opt, ret = 0;
633 bool sub_command_failed = false;
634 bool opt_all = false;
635 unsigned int selected_process_attr_tracker_count = 0;
636 const unsigned int command_count =
637 sizeof(process_attr_commands) / sizeof(struct process_attr_command_args);
638 enum cmd_error_code command_ret = CMD_SUCCESS;
639 static poptContext pc;
640 char *session_name = NULL;
641 const char *leftover = NULL;
642 struct mi_writer *writer = NULL;
643 size_t i;
644
645 for (i = 0; i < command_count; i++) {
646 process_attr_command_init(&process_attr_commands[i], (lttng_process_attr) i);
647 }
648
649 if (argc < 1) {
650 command_ret = CMD_ERROR;
651 goto end;
652 }
653
654 pc = poptGetContext(NULL, argc, argv, long_options, 0);
655 poptReadDefaultConfig(pc, 0);
656
657 while ((opt = poptGetNextOpt(pc)) != -1) {
658 switch (opt) {
659 case OPT_HELP:
660 SHOW_HELP();
661 goto end;
662 case OPT_LIST_OPTIONS:
663 list_cmd_options(stdout, long_options);
664 goto end;
665 case OPT_SESSION:
666 break;
667 case OPT_PID:
668 case OPT_VPID:
669 case OPT_UID:
670 case OPT_VUID:
671 case OPT_GID:
672 case OPT_VGID:
673 /* See OPT_ enum declaration comment. */
674 opt--;
675 selected_process_attr_tracker_count++;
676 process_attr_commands[opt].requested = true;
677 if (!opt_str_arg) {
678 continue;
679 }
680 ret = lttng_dynamic_pointer_array_add_pointer(
681 &process_attr_commands[opt].string_args, opt_str_arg);
682 if (ret) {
683 ERR("Allocation failed while parsing command arguments");
684 command_ret = CMD_ERROR;
685 goto end;
686 }
687 break;
688 case OPT_ALL:
689 opt_all = true;
690 break;
691 default:
692 command_ret = CMD_UNDEFINED;
693 goto end;
694 }
695 }
696
697 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace, false);
698 if (ret) {
699 command_ret = CMD_ERROR;
700 goto end;
701 }
702
703 if (selected_process_attr_tracker_count == 0) {
704 ERR("At least one process attribute must be specified");
705 command_ret = CMD_ERROR;
706 goto end;
707 }
708 if (opt_all) {
709 /*
710 * Only one process attribute tracker was specified; find it
711 * and set it in 'all' mode.
712 */
713 for (i = 0; i < command_count; i++) {
714 if (!process_attr_commands[i].requested) {
715 continue;
716 }
717 process_attr_commands[i].all = true;
718 if (lttng_dynamic_pointer_array_get_count(
719 &process_attr_commands[i].string_args)) {
720 ERR("The --all option cannot be used with a list of process attribute values");
721 command_ret = CMD_ERROR;
722 goto end;
723 }
724 }
725 } else {
726 for (i = 0; i < command_count; i++) {
727 if (!process_attr_commands[i].requested) {
728 continue;
729 }
730 if (lttng_dynamic_pointer_array_get_count(
731 &process_attr_commands[i].string_args) == 0) {
732 ERR("No process attribute value specified for %s tracker",
733 get_capitalized_process_attr_str(
734 process_attr_commands[i].process_attr));
735 command_ret = CMD_ERROR;
736 goto end;
737 }
738 }
739 }
740
741 if (!opt_session_name) {
742 session_name = get_session_name();
743 if (session_name == NULL) {
744 command_ret = CMD_ERROR;
745 goto end;
746 }
747 } else {
748 session_name = opt_session_name;
749 }
750
751 leftover = poptGetArg(pc);
752 if (leftover) {
753 ERR("Unknown argument: %s", leftover);
754 command_ret = CMD_ERROR;
755 goto end;
756 }
757
758 /* Mi check */
759 if (lttng_opt_mi) {
760 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
761 if (!writer) {
762 command_ret = CMD_ERROR;
763 goto end;
764 }
765 }
766
767 if (writer) {
768 /* Open command element */
769 ret = mi_lttng_writer_command_open(writer, get_mi_element_command(cmd_type));
770 if (ret) {
771 command_ret = CMD_ERROR;
772 goto end;
773 }
774
775 /* Open output element */
776 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output);
777 if (ret) {
778 command_ret = CMD_ERROR;
779 goto end;
780 }
781
782 ret = mi_lttng_trackers_open(writer);
783 if (ret) {
784 goto end;
785 }
786 }
787
788 /* Execute sub-commands. */
789 for (i = 0; i < command_count; i++) {
790 if (!process_attr_commands[i].requested) {
791 continue;
792 }
793 command_ret =
794 run_command(cmd_type, session_name, &process_attr_commands[i], writer);
795 if (command_ret != CMD_SUCCESS) {
796 sub_command_failed = true;
797 if (command_ret == CMD_FATAL) {
798 break;
799 }
800 }
801 }
802
803 /* Mi closing */
804 if (writer) {
805 /* Close trackers and output elements */
806 ret = mi_lttng_close_multi_element(writer, 2);
807 if (ret) {
808 command_ret = CMD_ERROR;
809 goto end;
810 }
811
812 /* Success ? */
813 ret = mi_lttng_writer_write_element_bool(
814 writer, mi_lttng_element_command_success, !sub_command_failed);
815 if (ret) {
816 command_ret = CMD_ERROR;
817 goto end;
818 }
819
820 /* Command element close */
821 ret = mi_lttng_writer_command_close(writer);
822 if (ret) {
823 command_ret = CMD_ERROR;
824 goto end;
825 }
826 }
827
828 end:
829 if (!opt_session_name) {
830 free(session_name);
831 }
832
833 /* Mi clean-up */
834 if (writer && mi_lttng_writer_destroy(writer)) {
835 /* Preserve original error code */
836 command_ret = CMD_ERROR;
837 }
838
839 for (i = 0; i < command_count; i++) {
840 process_attr_command_fini(&process_attr_commands[i]);
841 }
842
843 poptFreeContext(pc);
844 return (int) command_ret;
845 }
846
847 int cmd_track(int argc, const char **argv)
848 {
849 static const char *help_msg =
850 #ifdef LTTNG_EMBED_HELP
851 #include <lttng-track.1.h>
852 #else
853 NULL
854 #endif
855 ;
856
857 return cmd_track_untrack(CMD_TRACK, argc, argv, help_msg);
858 }
859
860 int cmd_untrack(int argc, const char **argv)
861 {
862 static const char *help_msg =
863 #ifdef LTTNG_EMBED_HELP
864 #include <lttng-untrack.1.h>
865 #else
866 NULL
867 #endif
868 ;
869
870 return cmd_track_untrack(CMD_UNTRACK, argc, argv, help_msg);
871 }
This page took 0.045842 seconds and 5 git commands to generate.