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