c4e52b78fef879d9edf902bf25e4dc63c50d28af
[lttng-tools.git] / src / bin / lttng / commands / list.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9 #include <stdint.h>
10 #define _LGPL_SOURCE
11 #include "../command.hpp"
12
13 #include <common/mi-lttng.hpp>
14 #include <common/time.hpp>
15 #include <common/tracker.hpp>
16
17 #include <lttng/domain-internal.hpp>
18 #include <lttng/lttng.h>
19
20 #include <inttypes.h>
21 #include <popt.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 static int opt_userspace;
27 static int opt_kernel;
28 static int opt_jul;
29 static int opt_log4j;
30 static int opt_python;
31 static char *opt_channel;
32 static int opt_domain;
33 static int opt_fields;
34 static int opt_syscall;
35
36 const char *indent4 = " ";
37 const char *indent6 = " ";
38 const char *indent8 = " ";
39
40 #ifdef LTTNG_EMBED_HELP
41 static const char help_msg[] =
42 #include <lttng-list.1.h>
43 ;
44 #endif
45
46 enum {
47 OPT_HELP = 1,
48 OPT_USERSPACE,
49 OPT_LIST_OPTIONS,
50 };
51
52 static struct lttng_handle *the_handle;
53 static struct mi_writer *the_writer;
54
55 /* Only set when listing a single session. */
56 static struct lttng_session the_listed_session;
57
58 static struct poptOption long_options[] = {
59 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
60 { "help", 'h', POPT_ARG_NONE, nullptr, OPT_HELP, nullptr, nullptr },
61 { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr },
62 { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr },
63 { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr },
64 { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr },
65 { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
66 { "channel", 'c', POPT_ARG_STRING, &opt_channel, 0, nullptr, nullptr },
67 { "domain", 'd', POPT_ARG_VAL, &opt_domain, 1, nullptr, nullptr },
68 { "fields", 'f', POPT_ARG_VAL, &opt_fields, 1, nullptr, nullptr },
69 { "syscall", 'S', POPT_ARG_VAL, &opt_syscall, 1, nullptr, nullptr },
70 { "list-options", 0, POPT_ARG_NONE, nullptr, OPT_LIST_OPTIONS, nullptr, nullptr },
71 { nullptr, 0, 0, nullptr, 0, nullptr, nullptr }
72 };
73
74 /*
75 * Get command line from /proc for a specific pid.
76 *
77 * On success, return an allocated string pointer to the proc cmdline.
78 * On error, return NULL.
79 */
80 static char *get_cmdline_by_pid(pid_t pid)
81 {
82 int ret;
83 FILE *fp = nullptr;
84 char *cmdline = nullptr;
85 /* Can't go bigger than /proc/LTTNG_MAX_PID/cmdline */
86 char path[sizeof("/proc//cmdline") + sizeof(LTTNG_MAX_PID_STR) - 1];
87
88 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
89 fp = fopen(path, "r");
90 if (fp == nullptr) {
91 goto end;
92 }
93
94 /* Caller must free() *cmdline */
95 cmdline = zmalloc<char>(PATH_MAX);
96 if (!cmdline) {
97 PERROR("malloc cmdline");
98 goto end;
99 }
100
101 ret = fread(cmdline, 1, PATH_MAX, fp);
102 if (ret < 0) {
103 PERROR("fread proc list");
104 }
105
106 end:
107 if (fp) {
108 fclose(fp);
109 }
110 return cmdline;
111 }
112
113 static const char *active_string(int value)
114 {
115 switch (value) {
116 case 0:
117 return "inactive";
118 case 1:
119 return "active";
120 case -1:
121 return "";
122 default:
123 return nullptr;
124 }
125 }
126
127 static const char *snapshot_string(int value)
128 {
129 switch (value) {
130 case 1:
131 return " snapshot";
132 default:
133 return "";
134 }
135 }
136
137 static const char *enabled_string(int value)
138 {
139 switch (value) {
140 case 0:
141 return " [disabled]";
142 case 1:
143 return " [enabled]";
144 case -1:
145 return "";
146 default:
147 return nullptr;
148 }
149 }
150
151 static const char *safe_string(const char *str)
152 {
153 return str ? str : "";
154 }
155
156 static const char *logleveltype_string(enum lttng_loglevel_type value)
157 {
158 switch (value) {
159 case LTTNG_EVENT_LOGLEVEL_ALL:
160 return ":";
161 case LTTNG_EVENT_LOGLEVEL_RANGE:
162 return " <=";
163 case LTTNG_EVENT_LOGLEVEL_SINGLE:
164 return " ==";
165 default:
166 return " <<TYPE UNKN>>";
167 }
168 }
169
170 static const char *bitness_event(enum lttng_event_flag flags)
171 {
172 if (flags & LTTNG_EVENT_FLAG_SYSCALL_32) {
173 if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
174 return " [32/64-bit]";
175 } else {
176 return " [32-bit]";
177 }
178 } else if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
179 return " [64-bit]";
180 } else {
181 return "";
182 }
183 }
184
185 /*
186 * Get exclusion names message for a single event.
187 *
188 * Returned pointer must be freed by caller. Returns NULL on error.
189 */
190 static char *get_exclusion_names_msg(struct lttng_event *event)
191 {
192 int ret;
193 int exclusion_count;
194 char *exclusion_msg = nullptr;
195 char *at;
196 size_t i;
197 const char *const exclusion_fmt = " [exclusions: ";
198 const size_t exclusion_fmt_len = strlen(exclusion_fmt);
199
200 exclusion_count = lttng_event_get_exclusion_name_count(event);
201 if (exclusion_count < 0) {
202 goto end;
203 } else if (exclusion_count == 0) {
204 /*
205 * No exclusions: return copy of empty string so that
206 * it can be freed by caller.
207 */
208 exclusion_msg = strdup("");
209 goto end;
210 }
211
212 /*
213 * exclusion_msg's size is bounded by the exclusion_fmt string,
214 * a comma per entry, the entry count (fixed-size), a closing
215 * bracket, and a trailing \0.
216 */
217 exclusion_msg = (char *) malloc(exclusion_count + exclusion_count * LTTNG_SYMBOL_NAME_LEN +
218 exclusion_fmt_len + 1);
219 if (!exclusion_msg) {
220 goto end;
221 }
222
223 at = strcpy(exclusion_msg, exclusion_fmt) + exclusion_fmt_len;
224 for (i = 0; i < exclusion_count; ++i) {
225 const char *name;
226
227 /* Append comma between exclusion names */
228 if (i > 0) {
229 *at = ',';
230 at++;
231 }
232
233 ret = lttng_event_get_exclusion_name(event, i, &name);
234 if (ret) {
235 /* Prints '?' on local error; should never happen */
236 *at = '?';
237 at++;
238 continue;
239 }
240
241 /* Append exclusion name */
242 at += sprintf(at, "%s", name);
243 }
244
245 /* This also puts a final '\0' at the end of exclusion_msg */
246 strcpy(at, "]");
247
248 end:
249 return exclusion_msg;
250 }
251
252 static void print_userspace_probe_location(struct lttng_event *event)
253 {
254 const struct lttng_userspace_probe_location *location;
255 const struct lttng_userspace_probe_location_lookup_method *lookup_method;
256 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
257
258 location = lttng_event_get_userspace_probe_location(event);
259 if (!location) {
260 MSG("Event has no userspace probe location");
261 return;
262 }
263
264 lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
265 if (!lookup_method) {
266 MSG("Event has no userspace probe location lookup method");
267 return;
268 }
269
270 MSG("%s%s (type: userspace-probe)%s", indent6, event->name, enabled_string(event->enabled));
271
272 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
273
274 switch (lttng_userspace_probe_location_get_type(location)) {
275 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
276 MSG("%sType: Unknown", indent8);
277 break;
278 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
279 {
280 const char *function_name;
281 char *binary_path;
282
283 MSG("%sType: Function", indent8);
284 function_name = lttng_userspace_probe_location_function_get_function_name(location);
285 binary_path = realpath(
286 lttng_userspace_probe_location_function_get_binary_path(location), nullptr);
287
288 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
289 MSG("%sFunction: %s()", indent8, function_name ? function_name : "NULL");
290 switch (lookup_type) {
291 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
292 MSG("%sLookup method: ELF", indent8);
293 break;
294 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
295 MSG("%sLookup method: default", indent8);
296 break;
297 default:
298 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
299 break;
300 }
301
302 free(binary_path);
303 break;
304 }
305 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
306 {
307 const char *probe_name, *provider_name;
308 char *binary_path;
309
310 MSG("%sType: Tracepoint", indent8);
311 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
312 provider_name =
313 lttng_userspace_probe_location_tracepoint_get_provider_name(location);
314 binary_path = realpath(
315 lttng_userspace_probe_location_tracepoint_get_binary_path(location),
316 nullptr);
317 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
318 MSG("%sTracepoint: %s:%s",
319 indent8,
320 provider_name ? provider_name : "NULL",
321 probe_name ? probe_name : "NULL");
322 switch (lookup_type) {
323 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
324 MSG("%sLookup method: SDT", indent8);
325 break;
326 default:
327 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
328 break;
329 }
330
331 free(binary_path);
332 break;
333 }
334 default:
335 ERR("Invalid probe type encountered");
336 }
337 }
338
339 /*
340 * Pretty print single event.
341 */
342 static void print_events(struct lttng_event *event)
343 {
344 int ret;
345 const char *filter_str;
346 char *filter_msg = nullptr;
347 char *exclusion_msg = nullptr;
348
349 ret = lttng_event_get_filter_expression(event, &filter_str);
350
351 if (ret) {
352 filter_msg = strdup(" [failed to retrieve filter]");
353 } else if (filter_str) {
354 if (asprintf(&filter_msg, " [filter: '%s']", filter_str) == -1) {
355 filter_msg = nullptr;
356 }
357 }
358
359 exclusion_msg = get_exclusion_names_msg(event);
360 if (!exclusion_msg) {
361 exclusion_msg = strdup(" [failed to retrieve exclusions]");
362 }
363
364 switch (event->type) {
365 case LTTNG_EVENT_TRACEPOINT:
366 {
367 if (event->loglevel != -1) {
368 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
369 indent6,
370 event->name,
371 logleveltype_string(event->loglevel_type),
372 mi_lttng_loglevel_string(event->loglevel, the_handle->domain.type),
373 event->loglevel,
374 enabled_string(event->enabled),
375 safe_string(exclusion_msg),
376 safe_string(filter_msg));
377 } else {
378 MSG("%s%s (type: tracepoint)%s%s%s",
379 indent6,
380 event->name,
381 enabled_string(event->enabled),
382 safe_string(exclusion_msg),
383 safe_string(filter_msg));
384 }
385 break;
386 }
387 case LTTNG_EVENT_FUNCTION:
388 MSG("%s%s (type: function)%s%s",
389 indent6,
390 event->name,
391 enabled_string(event->enabled),
392 safe_string(filter_msg));
393 if (event->attr.probe.addr != 0) {
394 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
395 } else {
396 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
397 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
398 }
399 break;
400 case LTTNG_EVENT_PROBE:
401 MSG("%s%s (type: probe)%s%s",
402 indent6,
403 event->name,
404 enabled_string(event->enabled),
405 safe_string(filter_msg));
406 if (event->attr.probe.addr != 0) {
407 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
408 } else {
409 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
410 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
411 }
412 break;
413 case LTTNG_EVENT_USERSPACE_PROBE:
414 print_userspace_probe_location(event);
415 break;
416 case LTTNG_EVENT_FUNCTION_ENTRY:
417 MSG("%s%s (type: function)%s%s",
418 indent6,
419 event->name,
420 enabled_string(event->enabled),
421 safe_string(filter_msg));
422 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
423 break;
424 case LTTNG_EVENT_SYSCALL:
425 MSG("%s%s%s%s%s%s",
426 indent6,
427 event->name,
428 (opt_syscall ? "" : " (type:syscall)"),
429 enabled_string(event->enabled),
430 bitness_event(event->flags),
431 safe_string(filter_msg));
432 break;
433 case LTTNG_EVENT_NOOP:
434 MSG("%s (type: noop)%s%s",
435 indent6,
436 enabled_string(event->enabled),
437 safe_string(filter_msg));
438 break;
439 case LTTNG_EVENT_ALL:
440 /* Fall-through. */
441 default:
442 /* We should never have "all" events in list. */
443 abort();
444 break;
445 }
446
447 free(filter_msg);
448 free(exclusion_msg);
449 }
450
451 static const char *field_type(struct lttng_event_field *field)
452 {
453 switch (field->type) {
454 case LTTNG_EVENT_FIELD_INTEGER:
455 return "integer";
456 case LTTNG_EVENT_FIELD_ENUM:
457 return "enum";
458 case LTTNG_EVENT_FIELD_FLOAT:
459 return "float";
460 case LTTNG_EVENT_FIELD_STRING:
461 return "string";
462 case LTTNG_EVENT_FIELD_OTHER:
463 default: /* fall-through */
464 return "unknown";
465 }
466 }
467
468 /*
469 * Pretty print single event fields.
470 */
471 static void print_event_field(struct lttng_event_field *field)
472 {
473 if (!field->field_name[0]) {
474 return;
475 }
476 MSG("%sfield: %s (%s)%s",
477 indent8,
478 field->field_name,
479 field_type(field),
480 field->nowrite ? " [no write]" : "");
481 }
482
483 /*
484 * Machine interface
485 * Jul and ust event listing
486 */
487 static int
488 mi_list_agent_ust_events(struct lttng_event *events, int count, struct lttng_domain *domain)
489 {
490 int ret, i;
491 pid_t cur_pid = 0;
492 char *cmdline = nullptr;
493 int pid_element_open = 0;
494
495 /* Open domains element */
496 ret = mi_lttng_domains_open(the_writer);
497 if (ret) {
498 goto end;
499 }
500
501 /* Write domain */
502 ret = mi_lttng_domain(the_writer, domain, 1);
503 if (ret) {
504 goto end;
505 }
506
507 /* Open pids element element */
508 ret = mi_lttng_pids_open(the_writer);
509 if (ret) {
510 goto end;
511 }
512
513 for (i = 0; i < count; i++) {
514 if (cur_pid != events[i].pid) {
515 if (pid_element_open) {
516 /* Close the previous events and pid element */
517 ret = mi_lttng_close_multi_element(the_writer, 2);
518 if (ret) {
519 goto end;
520 }
521 pid_element_open = 0;
522 }
523
524 cur_pid = events[i].pid;
525 cmdline = get_cmdline_by_pid(cur_pid);
526 if (!cmdline) {
527 ret = CMD_ERROR;
528 goto end;
529 }
530
531 if (!pid_element_open) {
532 /* Open and write a pid element */
533 ret = mi_lttng_pid(the_writer, cur_pid, cmdline, 1);
534 if (ret) {
535 goto error;
536 }
537
538 /* Open events element */
539 ret = mi_lttng_events_open(the_writer);
540 if (ret) {
541 goto error;
542 }
543
544 pid_element_open = 1;
545 }
546 free(cmdline);
547 }
548
549 /* Write an event */
550 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
551 if (ret) {
552 goto end;
553 }
554 }
555
556 /* Close pids */
557 ret = mi_lttng_writer_close_element(the_writer);
558 if (ret) {
559 goto end;
560 }
561
562 /* Close domain, domains */
563 ret = mi_lttng_close_multi_element(the_writer, 2);
564 end:
565 return ret;
566 error:
567 free(cmdline);
568 return ret;
569 }
570
571 static int list_agent_events()
572 {
573 int i, size, ret = CMD_SUCCESS;
574 struct lttng_domain domain;
575 struct lttng_handle *handle = nullptr;
576 struct lttng_event *event_list = nullptr;
577 pid_t cur_pid = 0;
578 char *cmdline = nullptr;
579 const char *agent_domain_str;
580
581 memset(&domain, 0, sizeof(domain));
582 if (opt_jul) {
583 domain.type = LTTNG_DOMAIN_JUL;
584 } else if (opt_log4j) {
585 domain.type = LTTNG_DOMAIN_LOG4J;
586 } else if (opt_python) {
587 domain.type = LTTNG_DOMAIN_PYTHON;
588 } else {
589 ERR("Invalid agent domain selected.");
590 ret = CMD_ERROR;
591 goto error;
592 }
593
594 agent_domain_str = lttng_domain_type_str(domain.type);
595
596 DBG("Getting %s tracing events", agent_domain_str);
597
598 handle = lttng_create_handle(nullptr, &domain);
599 if (handle == nullptr) {
600 ret = CMD_ERROR;
601 goto end;
602 }
603
604 size = lttng_list_tracepoints(handle, &event_list);
605 if (size < 0) {
606 ERR("Unable to list %s events: %s", agent_domain_str, lttng_strerror(size));
607 ret = CMD_ERROR;
608 goto end;
609 }
610
611 if (lttng_opt_mi) {
612 /* Mi print */
613 ret = mi_list_agent_ust_events(event_list, size, &domain);
614 if (ret) {
615 ret = CMD_ERROR;
616 goto error;
617 }
618 } else {
619 /* Pretty print */
620 MSG("%s events (Logger name):\n-------------------------", agent_domain_str);
621
622 if (size == 0) {
623 MSG("None");
624 }
625
626 for (i = 0; i < size; i++) {
627 if (cur_pid != event_list[i].pid) {
628 cur_pid = event_list[i].pid;
629 cmdline = get_cmdline_by_pid(cur_pid);
630 if (cmdline == nullptr) {
631 ret = CMD_ERROR;
632 goto error;
633 }
634 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
635 free(cmdline);
636 }
637 MSG("%s- %s", indent6, event_list[i].name);
638 }
639
640 MSG("");
641 }
642
643 error:
644 free(event_list);
645 end:
646 lttng_destroy_handle(handle);
647 return ret;
648 }
649
650 /*
651 * Ask session daemon for all user space tracepoints available.
652 */
653 static int list_ust_events()
654 {
655 int i, size, ret = CMD_SUCCESS;
656 struct lttng_domain domain;
657 struct lttng_handle *handle;
658 struct lttng_event *event_list = nullptr;
659 pid_t cur_pid = 0;
660 char *cmdline = nullptr;
661
662 memset(&domain, 0, sizeof(domain));
663
664 DBG("Getting UST tracing events");
665
666 domain.type = LTTNG_DOMAIN_UST;
667
668 handle = lttng_create_handle(nullptr, &domain);
669 if (handle == nullptr) {
670 ret = CMD_ERROR;
671 goto end;
672 }
673
674 size = lttng_list_tracepoints(handle, &event_list);
675 if (size < 0) {
676 ERR("Unable to list UST events: %s", lttng_strerror(size));
677 ret = CMD_ERROR;
678 goto error;
679 }
680
681 if (lttng_opt_mi) {
682 /* Mi print */
683 ret = mi_list_agent_ust_events(event_list, size, &domain);
684 } else {
685 /* Pretty print */
686 MSG("UST events:\n-------------");
687
688 if (size == 0) {
689 MSG("None");
690 }
691
692 for (i = 0; i < size; i++) {
693 if (cur_pid != event_list[i].pid) {
694 cur_pid = event_list[i].pid;
695 cmdline = get_cmdline_by_pid(cur_pid);
696 if (cmdline == nullptr) {
697 ret = CMD_ERROR;
698 goto error;
699 }
700 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
701 free(cmdline);
702 }
703 print_events(&event_list[i]);
704 }
705
706 MSG("");
707 }
708
709 error:
710 free(event_list);
711 end:
712 lttng_destroy_handle(handle);
713 return ret;
714 }
715
716 /*
717 * Machine interface
718 * List all ust event with their fields
719 */
720 static int
721 mi_list_ust_event_fields(struct lttng_event_field *fields, int count, struct lttng_domain *domain)
722 {
723 int ret, i;
724 pid_t cur_pid = 0;
725 char *cmdline = nullptr;
726 int pid_element_open = 0;
727 int event_element_open = 0;
728 struct lttng_event cur_event;
729
730 memset(&cur_event, 0, sizeof(cur_event));
731
732 /* Open domains element */
733 ret = mi_lttng_domains_open(the_writer);
734 if (ret) {
735 goto end;
736 }
737
738 /* Write domain */
739 ret = mi_lttng_domain(the_writer, domain, 1);
740 if (ret) {
741 goto end;
742 }
743
744 /* Open pids element */
745 ret = mi_lttng_pids_open(the_writer);
746 if (ret) {
747 goto end;
748 }
749
750 for (i = 0; i < count; i++) {
751 if (cur_pid != fields[i].event.pid) {
752 if (pid_element_open) {
753 if (event_element_open) {
754 /* Close the previous field element and event. */
755 ret = mi_lttng_close_multi_element(the_writer, 2);
756 if (ret) {
757 goto end;
758 }
759 event_element_open = 0;
760 }
761 /* Close the previous events, pid element */
762 ret = mi_lttng_close_multi_element(the_writer, 2);
763 if (ret) {
764 goto end;
765 }
766 pid_element_open = 0;
767 }
768
769 cur_pid = fields[i].event.pid;
770 cmdline = get_cmdline_by_pid(cur_pid);
771 if (!pid_element_open) {
772 /* Open and write a pid element */
773 ret = mi_lttng_pid(the_writer, cur_pid, cmdline, 1);
774 if (ret) {
775 goto error;
776 }
777
778 /* Open events element */
779 ret = mi_lttng_events_open(the_writer);
780 if (ret) {
781 goto error;
782 }
783 pid_element_open = 1;
784 }
785 free(cmdline);
786 /* Wipe current event since we are about to print a new PID. */
787 memset(&cur_event, 0, sizeof(cur_event));
788 }
789
790 if (strcmp(cur_event.name, fields[i].event.name) != 0) {
791 if (event_element_open) {
792 /* Close the previous fields element and the previous event */
793 ret = mi_lttng_close_multi_element(the_writer, 2);
794 if (ret) {
795 goto end;
796 }
797 event_element_open = 0;
798 }
799
800 memcpy(&cur_event, &fields[i].event, sizeof(cur_event));
801
802 if (!event_element_open) {
803 /* Open and write the event */
804 ret = mi_lttng_event(
805 the_writer, &cur_event, 1, the_handle->domain.type);
806 if (ret) {
807 goto end;
808 }
809
810 /* Open a fields element */
811 ret = mi_lttng_event_fields_open(the_writer);
812 if (ret) {
813 goto end;
814 }
815 event_element_open = 1;
816 }
817 }
818
819 /* Print the event_field */
820 ret = mi_lttng_event_field(the_writer, &fields[i]);
821 if (ret) {
822 goto end;
823 }
824 }
825
826 /* Close pids, domain, domains */
827 ret = mi_lttng_close_multi_element(the_writer, 3);
828 end:
829 return ret;
830 error:
831 free(cmdline);
832 return ret;
833 }
834
835 /*
836 * Ask session daemon for all user space tracepoint fields available.
837 */
838 static int list_ust_event_fields()
839 {
840 int i, size, ret = CMD_SUCCESS;
841 struct lttng_domain domain;
842 struct lttng_handle *handle;
843 struct lttng_event_field *event_field_list;
844 pid_t cur_pid = 0;
845 char *cmdline = nullptr;
846
847 struct lttng_event cur_event;
848
849 memset(&domain, 0, sizeof(domain));
850 memset(&cur_event, 0, sizeof(cur_event));
851
852 DBG("Getting UST tracing event fields");
853
854 domain.type = LTTNG_DOMAIN_UST;
855
856 handle = lttng_create_handle(nullptr, &domain);
857 if (handle == nullptr) {
858 ret = CMD_ERROR;
859 goto end;
860 }
861
862 size = lttng_list_tracepoint_fields(handle, &event_field_list);
863 if (size < 0) {
864 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
865 ret = CMD_ERROR;
866 goto end;
867 }
868
869 if (lttng_opt_mi) {
870 /* Mi print */
871 ret = mi_list_ust_event_fields(event_field_list, size, &domain);
872 if (ret) {
873 ret = CMD_ERROR;
874 goto error;
875 }
876 } else {
877 /* Pretty print */
878 MSG("UST events:\n-------------");
879
880 if (size == 0) {
881 MSG("None");
882 }
883
884 for (i = 0; i < size; i++) {
885 if (cur_pid != event_field_list[i].event.pid) {
886 cur_pid = event_field_list[i].event.pid;
887 cmdline = get_cmdline_by_pid(cur_pid);
888 if (cmdline == nullptr) {
889 ret = CMD_ERROR;
890 goto error;
891 }
892 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
893 free(cmdline);
894 /* Wipe current event since we are about to print a new PID. */
895 memset(&cur_event, 0, sizeof(cur_event));
896 }
897 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
898 print_events(&event_field_list[i].event);
899 memcpy(&cur_event, &event_field_list[i].event, sizeof(cur_event));
900 }
901 print_event_field(&event_field_list[i]);
902 }
903
904 MSG("");
905 }
906
907 error:
908 free(event_field_list);
909 end:
910 lttng_destroy_handle(handle);
911 return ret;
912 }
913
914 /*
915 * Machine interface
916 * Print a list of kernel events
917 */
918 static int mi_list_kernel_events(struct lttng_event *events, int count, struct lttng_domain *domain)
919 {
920 int ret, i;
921
922 /* Open domains element */
923 ret = mi_lttng_domains_open(the_writer);
924 if (ret) {
925 goto end;
926 }
927
928 /* Write domain */
929 ret = mi_lttng_domain(the_writer, domain, 1);
930 if (ret) {
931 goto end;
932 }
933
934 /* Open events */
935 ret = mi_lttng_events_open(the_writer);
936 if (ret) {
937 goto end;
938 }
939
940 for (i = 0; i < count; i++) {
941 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
942 if (ret) {
943 goto end;
944 }
945 }
946
947 /* close events, domain and domains */
948 ret = mi_lttng_close_multi_element(the_writer, 3);
949 if (ret) {
950 goto end;
951 }
952
953 end:
954 return ret;
955 }
956
957 /*
958 * Ask for all trace events in the kernel
959 */
960 static int list_kernel_events()
961 {
962 int i, size, ret = CMD_SUCCESS;
963 struct lttng_domain domain;
964 struct lttng_handle *handle;
965 struct lttng_event *event_list;
966
967 memset(&domain, 0, sizeof(domain));
968
969 DBG("Getting kernel tracing events");
970
971 domain.type = LTTNG_DOMAIN_KERNEL;
972
973 handle = lttng_create_handle(nullptr, &domain);
974 if (handle == nullptr) {
975 ret = CMD_ERROR;
976 goto error;
977 }
978
979 size = lttng_list_tracepoints(handle, &event_list);
980 if (size < 0) {
981 ERR("Unable to list kernel events: %s", lttng_strerror(size));
982 lttng_destroy_handle(handle);
983 return CMD_ERROR;
984 }
985
986 if (lttng_opt_mi) {
987 /* Mi print */
988 ret = mi_list_kernel_events(event_list, size, &domain);
989 if (ret) {
990 ret = CMD_ERROR;
991 goto end;
992 }
993 } else {
994 MSG("Kernel events:\n-------------");
995
996 for (i = 0; i < size; i++) {
997 print_events(&event_list[i]);
998 }
999
1000 MSG("");
1001 }
1002
1003 end:
1004 free(event_list);
1005
1006 lttng_destroy_handle(handle);
1007 return ret;
1008
1009 error:
1010 lttng_destroy_handle(handle);
1011 return ret;
1012 }
1013
1014 /*
1015 * Machine interface
1016 * Print a list of system calls.
1017 */
1018 static int mi_list_syscalls(struct lttng_event *events, int count)
1019 {
1020 int ret, i;
1021
1022 /* Open events */
1023 ret = mi_lttng_events_open(the_writer);
1024 if (ret) {
1025 goto end;
1026 }
1027
1028 for (i = 0; i < count; i++) {
1029 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
1030 if (ret) {
1031 goto end;
1032 }
1033 }
1034
1035 /* Close events. */
1036 ret = mi_lttng_writer_close_element(the_writer);
1037 if (ret) {
1038 goto end;
1039 }
1040
1041 end:
1042 return ret;
1043 }
1044
1045 /*
1046 * Ask for kernel system calls.
1047 */
1048 static int list_syscalls()
1049 {
1050 int i, size, ret = CMD_SUCCESS;
1051 struct lttng_event *event_list;
1052
1053 DBG("Getting kernel system call events");
1054
1055 size = lttng_list_syscalls(&event_list);
1056 if (size < 0) {
1057 ERR("Unable to list system calls: %s", lttng_strerror(size));
1058 ret = CMD_ERROR;
1059 goto error;
1060 }
1061
1062 if (lttng_opt_mi) {
1063 /* Mi print */
1064 ret = mi_list_syscalls(event_list, size);
1065 if (ret) {
1066 ret = CMD_ERROR;
1067 goto end;
1068 }
1069 } else {
1070 MSG("System calls:\n-------------");
1071
1072 for (i = 0; i < size; i++) {
1073 print_events(&event_list[i]);
1074 }
1075
1076 MSG("");
1077 }
1078
1079 end:
1080 free(event_list);
1081 return ret;
1082
1083 error:
1084 return ret;
1085 }
1086
1087 /*
1088 * Machine Interface
1089 * Print a list of agent events
1090 */
1091 static int mi_list_session_agent_events(struct lttng_event *events, int count)
1092 {
1093 int ret, i;
1094
1095 /* Open events element */
1096 ret = mi_lttng_events_open(the_writer);
1097 if (ret) {
1098 goto end;
1099 }
1100
1101 for (i = 0; i < count; i++) {
1102 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
1103 if (ret) {
1104 goto end;
1105 }
1106 }
1107
1108 /* Close events element */
1109 ret = mi_lttng_writer_close_element(the_writer);
1110
1111 end:
1112 return ret;
1113 }
1114
1115 /*
1116 * List agent events for a specific session using the handle.
1117 *
1118 * Return CMD_SUCCESS on success else a negative value.
1119 */
1120 static int list_session_agent_events()
1121 {
1122 int ret = CMD_SUCCESS, count, i;
1123 struct lttng_event *events = nullptr;
1124
1125 count = lttng_list_events(the_handle, "", &events);
1126 if (count < 0) {
1127 ret = CMD_ERROR;
1128 ERR("%s", lttng_strerror(count));
1129 goto error;
1130 }
1131
1132 if (lttng_opt_mi) {
1133 /* Mi print */
1134 ret = mi_list_session_agent_events(events, count);
1135 if (ret) {
1136 ret = CMD_ERROR;
1137 goto end;
1138 }
1139 } else {
1140 /* Pretty print */
1141 MSG("Events (Logger name):\n---------------------");
1142 if (count == 0) {
1143 MSG("%sNone\n", indent6);
1144 goto end;
1145 }
1146
1147 for (i = 0; i < count; i++) {
1148 const char *filter_str;
1149 char *filter_msg = nullptr;
1150 struct lttng_event *event = &events[i];
1151
1152 ret = lttng_event_get_filter_expression(event, &filter_str);
1153 if (ret) {
1154 filter_msg = strdup(" [failed to retrieve filter]");
1155 } else if (filter_str) {
1156 if (asprintf(&filter_msg, " [filter: '%s']", filter_str) == -1) {
1157 filter_msg = nullptr;
1158 }
1159 }
1160
1161 if (event->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
1162 MSG("%s- %s%s (loglevel%s %s)%s",
1163 indent4,
1164 event->name,
1165 enabled_string(event->enabled),
1166 logleveltype_string(event->loglevel_type),
1167 mi_lttng_loglevel_string(event->loglevel,
1168 the_handle->domain.type),
1169 safe_string(filter_msg));
1170 } else {
1171 MSG("%s- %s%s%s",
1172 indent4,
1173 event->name,
1174 enabled_string(event->enabled),
1175 safe_string(filter_msg));
1176 }
1177 free(filter_msg);
1178 }
1179
1180 MSG("");
1181 }
1182
1183 end:
1184 free(events);
1185 error:
1186 return ret;
1187 }
1188
1189 /*
1190 * Machine interface
1191 * print a list of event
1192 */
1193 static int mi_list_events(struct lttng_event *events, int count)
1194 {
1195 int ret, i;
1196
1197 /* Open events element */
1198 ret = mi_lttng_events_open(the_writer);
1199 if (ret) {
1200 goto end;
1201 }
1202
1203 for (i = 0; i < count; i++) {
1204 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
1205 if (ret) {
1206 goto end;
1207 }
1208 }
1209
1210 /* Close events element */
1211 ret = mi_lttng_writer_close_element(the_writer);
1212
1213 end:
1214 return ret;
1215 }
1216
1217 /*
1218 * List events of channel of session and domain.
1219 */
1220 static int list_events(const char *channel_name)
1221 {
1222 int ret = CMD_SUCCESS, count, i;
1223 struct lttng_event *events = nullptr;
1224
1225 count = lttng_list_events(the_handle, channel_name, &events);
1226 if (count < 0) {
1227 ret = CMD_ERROR;
1228 ERR("%s", lttng_strerror(count));
1229 goto error;
1230 }
1231
1232 if (lttng_opt_mi) {
1233 /* Mi print */
1234 ret = mi_list_events(events, count);
1235 if (ret) {
1236 ret = CMD_ERROR;
1237 goto end;
1238 }
1239 } else {
1240 /* Pretty print */
1241 MSG("\n%sRecording event rules:", indent4);
1242 if (count == 0) {
1243 MSG("%sNone\n", indent6);
1244 goto end;
1245 }
1246
1247 for (i = 0; i < count; i++) {
1248 print_events(&events[i]);
1249 }
1250
1251 MSG("");
1252 }
1253 end:
1254 free(events);
1255 error:
1256 return ret;
1257 }
1258
1259 static void print_timer(const char *timer_name, uint32_t space_count, int64_t value)
1260 {
1261 uint32_t i;
1262
1263 _MSG("%s%s:", indent6, timer_name);
1264 for (i = 0; i < space_count; i++) {
1265 _MSG(" ");
1266 }
1267
1268 if (value) {
1269 MSG("%" PRId64 " %s", value, USEC_UNIT);
1270 } else {
1271 MSG("inactive");
1272 }
1273 }
1274
1275 /*
1276 * Pretty print channel
1277 */
1278 static void print_channel(struct lttng_channel *channel)
1279 {
1280 int ret;
1281 uint64_t discarded_events, lost_packets, monitor_timer_interval;
1282 int64_t blocking_timeout;
1283
1284 ret = lttng_channel_get_discarded_event_count(channel, &discarded_events);
1285 if (ret) {
1286 ERR("Failed to retrieve discarded event count of channel");
1287 return;
1288 }
1289
1290 ret = lttng_channel_get_lost_packet_count(channel, &lost_packets);
1291 if (ret) {
1292 ERR("Failed to retrieve lost packet count of channel");
1293 return;
1294 }
1295
1296 ret = lttng_channel_get_monitor_timer_interval(channel, &monitor_timer_interval);
1297 if (ret) {
1298 ERR("Failed to retrieve monitor interval of channel");
1299 return;
1300 }
1301
1302 ret = lttng_channel_get_blocking_timeout(channel, &blocking_timeout);
1303 if (ret) {
1304 ERR("Failed to retrieve blocking timeout of channel");
1305 return;
1306 }
1307
1308 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
1309 MSG("%sAttributes:", indent4);
1310 MSG("%sEvent-loss mode: %s", indent6, channel->attr.overwrite ? "overwrite" : "discard");
1311 MSG("%sSub-buffer size: %" PRIu64 " bytes", indent6, channel->attr.subbuf_size);
1312 MSG("%sSub-buffer count: %" PRIu64, indent6, channel->attr.num_subbuf);
1313
1314 print_timer("Switch timer", 5, channel->attr.switch_timer_interval);
1315 print_timer("Read timer", 7, channel->attr.read_timer_interval);
1316 print_timer("Monitor timer", 4, monitor_timer_interval);
1317
1318 if (!channel->attr.overwrite) {
1319 if (blocking_timeout == -1) {
1320 MSG("%sBlocking timeout: infinite", indent6);
1321 } else {
1322 MSG("%sBlocking timeout: %" PRId64 " %s",
1323 indent6,
1324 blocking_timeout,
1325 USEC_UNIT);
1326 }
1327 }
1328
1329 MSG("%sTrace file count: %" PRIu64 " per stream",
1330 indent6,
1331 channel->attr.tracefile_count == 0 ? 1 : channel->attr.tracefile_count);
1332 if (channel->attr.tracefile_size != 0) {
1333 MSG("%sTrace file size: %" PRIu64 " bytes", indent6, channel->attr.tracefile_size);
1334 } else {
1335 MSG("%sTrace file size: %s", indent6, "unlimited");
1336 }
1337 switch (channel->attr.output) {
1338 case LTTNG_EVENT_SPLICE:
1339 MSG("%sOutput mode: splice", indent6);
1340 break;
1341 case LTTNG_EVENT_MMAP:
1342 MSG("%sOutput mode: mmap", indent6);
1343 break;
1344 }
1345
1346 MSG("\n%sStatistics:", indent4);
1347 if (the_listed_session.snapshot_mode) {
1348 /*
1349 * The lost packet count is omitted for sessions in snapshot
1350 * mode as it is misleading: it would indicate the number of
1351 * packets that the consumer could not extract during the
1352 * course of recording the snapshot. It does not have the
1353 * same meaning as the "regular" lost packet count that
1354 * would result from the consumer not keeping up with
1355 * event production in an overwrite-mode channel.
1356 *
1357 * A more interesting statistic would be the number of
1358 * packets lost between the first and last extracted
1359 * packets of a given snapshot (which prevents most analyses).
1360 */
1361 MSG("%sNone", indent6);
1362 goto skip_stats_printing;
1363 }
1364
1365 if (!channel->attr.overwrite) {
1366 MSG("%sDiscarded events: %" PRIu64, indent6, discarded_events);
1367 } else {
1368 MSG("%sLost packets: %" PRIu64, indent6, lost_packets);
1369 }
1370 skip_stats_printing:
1371 return;
1372 }
1373
1374 /*
1375 * Machine interface
1376 * Print a list of channel
1377 *
1378 */
1379 static int mi_list_channels(struct lttng_channel *channels, int count, const char *channel_name)
1380 {
1381 int i, ret;
1382 unsigned int chan_found = 0;
1383
1384 /* Open channels element */
1385 ret = mi_lttng_channels_open(the_writer);
1386 if (ret) {
1387 goto error;
1388 }
1389
1390 for (i = 0; i < count; i++) {
1391 if (channel_name != nullptr) {
1392 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1393 chan_found = 1;
1394 } else {
1395 continue;
1396 }
1397 }
1398
1399 /* Write channel element and leave it open */
1400 ret = mi_lttng_channel(the_writer, &channels[i], 1);
1401 if (ret) {
1402 goto error;
1403 }
1404
1405 /* Listing events per channel */
1406 ret = list_events(channels[i].name);
1407 if (ret) {
1408 goto error;
1409 }
1410
1411 /* Closing the channel element we opened earlier */
1412 ret = mi_lttng_writer_close_element(the_writer);
1413 if (ret) {
1414 goto error;
1415 }
1416
1417 if (chan_found) {
1418 break;
1419 }
1420 }
1421
1422 /* Close channels element */
1423 ret = mi_lttng_writer_close_element(the_writer);
1424 if (ret) {
1425 goto error;
1426 }
1427
1428 error:
1429 return ret;
1430 }
1431
1432 /*
1433 * List channel(s) of session and domain.
1434 *
1435 * If channel_name is NULL, all channels are listed.
1436 */
1437 static int list_channels(const char *channel_name)
1438 {
1439 int count, i, ret = CMD_SUCCESS;
1440 unsigned int chan_found = 0;
1441 struct lttng_channel *channels = nullptr;
1442
1443 DBG("Listing channel(s) (%s)", channel_name ?: "<all>");
1444
1445 count = lttng_list_channels(the_handle, &channels);
1446 if (count < 0) {
1447 switch (-count) {
1448 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
1449 if (lttng_opt_mi) {
1450 /* When printing mi this is not an error
1451 * but an empty channels element */
1452 count = 0;
1453 } else {
1454 ret = CMD_SUCCESS;
1455 goto error_channels;
1456 }
1457 break;
1458 default:
1459 /* We had a real error */
1460 ret = CMD_ERROR;
1461 ERR("%s", lttng_strerror(count));
1462 goto error_channels;
1463 break;
1464 }
1465 }
1466
1467 if (lttng_opt_mi) {
1468 /* Mi print */
1469 ret = mi_list_channels(channels, count, channel_name);
1470 if (ret) {
1471 ret = CMD_ERROR;
1472 goto error;
1473 }
1474 } else {
1475 /* Pretty print */
1476 if (count) {
1477 MSG("Channels:\n-------------");
1478 }
1479
1480 for (i = 0; i < count; i++) {
1481 if (channel_name != nullptr) {
1482 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1483 chan_found = 1;
1484 } else {
1485 continue;
1486 }
1487 }
1488 print_channel(&channels[i]);
1489
1490 /* Listing events per channel */
1491 ret = list_events(channels[i].name);
1492 if (ret) {
1493 goto error;
1494 }
1495
1496 if (chan_found) {
1497 break;
1498 }
1499 }
1500
1501 if (!chan_found && channel_name != nullptr) {
1502 ret = CMD_ERROR;
1503 ERR("Channel %s not found", channel_name);
1504 goto error;
1505 }
1506 }
1507 error:
1508 free(channels);
1509
1510 error_channels:
1511 return ret;
1512 }
1513
1514 static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr)
1515 {
1516 switch (process_attr) {
1517 case LTTNG_PROCESS_ATTR_PROCESS_ID:
1518 return "Process ID";
1519 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
1520 return "Virtual process ID";
1521 case LTTNG_PROCESS_ATTR_USER_ID:
1522 return "User ID";
1523 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
1524 return "Virtual user ID";
1525 case LTTNG_PROCESS_ATTR_GROUP_ID:
1526 return "Group ID";
1527 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
1528 return "Virtual group ID";
1529 default:
1530 return "Unknown";
1531 }
1532 return nullptr;
1533 }
1534
1535 static int handle_process_attr_status(enum lttng_process_attr process_attr,
1536 enum lttng_process_attr_tracker_handle_status status)
1537 {
1538 int ret = CMD_SUCCESS;
1539
1540 switch (status) {
1541 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
1542 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
1543 /* Carry on. */
1544 break;
1545 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
1546 ERR("Communication occurred while fetching %s tracker",
1547 lttng_process_attr_to_string(process_attr));
1548 ret = CMD_ERROR;
1549 break;
1550 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
1551 ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists",
1552 lttng_process_attr_to_string(process_attr),
1553 the_handle->session_name);
1554 ret = CMD_ERROR;
1555 break;
1556 default:
1557 ERR("Unknown error occurred while fetching the inclusion set of the %s tracker",
1558 lttng_process_attr_to_string(process_attr));
1559 ret = CMD_ERROR;
1560 break;
1561 }
1562
1563 return ret;
1564 }
1565
1566 static int mi_output_empty_tracker(enum lttng_process_attr process_attr)
1567 {
1568 int ret;
1569
1570 ret = mi_lttng_process_attribute_tracker_open(the_writer, process_attr);
1571 if (ret) {
1572 goto end;
1573 }
1574
1575 ret = mi_lttng_close_multi_element(the_writer, 2);
1576 end:
1577 return ret;
1578 }
1579
1580 static inline bool is_value_type_name(enum lttng_process_attr_value_type value_type)
1581 {
1582 return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ||
1583 value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME;
1584 }
1585
1586 /*
1587 * List a process attribute tracker for a session and domain tuple.
1588 */
1589 static int list_process_attr_tracker(enum lttng_process_attr process_attr)
1590 {
1591 int ret = 0;
1592 unsigned int count, i;
1593 enum lttng_tracking_policy policy;
1594 enum lttng_error_code ret_code;
1595 enum lttng_process_attr_tracker_handle_status handle_status;
1596 enum lttng_process_attr_values_status values_status;
1597 const struct lttng_process_attr_values *values;
1598 struct lttng_process_attr_tracker_handle *tracker_handle = nullptr;
1599
1600 ret_code = lttng_session_get_tracker_handle(
1601 the_handle->session_name, the_handle->domain.type, process_attr, &tracker_handle);
1602 if (ret_code != LTTNG_OK) {
1603 ERR("Failed to get process attribute tracker handle: %s", lttng_strerror(ret_code));
1604 ret = CMD_ERROR;
1605 goto end;
1606 }
1607
1608 handle_status =
1609 lttng_process_attr_tracker_handle_get_inclusion_set(tracker_handle, &values);
1610 ret = handle_process_attr_status(process_attr, handle_status);
1611 if (ret != CMD_SUCCESS) {
1612 goto end;
1613 }
1614
1615 handle_status =
1616 lttng_process_attr_tracker_handle_get_tracking_policy(tracker_handle, &policy);
1617 ret = handle_process_attr_status(process_attr, handle_status);
1618 if (ret != CMD_SUCCESS) {
1619 goto end;
1620 }
1621
1622 {
1623 char *process_attr_name;
1624 const int print_ret = asprintf(
1625 &process_attr_name, "%ss:", get_capitalized_process_attr_str(process_attr));
1626
1627 if (print_ret == -1) {
1628 ret = CMD_FATAL;
1629 goto end;
1630 }
1631 _MSG(" %-22s", process_attr_name);
1632 free(process_attr_name);
1633 }
1634 switch (policy) {
1635 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
1636 break;
1637 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
1638 if (the_writer) {
1639 mi_output_empty_tracker(process_attr);
1640 }
1641 MSG("none");
1642 ret = CMD_SUCCESS;
1643 goto end;
1644 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
1645 MSG("all");
1646 ret = CMD_SUCCESS;
1647 goto end;
1648 default:
1649 ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`",
1650 lttng_process_attr_to_string(process_attr),
1651 the_handle->session_name);
1652 ret = CMD_FATAL;
1653 goto end;
1654 }
1655
1656 values_status = lttng_process_attr_values_get_count(values, &count);
1657 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1658 ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`",
1659 lttng_process_attr_to_string(process_attr),
1660 the_handle->session_name);
1661 ret = CMD_FATAL;
1662 goto end;
1663 }
1664
1665 if (count == 0) {
1666 /* Functionally equivalent to the 'exclude all' policy. */
1667 if (the_writer) {
1668 mi_output_empty_tracker(process_attr);
1669 }
1670 MSG("none");
1671 ret = CMD_SUCCESS;
1672 goto end;
1673 }
1674
1675 /* Mi tracker_id element */
1676 if (the_writer) {
1677 /* Open tracker_id and targets elements */
1678 ret = mi_lttng_process_attribute_tracker_open(the_writer, process_attr);
1679 if (ret) {
1680 goto end;
1681 }
1682 }
1683
1684 for (i = 0; i < count; i++) {
1685 const enum lttng_process_attr_value_type value_type =
1686 lttng_process_attr_values_get_type_at_index(values, i);
1687 int64_t integral_value = INT64_MAX;
1688 const char *name = "error";
1689
1690 if (i >= 1) {
1691 _MSG(", ");
1692 }
1693 switch (value_type) {
1694 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID:
1695 {
1696 pid_t pid;
1697
1698 values_status = lttng_process_attr_values_get_pid_at_index(values, i, &pid);
1699 integral_value = (int64_t) pid;
1700 break;
1701 }
1702 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID:
1703 {
1704 uid_t uid;
1705
1706 values_status = lttng_process_attr_values_get_uid_at_index(values, i, &uid);
1707 integral_value = (int64_t) uid;
1708 break;
1709 }
1710 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID:
1711 {
1712 gid_t gid;
1713
1714 values_status = lttng_process_attr_values_get_gid_at_index(values, i, &gid);
1715 integral_value = (int64_t) gid;
1716 break;
1717 }
1718 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME:
1719 values_status =
1720 lttng_process_attr_values_get_user_name_at_index(values, i, &name);
1721 break;
1722 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME:
1723 values_status =
1724 lttng_process_attr_values_get_group_name_at_index(values, i, &name);
1725 break;
1726 default:
1727 ret = CMD_ERROR;
1728 goto end;
1729 }
1730
1731 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1732 /*
1733 * Not possible given the current liblttng-ctl
1734 * implementation.
1735 */
1736 ERR("Unknown error occurred while fetching process attribute value in inclusion list");
1737 ret = CMD_FATAL;
1738 goto end;
1739 }
1740
1741 if (is_value_type_name(value_type)) {
1742 _MSG("`%s`", name);
1743 } else {
1744 _MSG("%" PRIi64, integral_value);
1745 }
1746
1747 /* Mi */
1748 if (the_writer) {
1749 ret = is_value_type_name(value_type) ?
1750 mi_lttng_string_process_attribute_value(
1751 the_writer, process_attr, name, false) :
1752 mi_lttng_integral_process_attribute_value(
1753 the_writer, process_attr, integral_value, false);
1754 if (ret) {
1755 goto end;
1756 }
1757 }
1758 }
1759 MSG("");
1760
1761 /* Mi close tracker_id and targets */
1762 if (the_writer) {
1763 ret = mi_lttng_close_multi_element(the_writer, 2);
1764 if (ret) {
1765 goto end;
1766 }
1767 }
1768 end:
1769 lttng_process_attr_tracker_handle_destroy(tracker_handle);
1770 return ret;
1771 }
1772
1773 /*
1774 * List all trackers of a domain
1775 */
1776 static int list_trackers(const struct lttng_domain *domain)
1777 {
1778 int ret = 0;
1779
1780 MSG("Tracked process attributes");
1781 /* Trackers listing */
1782 if (lttng_opt_mi) {
1783 ret = mi_lttng_trackers_open(the_writer);
1784 if (ret) {
1785 goto end;
1786 }
1787 }
1788
1789 switch (domain->type) {
1790 case LTTNG_DOMAIN_KERNEL:
1791 /* pid tracker */
1792 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID);
1793 if (ret) {
1794 goto end;
1795 }
1796 /* vpid tracker */
1797 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
1798 if (ret) {
1799 goto end;
1800 }
1801 /* uid tracker */
1802 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID);
1803 if (ret) {
1804 goto end;
1805 }
1806 /* vuid tracker */
1807 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
1808 if (ret) {
1809 goto end;
1810 }
1811 /* gid tracker */
1812 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID);
1813 if (ret) {
1814 goto end;
1815 }
1816 /* vgid tracker */
1817 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
1818 if (ret) {
1819 goto end;
1820 }
1821 break;
1822 case LTTNG_DOMAIN_UST:
1823 /* vpid tracker */
1824 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
1825 if (ret) {
1826 goto end;
1827 }
1828 /* vuid tracker */
1829 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
1830 if (ret) {
1831 goto end;
1832 }
1833 /* vgid tracker */
1834 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
1835 if (ret) {
1836 goto end;
1837 }
1838 break;
1839 default:
1840 break;
1841 }
1842 MSG();
1843 if (lttng_opt_mi) {
1844 /* Close trackers element */
1845 ret = mi_lttng_writer_close_element(the_writer);
1846 if (ret) {
1847 goto end;
1848 }
1849 }
1850
1851 end:
1852 return ret;
1853 }
1854
1855 static enum cmd_error_code
1856 print_periodic_rotation_schedule(const struct lttng_rotation_schedule *schedule)
1857 {
1858 enum cmd_error_code ret;
1859 enum lttng_rotation_status status;
1860 uint64_t value;
1861
1862 status = lttng_rotation_schedule_periodic_get_period(schedule, &value);
1863 if (status != LTTNG_ROTATION_STATUS_OK) {
1864 ERR("Failed to retrieve period parameter from periodic rotation schedule.");
1865 ret = CMD_ERROR;
1866 goto end;
1867 }
1868
1869 MSG(" timer period: %" PRIu64 " %s", value, USEC_UNIT);
1870 ret = CMD_SUCCESS;
1871 end:
1872 return ret;
1873 }
1874
1875 static enum cmd_error_code
1876 print_size_threshold_rotation_schedule(const struct lttng_rotation_schedule *schedule)
1877 {
1878 enum cmd_error_code ret;
1879 enum lttng_rotation_status status;
1880 uint64_t value;
1881
1882 status = lttng_rotation_schedule_size_threshold_get_threshold(schedule, &value);
1883 if (status != LTTNG_ROTATION_STATUS_OK) {
1884 ERR("Failed to retrieve size parameter from size-based rotation schedule.");
1885 ret = CMD_ERROR;
1886 goto end;
1887 }
1888
1889 MSG(" size threshold: %" PRIu64 " bytes", value);
1890 ret = CMD_SUCCESS;
1891 end:
1892 return ret;
1893 }
1894
1895 static enum cmd_error_code print_rotation_schedule(const struct lttng_rotation_schedule *schedule)
1896 {
1897 enum cmd_error_code ret;
1898
1899 switch (lttng_rotation_schedule_get_type(schedule)) {
1900 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
1901 ret = print_size_threshold_rotation_schedule(schedule);
1902 break;
1903 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
1904 ret = print_periodic_rotation_schedule(schedule);
1905 break;
1906 default:
1907 ret = CMD_ERROR;
1908 }
1909 return ret;
1910 }
1911
1912 /*
1913 * List the automatic rotation settings.
1914 */
1915 static enum cmd_error_code list_rotate_settings(const char *session_name)
1916 {
1917 int ret;
1918 enum cmd_error_code cmd_ret = CMD_SUCCESS;
1919 unsigned int count, i;
1920 struct lttng_rotation_schedules *schedules = nullptr;
1921 enum lttng_rotation_status status;
1922
1923 ret = lttng_session_list_rotation_schedules(session_name, &schedules);
1924 if (ret != LTTNG_OK) {
1925 ERR("Failed to list session rotation schedules: %s", lttng_strerror(ret));
1926 cmd_ret = CMD_ERROR;
1927 goto end;
1928 }
1929
1930 status = lttng_rotation_schedules_get_count(schedules, &count);
1931 if (status != LTTNG_ROTATION_STATUS_OK) {
1932 ERR("Failed to retrieve the number of session rotation schedules.");
1933 cmd_ret = CMD_ERROR;
1934 goto end;
1935 }
1936
1937 if (count == 0) {
1938 cmd_ret = CMD_SUCCESS;
1939 goto end;
1940 }
1941
1942 MSG("Automatic rotation schedules:");
1943 if (lttng_opt_mi) {
1944 ret = mi_lttng_writer_open_element(the_writer, mi_lttng_element_rotation_schedules);
1945 if (ret) {
1946 cmd_ret = CMD_ERROR;
1947 goto end;
1948 }
1949 }
1950
1951 for (i = 0; i < count; i++) {
1952 enum cmd_error_code tmp_ret = CMD_SUCCESS;
1953 const struct lttng_rotation_schedule *schedule;
1954
1955 schedule = lttng_rotation_schedules_get_at_index(schedules, i);
1956 if (!schedule) {
1957 ERR("Failed to retrieve session rotation schedule.");
1958 cmd_ret = CMD_ERROR;
1959 goto end;
1960 }
1961
1962 if (lttng_opt_mi) {
1963 ret = mi_lttng_rotation_schedule(the_writer, schedule);
1964 if (ret) {
1965 tmp_ret = CMD_ERROR;
1966 }
1967 } else {
1968 tmp_ret = print_rotation_schedule(schedule);
1969 }
1970
1971 /*
1972 * Report an error if the serialization of any of the
1973 * descriptors failed.
1974 */
1975 cmd_ret = cmd_ret ? cmd_ret : tmp_ret;
1976 }
1977
1978 _MSG("\n");
1979 if (lttng_opt_mi) {
1980 /* Close the rotation_schedules element. */
1981 ret = mi_lttng_writer_close_element(the_writer);
1982 if (ret) {
1983 cmd_ret = CMD_ERROR;
1984 goto end;
1985 }
1986 }
1987 end:
1988 lttng_rotation_schedules_destroy(schedules);
1989 return cmd_ret;
1990 }
1991
1992 /*
1993 * Machine interface
1994 * Find the session with session_name as name
1995 * and print his informations.
1996 */
1997 static int mi_list_session(const char *session_name, struct lttng_session *sessions, int count)
1998 {
1999 int ret, i;
2000 unsigned int session_found = 0;
2001
2002 if (session_name == nullptr) {
2003 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2004 goto end;
2005 }
2006
2007 for (i = 0; i < count; i++) {
2008 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2009 /* We need to leave it open to append other informations
2010 * like domain, channel, events etc.*/
2011 session_found = 1;
2012 ret = mi_lttng_session(the_writer, &sessions[i], 1);
2013 if (ret) {
2014 goto end;
2015 }
2016 break;
2017 }
2018 }
2019
2020 if (!session_found) {
2021 ERR("Session '%s' not found", session_name);
2022 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2023 goto end;
2024 }
2025
2026 end:
2027 return ret;
2028 }
2029
2030 /*
2031 * Machine interface
2032 * List all availables session
2033 */
2034 static int mi_list_sessions(struct lttng_session *sessions, int count)
2035 {
2036 int ret, i;
2037
2038 /* Opening sessions element */
2039 ret = mi_lttng_sessions_open(the_writer);
2040 if (ret) {
2041 goto end;
2042 }
2043
2044 /* Listing sessions */
2045 for (i = 0; i < count; i++) {
2046 ret = mi_lttng_session(the_writer, &sessions[i], 0);
2047 if (ret) {
2048 goto end;
2049 }
2050 }
2051
2052 /* Closing sessions element */
2053 ret = mi_lttng_writer_close_element(the_writer);
2054 if (ret) {
2055 goto end;
2056 }
2057
2058 end:
2059 return ret;
2060 }
2061
2062 /*
2063 * List available tracing session. List only basic information.
2064 *
2065 * If session_name is NULL, all sessions are listed.
2066 */
2067 static int list_sessions(const char *session_name)
2068 {
2069 int ret = CMD_SUCCESS;
2070 int count, i;
2071 unsigned int session_found = 0;
2072 struct lttng_session *sessions = nullptr;
2073
2074 count = lttng_list_sessions(&sessions);
2075 DBG("Session count %d", count);
2076 if (count < 0) {
2077 ret = CMD_ERROR;
2078 ERR("%s", lttng_strerror(count));
2079 goto end;
2080 }
2081
2082 if (lttng_opt_mi) {
2083 /* Mi */
2084 if (session_name == nullptr) {
2085 /* List all sessions */
2086 ret = mi_list_sessions(sessions, count);
2087 } else {
2088 /* Note : this return an open session element */
2089 ret = mi_list_session(session_name, sessions, count);
2090 }
2091 if (ret) {
2092 ret = CMD_ERROR;
2093 goto end;
2094 }
2095 } else {
2096 /* Pretty print */
2097 if (count == 0) {
2098 MSG("Currently no available recording session");
2099 goto end;
2100 }
2101
2102 if (session_name == nullptr) {
2103 MSG("Available recording sessions:");
2104 }
2105
2106 for (i = 0; i < count; i++) {
2107 if (session_name != nullptr) {
2108 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2109 session_found = 1;
2110 MSG("Recording session %s: [%s%s]",
2111 session_name,
2112 active_string(sessions[i].enabled),
2113 snapshot_string(sessions[i].snapshot_mode));
2114 if (*sessions[i].path) {
2115 MSG("%sTrace output: %s\n",
2116 indent4,
2117 sessions[i].path);
2118 }
2119 memcpy(&the_listed_session,
2120 &sessions[i],
2121 sizeof(the_listed_session));
2122 break;
2123 }
2124 } else {
2125 MSG(" %d) %s [%s%s]",
2126 i + 1,
2127 sessions[i].name,
2128 active_string(sessions[i].enabled),
2129 snapshot_string(sessions[i].snapshot_mode));
2130 if (*sessions[i].path) {
2131 MSG("%sTrace output: %s", indent4, sessions[i].path);
2132 }
2133 if (sessions[i].live_timer_interval != 0) {
2134 MSG("%sLive timer interval: %u %s",
2135 indent4,
2136 sessions[i].live_timer_interval,
2137 USEC_UNIT);
2138 }
2139 MSG("");
2140 }
2141 }
2142
2143 if (!session_found && session_name != nullptr) {
2144 ERR("Session '%s' not found", session_name);
2145 ret = CMD_ERROR;
2146 goto end;
2147 }
2148
2149 if (session_name == nullptr) {
2150 MSG("\nUse lttng list <session_name> for more details");
2151 }
2152 }
2153
2154 end:
2155 free(sessions);
2156 return ret;
2157 }
2158
2159 /*
2160 * Machine Interface
2161 * list available domain(s) for a session.
2162 */
2163 static int mi_list_domains(struct lttng_domain *domains, int count)
2164 {
2165 int i, ret;
2166 /* Open domains element */
2167 ret = mi_lttng_domains_open(the_writer);
2168 if (ret) {
2169 goto end;
2170 }
2171
2172 for (i = 0; i < count; i++) {
2173 ret = mi_lttng_domain(the_writer, &domains[i], 0);
2174 if (ret) {
2175 goto end;
2176 }
2177 }
2178
2179 /* Closing domains element */
2180 ret = mi_lttng_writer_close_element(the_writer);
2181 if (ret) {
2182 goto end;
2183 }
2184 end:
2185 return ret;
2186 }
2187
2188 /*
2189 * List available domain(s) for a session.
2190 */
2191 static int list_domains(const char *session_name)
2192 {
2193 int i, count, ret = CMD_SUCCESS;
2194 struct lttng_domain *domains = nullptr;
2195
2196 count = lttng_list_domains(session_name, &domains);
2197 if (count < 0) {
2198 ret = CMD_ERROR;
2199 ERR("%s", lttng_strerror(count));
2200 goto end;
2201 }
2202
2203 if (lttng_opt_mi) {
2204 /* Mi output */
2205 ret = mi_list_domains(domains, count);
2206 if (ret) {
2207 ret = CMD_ERROR;
2208 goto error;
2209 }
2210 } else {
2211 /* Pretty print */
2212 MSG("Domains:\n-------------");
2213 if (count == 0) {
2214 MSG(" None");
2215 goto end;
2216 }
2217
2218 for (i = 0; i < count; i++) {
2219 switch (domains[i].type) {
2220 case LTTNG_DOMAIN_KERNEL:
2221 MSG(" - Kernel");
2222 break;
2223 case LTTNG_DOMAIN_UST:
2224 MSG(" - UST global");
2225 break;
2226 case LTTNG_DOMAIN_JUL:
2227 MSG(" - JUL (Java Util Logging)");
2228 break;
2229 case LTTNG_DOMAIN_LOG4J:
2230 MSG(" - LOG4j (Logging for Java)");
2231 break;
2232 case LTTNG_DOMAIN_PYTHON:
2233 MSG(" - Python (logging)");
2234 break;
2235 default:
2236 break;
2237 }
2238 }
2239 }
2240
2241 error:
2242 free(domains);
2243
2244 end:
2245 return ret;
2246 }
2247
2248 /*
2249 * The 'list <options>' first level command
2250 */
2251 int cmd_list(int argc, const char **argv)
2252 {
2253 int opt, ret = CMD_SUCCESS;
2254 const char *arg_session_name, *leftover = nullptr;
2255 static poptContext pc;
2256 struct lttng_domain domain;
2257 struct lttng_domain *domains = nullptr;
2258
2259 memset(&domain, 0, sizeof(domain));
2260
2261 if (argc < 1) {
2262 ret = CMD_ERROR;
2263 goto end;
2264 }
2265
2266 pc = poptGetContext(nullptr, argc, argv, long_options, 0);
2267 poptReadDefaultConfig(pc, 0);
2268
2269 while ((opt = poptGetNextOpt(pc)) != -1) {
2270 switch (opt) {
2271 case OPT_HELP:
2272 SHOW_HELP();
2273 goto end;
2274 case OPT_USERSPACE:
2275 opt_userspace = 1;
2276 break;
2277 case OPT_LIST_OPTIONS:
2278 list_cmd_options(stdout, long_options);
2279 goto end;
2280 default:
2281 ret = CMD_UNDEFINED;
2282 goto end;
2283 }
2284 }
2285
2286 /* Mi check */
2287 if (lttng_opt_mi) {
2288 the_writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
2289 if (!the_writer) {
2290 ret = CMD_ERROR;
2291 goto end;
2292 }
2293
2294 /* Open command element */
2295 ret = mi_lttng_writer_command_open(the_writer, mi_lttng_element_command_list);
2296 if (ret) {
2297 ret = CMD_ERROR;
2298 goto end;
2299 }
2300
2301 /* Open output element */
2302 ret = mi_lttng_writer_open_element(the_writer, mi_lttng_element_command_output);
2303 if (ret) {
2304 ret = CMD_ERROR;
2305 goto end;
2306 }
2307 }
2308
2309 /* Get session name (trailing argument) */
2310 arg_session_name = poptGetArg(pc);
2311 DBG2("Session name: %s", arg_session_name);
2312
2313 leftover = poptGetArg(pc);
2314 if (leftover) {
2315 ERR("Unknown argument: %s", leftover);
2316 ret = CMD_ERROR;
2317 goto end;
2318 }
2319
2320 if (opt_kernel) {
2321 domain.type = LTTNG_DOMAIN_KERNEL;
2322 } else if (opt_userspace) {
2323 DBG2("Listing userspace global domain");
2324 domain.type = LTTNG_DOMAIN_UST;
2325 } else if (opt_jul) {
2326 DBG2("Listing JUL domain");
2327 domain.type = LTTNG_DOMAIN_JUL;
2328 } else if (opt_log4j) {
2329 domain.type = LTTNG_DOMAIN_LOG4J;
2330 } else if (opt_python) {
2331 domain.type = LTTNG_DOMAIN_PYTHON;
2332 }
2333
2334 if (!opt_kernel && opt_syscall) {
2335 WARN("--syscall will only work with the Kernel domain (-k)");
2336 ret = CMD_ERROR;
2337 goto end;
2338 }
2339
2340 if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) {
2341 the_handle = lttng_create_handle(arg_session_name, &domain);
2342 if (the_handle == nullptr) {
2343 ret = CMD_FATAL;
2344 goto end;
2345 }
2346 }
2347
2348 if (arg_session_name == nullptr) {
2349 if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_python) {
2350 ret = list_sessions(nullptr);
2351 if (ret) {
2352 goto end;
2353 }
2354 }
2355 if (opt_kernel) {
2356 if (opt_syscall) {
2357 ret = list_syscalls();
2358 if (ret) {
2359 goto end;
2360 }
2361 } else {
2362 ret = list_kernel_events();
2363 if (ret) {
2364 goto end;
2365 }
2366 }
2367 }
2368 if (opt_userspace) {
2369 if (opt_fields) {
2370 ret = list_ust_event_fields();
2371 } else {
2372 ret = list_ust_events();
2373 }
2374 if (ret) {
2375 goto end;
2376 }
2377 }
2378 if (opt_jul || opt_log4j || opt_python) {
2379 ret = list_agent_events();
2380 if (ret) {
2381 goto end;
2382 }
2383 }
2384 } else {
2385 /* List session attributes */
2386 if (lttng_opt_mi) {
2387 /* Open element sessions
2388 * Present for xml consistency */
2389 ret = mi_lttng_sessions_open(the_writer);
2390 if (ret) {
2391 goto end;
2392 }
2393 }
2394 /* MI: the ouptut of list_sessions is an unclosed session element */
2395 ret = list_sessions(arg_session_name);
2396 if (ret) {
2397 goto end;
2398 }
2399
2400 ret = list_rotate_settings(arg_session_name);
2401 if (ret) {
2402 goto end;
2403 }
2404
2405 /* Domain listing */
2406 if (opt_domain) {
2407 ret = list_domains(arg_session_name);
2408 goto end;
2409 }
2410
2411 /* Channel listing */
2412 if (opt_kernel || opt_userspace) {
2413 if (lttng_opt_mi) {
2414 /* Add of domains and domain element for xml
2415 * consistency and validation
2416 */
2417 ret = mi_lttng_domains_open(the_writer);
2418 if (ret) {
2419 goto end;
2420 }
2421
2422 /* Open domain and leave it open for
2423 * nested channels printing */
2424 ret = mi_lttng_domain(the_writer, &domain, 1);
2425 if (ret) {
2426 goto end;
2427 }
2428 }
2429
2430 /* Trackers */
2431 ret = list_trackers(&domain);
2432 if (ret) {
2433 goto end;
2434 }
2435
2436 /* Channels */
2437 ret = list_channels(opt_channel);
2438 if (ret) {
2439 goto end;
2440 }
2441
2442 if (lttng_opt_mi) {
2443 /* Close domain and domain element */
2444 ret = mi_lttng_close_multi_element(the_writer, 2);
2445 }
2446 if (ret) {
2447 goto end;
2448 }
2449
2450 } else {
2451 int i, nb_domain;
2452
2453 /* We want all domain(s) */
2454 nb_domain = lttng_list_domains(arg_session_name, &domains);
2455 if (nb_domain < 0) {
2456 ret = CMD_ERROR;
2457 ERR("%s", lttng_strerror(nb_domain));
2458 goto end;
2459 }
2460
2461 if (lttng_opt_mi) {
2462 ret = mi_lttng_domains_open(the_writer);
2463 if (ret) {
2464 ret = CMD_ERROR;
2465 goto end;
2466 }
2467 }
2468
2469 for (i = 0; i < nb_domain; i++) {
2470 switch (domains[i].type) {
2471 case LTTNG_DOMAIN_KERNEL:
2472 MSG("=== Domain: Linux kernel ===\n");
2473 break;
2474 case LTTNG_DOMAIN_UST:
2475 MSG("=== Domain: User space ===\n");
2476 MSG("Buffering scheme: %s\n",
2477 domains[i].buf_type == LTTNG_BUFFER_PER_PID ?
2478 "per-process" :
2479 "per-user");
2480 break;
2481 case LTTNG_DOMAIN_JUL:
2482 MSG("=== Domain: java.util.logging (JUL) ===\n");
2483 break;
2484 case LTTNG_DOMAIN_LOG4J:
2485 MSG("=== Domain: log4j ===\n");
2486 break;
2487 case LTTNG_DOMAIN_PYTHON:
2488 MSG("=== Domain: Python logging ===\n");
2489 break;
2490 default:
2491 MSG("=== Domain: Unimplemented ===\n");
2492 break;
2493 }
2494
2495 if (lttng_opt_mi) {
2496 ret = mi_lttng_domain(the_writer, &domains[i], 1);
2497 if (ret) {
2498 ret = CMD_ERROR;
2499 goto end;
2500 }
2501 }
2502
2503 /* Clean handle before creating a new one */
2504 if (the_handle) {
2505 lttng_destroy_handle(the_handle);
2506 }
2507
2508 the_handle = lttng_create_handle(arg_session_name, &domains[i]);
2509 if (the_handle == nullptr) {
2510 ret = CMD_FATAL;
2511 goto end;
2512 }
2513
2514 if (domains[i].type == LTTNG_DOMAIN_JUL ||
2515 domains[i].type == LTTNG_DOMAIN_LOG4J ||
2516 domains[i].type == LTTNG_DOMAIN_PYTHON) {
2517 ret = list_session_agent_events();
2518 if (ret) {
2519 goto end;
2520 }
2521
2522 goto next_domain;
2523 }
2524
2525 switch (domains[i].type) {
2526 case LTTNG_DOMAIN_KERNEL:
2527 case LTTNG_DOMAIN_UST:
2528 ret = list_trackers(&domains[i]);
2529 if (ret) {
2530 goto end;
2531 }
2532 break;
2533 default:
2534 break;
2535 }
2536
2537 ret = list_channels(opt_channel);
2538 if (ret) {
2539 goto end;
2540 }
2541
2542 next_domain:
2543 if (lttng_opt_mi) {
2544 /* Close domain element */
2545 ret = mi_lttng_writer_close_element(the_writer);
2546 if (ret) {
2547 ret = CMD_ERROR;
2548 goto end;
2549 }
2550 }
2551 }
2552 if (lttng_opt_mi) {
2553 /* Close the domains, session and sessions element */
2554 ret = mi_lttng_close_multi_element(the_writer, 3);
2555 if (ret) {
2556 ret = CMD_ERROR;
2557 goto end;
2558 }
2559 }
2560 }
2561 }
2562
2563 /* Mi closing */
2564 if (lttng_opt_mi) {
2565 /* Close output element */
2566 ret = mi_lttng_writer_close_element(the_writer);
2567 if (ret) {
2568 ret = CMD_ERROR;
2569 goto end;
2570 }
2571
2572 /* Command element close */
2573 ret = mi_lttng_writer_command_close(the_writer);
2574 if (ret) {
2575 ret = CMD_ERROR;
2576 goto end;
2577 }
2578 }
2579 end:
2580 /* Mi clean-up */
2581 if (the_writer && mi_lttng_writer_destroy(the_writer)) {
2582 /* Preserve original error code */
2583 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
2584 }
2585
2586 free(domains);
2587 if (the_handle) {
2588 lttng_destroy_handle(the_handle);
2589 }
2590
2591 poptFreeContext(pc);
2592 return ret;
2593 }
This page took 0.082033 seconds and 4 git commands to generate.