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