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