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