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