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