Fix: mi: logically dead code, missing ret assignment
[lttng-tools.git] / src / bin / lttng / commands / list.c
CommitLineData
f3ed775e
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
f3ed775e
DG
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
d14d33bf
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
f3ed775e
DG
16 */
17
18#define _GNU_SOURCE
9f19cc17 19#include <inttypes.h>
f3ed775e
DG
20#include <popt.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
7a3d1328 24#include <assert.h>
f3ed775e 25
fb14d0d8
JR
26#include <common/mi-lttng.h>
27
c399183f 28#include "../command.h"
f3ed775e 29
9f19cc17
DG
30static int opt_userspace;
31static int opt_kernel;
3c6a091f 32static int opt_jul;
9f19cc17
DG
33static char *opt_channel;
34static int opt_domain;
f37d259d 35static int opt_fields;
d78d6610
DG
36#if 0
37/* Not implemented yet */
38static char *opt_cmd_name;
39static pid_t opt_pid;
40#endif
9f19cc17
DG
41
42const char *indent4 = " ";
43const char *indent6 = " ";
44const char *indent8 = " ";
f3ed775e
DG
45
46enum {
47 OPT_HELP = 1,
eeac7d46 48 OPT_USERSPACE,
679b4943 49 OPT_LIST_OPTIONS,
f3ed775e
DG
50};
51
cd80958d 52static struct lttng_handle *handle;
fb14d0d8 53static struct mi_writer *writer;
cd80958d 54
f3ed775e
DG
55static struct poptOption long_options[] = {
56 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
9f19cc17 58 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
3c6a091f 59 {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
d78d6610
DG
60#if 0
61 /* Not implemented yet */
62 {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0},
63 {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0},
64#else
65 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
66#endif
9f19cc17
DG
67 {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0},
68 {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0},
f37d259d 69 {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0},
679b4943 70 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
f3ed775e
DG
71 {0, 0, 0, 0, 0, 0, 0}
72};
73
74/*
75 * usage
76 */
77static void usage(FILE *ofp)
78{
747361fe 79 fprintf(ofp, "usage: lttng list [OPTIONS] [SESSION [SESSION OPTIONS]]\n");
9f19cc17
DG
80 fprintf(ofp, "\n");
81 fprintf(ofp, "With no arguments, list available tracing session(s)\n");
82 fprintf(ofp, "\n");
27221701
DG
83 fprintf(ofp, "Without a session, -k lists available kernel events\n");
84 fprintf(ofp, "Without a session, -u lists available userspace events\n");
9f19cc17
DG
85 fprintf(ofp, "\n");
86 fprintf(ofp, " -h, --help Show this help\n");
27221701 87 fprintf(ofp, " --list-options Simple listing of options\n");
9f19cc17
DG
88 fprintf(ofp, " -k, --kernel Select kernel domain\n");
89 fprintf(ofp, " -u, --userspace Select user-space domain.\n");
3c6a091f 90 fprintf(ofp, " -j, --jul Apply for Java application using JUL\n");
f37d259d 91 fprintf(ofp, " -f, --fields List event fields.\n");
d78d6610 92#if 0
9f19cc17 93 fprintf(ofp, " -p, --pid PID List user-space events by PID\n");
d78d6610 94#endif
f3ed775e 95 fprintf(ofp, "\n");
27221701 96 fprintf(ofp, "Session Options:\n");
9f19cc17
DG
97 fprintf(ofp, " -c, --channel NAME List details of a channel\n");
98 fprintf(ofp, " -d, --domain List available domain(s)\n");
f3ed775e
DG
99 fprintf(ofp, "\n");
100}
101
102/*
9f19cc17 103 * Get command line from /proc for a specific pid.
f3ed775e 104 *
9f19cc17
DG
105 * On success, return an allocated string pointer to the proc cmdline.
106 * On error, return NULL.
f3ed775e
DG
107 */
108static char *get_cmdline_by_pid(pid_t pid)
109{
110 int ret;
111 FILE *fp;
112 char *cmdline = NULL;
5f1abdd9 113 char path[20]; /* Can't go bigger than /proc/65535/cmdline */
f3ed775e
DG
114
115 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
116 fp = fopen(path, "r");
117 if (fp == NULL) {
118 goto end;
119 }
120
121 /* Caller must free() *cmdline */
122 cmdline = malloc(PATH_MAX);
f6962219
JG
123 if (!cmdline) {
124 perror("malloc cmdline");
125 goto end;
126 }
f3ed775e 127 ret = fread(cmdline, 1, PATH_MAX, fp);
f40799e8
DG
128 if (ret < 0) {
129 perror("fread proc list");
130 }
f3ed775e
DG
131 fclose(fp);
132
133end:
134 return cmdline;
135}
b551a063 136
464dd62d
MD
137static
138const char *active_string(int value)
139{
140 switch (value) {
2cbf8fed
DG
141 case 0: return "inactive";
142 case 1: return "active";
464dd62d
MD
143 case -1: return "";
144 default: return NULL;
145 }
146}
147
2cbf8fed
DG
148static const char *snapshot_string(int value)
149{
150 switch (value) {
151 case 1:
152 return " snapshot";
153 default:
154 return "";
155 }
156}
157
464dd62d
MD
158static
159const char *enabled_string(int value)
160{
161 switch (value) {
b09f0429
MD
162 case 0: return " [disabled]";
163 case 1: return " [enabled]";
464dd62d
MD
164 case -1: return "";
165 default: return NULL;
166 }
167}
168
fceb65df
MD
169static
170const char *filter_string(int value)
171{
172 switch (value) {
173 case 1: return " [with filter]";
174 default: return "";
175 }
176}
177
4634f12e
JI
178static
179const char *exclusion_string(int value)
180{
181 switch (value) {
182 case 1: return " [has exclusions]";
183 default: return "";
184 }
185}
186
1f0e17de
DG
187static const char *logleveltype_string(enum lttng_loglevel_type value)
188{
189 switch (value) {
af6bce80
DG
190 case LTTNG_EVENT_LOGLEVEL_ALL:
191 return ":";
1f0e17de 192 case LTTNG_EVENT_LOGLEVEL_RANGE:
af6bce80 193 return " <=";
1f0e17de 194 case LTTNG_EVENT_LOGLEVEL_SINGLE:
af6bce80 195 return " ==";
1f0e17de 196 default:
af6bce80 197 return " <<TYPE UNKN>>";
1f0e17de
DG
198 }
199}
200
b551a063
DG
201/*
202 * Pretty print single event.
203 */
204static void print_events(struct lttng_event *event)
205{
206 switch (event->type) {
207 case LTTNG_EVENT_TRACEPOINT:
e4baff1e 208 {
8b703175 209 if (event->loglevel != -1) {
af6bce80 210 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
8b703175 211 indent6,
81afa345 212 event->name,
1f0e17de 213 logleveltype_string(event->loglevel_type),
fb14d0d8 214 mi_lttng_loglevel_string(event->loglevel),
8b703175 215 event->loglevel,
fceb65df 216 enabled_string(event->enabled),
4634f12e 217 exclusion_string(event->exclusion),
fceb65df 218 filter_string(event->filter));
8b703175 219 } else {
4634f12e 220 MSG("%s%s (type: tracepoint)%s%s%s",
8b703175
MD
221 indent6,
222 event->name,
fceb65df 223 enabled_string(event->enabled),
4634f12e 224 exclusion_string(event->exclusion),
fceb65df 225 filter_string(event->filter));
8b703175 226 }
b551a063 227 break;
e4baff1e 228 }
1896972b
DG
229 case LTTNG_EVENT_FUNCTION:
230 MSG("%s%s (type: function)%s%s", indent6,
231 event->name, enabled_string(event->enabled),
232 filter_string(event->filter));
233 if (event->attr.probe.addr != 0) {
234 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
235 } else {
236 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
237 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
238 }
239 break;
b551a063 240 case LTTNG_EVENT_PROBE:
fceb65df
MD
241 MSG("%s%s (type: probe)%s%s", indent6,
242 event->name, enabled_string(event->enabled),
243 filter_string(event->filter));
b551a063
DG
244 if (event->attr.probe.addr != 0) {
245 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
246 } else {
247 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
248 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
249 }
250 break;
b551a063 251 case LTTNG_EVENT_FUNCTION_ENTRY:
fceb65df
MD
252 MSG("%s%s (type: function)%s%s", indent6,
253 event->name, enabled_string(event->enabled),
254 filter_string(event->filter));
b551a063
DG
255 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
256 break;
257 case LTTNG_EVENT_SYSCALL:
fceb65df
MD
258 MSG("%ssyscalls (type: syscall)%s%s", indent6,
259 enabled_string(event->enabled),
260 filter_string(event->filter));
b551a063
DG
261 break;
262 case LTTNG_EVENT_NOOP:
fceb65df
MD
263 MSG("%s (type: noop)%s%s", indent6,
264 enabled_string(event->enabled),
265 filter_string(event->filter));
b551a063
DG
266 break;
267 case LTTNG_EVENT_ALL:
268 /* We should never have "all" events in list. */
269 assert(0);
270 break;
271 }
272}
273
f37d259d
MD
274static const char *field_type(struct lttng_event_field *field)
275{
276 switch(field->type) {
277 case LTTNG_EVENT_FIELD_INTEGER:
278 return "integer";
279 case LTTNG_EVENT_FIELD_ENUM:
280 return "enum";
281 case LTTNG_EVENT_FIELD_FLOAT:
282 return "float";
283 case LTTNG_EVENT_FIELD_STRING:
284 return "string";
285 case LTTNG_EVENT_FIELD_OTHER:
286 default: /* fall-through */
287 return "unknown";
288 }
289}
290
291/*
292 * Pretty print single event fields.
293 */
294static void print_event_field(struct lttng_event_field *field)
295{
296 if (!field->field_name[0]) {
297 return;
298 }
d8fbe2a9 299 MSG("%sfield: %s (%s)%s", indent8, field->field_name,
45a32634 300 field_type(field), field->nowrite ? " [no write]" : "");
f37d259d
MD
301}
302
fb14d0d8
JR
303/*
304 * Machine interface
305 * Jul and ust event listing
306 */
307static int mi_list_jul_ust_events(struct lttng_event *events, int count,
308 struct lttng_domain *domain)
309{
310 int ret, i;
311 pid_t cur_pid = 0;
312 char *cmdline = NULL;
313 int pid_element_open = 0;
314
315 /* Open domains element */
316 ret = mi_lttng_domains_open(writer);
317 if (ret) {
318 goto end;
319 }
320
321 /* Write domain */
322 ret = mi_lttng_domain(writer, domain, 1);
323 if (ret) {
324 goto end;
325 }
326
327 /* Open pids element */
328 ret = mi_lttng_pids_open(writer);
329 if (ret) {
330 goto end;
331 }
332
333 for (i = 0; i < count; i++) {
334 if (cur_pid != events[i].pid) {
335 if (pid_element_open) {
336 /* Close the previous events and pid element */
337 ret = mi_lttng_close_multi_element(writer, 2);
338 if (ret) {
339 goto end;
340 }
341 pid_element_open = 0;
342 }
343
344 cur_pid = events[i].pid;
345 cmdline = get_cmdline_by_pid(cur_pid);
346 if (!cmdline) {
347 ret = CMD_ERROR;
348 goto end;
349 }
350
351 if (!pid_element_open) {
352 /* Open and write a pid element */
353 ret = mi_lttng_pid(writer, cur_pid, cmdline, 1);
354 if (ret) {
355 goto error;
356 }
357
358 /* Open events element */
359 ret = mi_lttng_events_open(writer);
360 if (ret) {
361 goto error;
362 }
363
364 pid_element_open = 1;
365 }
366 free(cmdline);
367 }
368
369 /* Write an event */
370 ret = mi_lttng_event(writer, &events[i], 0);
371 if (ret) {
372 goto end;
373 }
374 }
375
376 /* Close pids */
377 ret = mi_lttng_writer_close_element(writer);
378 if (ret) {
379 goto end;
380 }
381
382 /* Close domain, domains */
383 ret = mi_lttng_close_multi_element(writer, 2);
384end:
385 return ret;
386error:
387 free(cmdline);
388 return ret;
389}
390
3c6a091f
DG
391static int list_jul_events(void)
392{
fb14d0d8 393 int i, size, ret = CMD_SUCCESS;
3c6a091f
DG
394 struct lttng_domain domain;
395 struct lttng_handle *handle;
396 struct lttng_event *event_list;
397 pid_t cur_pid = 0;
398 char *cmdline = NULL;
399
400 DBG("Getting JUL tracing events");
401
402 memset(&domain, 0, sizeof(domain));
403 domain.type = LTTNG_DOMAIN_JUL;
404
405 handle = lttng_create_handle(NULL, &domain);
406 if (handle == NULL) {
fb14d0d8
JR
407 ret = CMD_ERROR;
408 goto end;
3c6a091f
DG
409 }
410
411 size = lttng_list_tracepoints(handle, &event_list);
412 if (size < 0) {
413 ERR("Unable to list JUL events: %s", lttng_strerror(size));
fb14d0d8
JR
414 ret = CMD_ERROR;
415 goto end;
3c6a091f
DG
416 }
417
fb14d0d8
JR
418 if (lttng_opt_mi) {
419 /* Mi print */
420 ret = mi_list_jul_ust_events(event_list, size, &domain);
421 if (ret) {
422 ret = CMD_ERROR;
423 goto error;
3c6a091f 424 }
fb14d0d8
JR
425 } else {
426 /* Pretty print */
427 MSG("JUL events (Logger name):\n-------------------------");
3c6a091f 428
fb14d0d8
JR
429 if (size == 0) {
430 MSG("None");
431 }
3c6a091f 432
fb14d0d8
JR
433 for (i = 0; i < size; i++) {
434 if (cur_pid != event_list[i].pid) {
435 cur_pid = event_list[i].pid;
436 cmdline = get_cmdline_by_pid(cur_pid);
437 if (cmdline == NULL) {
438 ret = CMD_ERROR;
439 goto error;
440 }
441 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
442 free(cmdline);
443 }
444 MSG("%s- %s", indent6, event_list[i].name);
445 }
3c6a091f 446
fb14d0d8
JR
447 MSG("");
448 }
3c6a091f
DG
449
450error:
fb14d0d8
JR
451 free(event_list);
452end:
3c6a091f 453 lttng_destroy_handle(handle);
fb14d0d8 454 return ret;
3c6a091f
DG
455}
456
b551a063
DG
457/*
458 * Ask session daemon for all user space tracepoints available.
459 */
460static int list_ust_events(void)
461{
fb14d0d8 462 int i, size, ret = CMD_SUCCESS;
b551a063
DG
463 struct lttng_domain domain;
464 struct lttng_handle *handle;
465 struct lttng_event *event_list;
466 pid_t cur_pid = 0;
ea5cbc00 467 char *cmdline = NULL;
b551a063 468
441c16a7
MD
469 memset(&domain, 0, sizeof(domain));
470
b551a063
DG
471 DBG("Getting UST tracing events");
472
473 domain.type = LTTNG_DOMAIN_UST;
474
475 handle = lttng_create_handle(NULL, &domain);
476 if (handle == NULL) {
fb14d0d8
JR
477 ret = CMD_ERROR;
478 goto end;
b551a063
DG
479 }
480
481 size = lttng_list_tracepoints(handle, &event_list);
482 if (size < 0) {
60e835ca 483 ERR("Unable to list UST events: %s", lttng_strerror(size));
fb14d0d8
JR
484 ret = CMD_ERROR;
485 goto error;
b551a063
DG
486 }
487
fb14d0d8
JR
488 if (lttng_opt_mi) {
489 /* Mi print */
490 ret = mi_list_jul_ust_events(event_list, size, &domain);
491 } else {
492 /* Pretty print */
493 MSG("UST events:\n-------------");
494
495 if (size == 0) {
496 MSG("None");
497 }
498
499 for (i = 0; i < size; i++) {
500 if (cur_pid != event_list[i].pid) {
501 cur_pid = event_list[i].pid;
502 cmdline = get_cmdline_by_pid(cur_pid);
503 if (cmdline == NULL) {
504 ret = CMD_ERROR;
505 goto error;
506 }
507 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
508 free(cmdline);
509 }
510 print_events(&event_list[i]);
511 }
b551a063 512
fb14d0d8 513 MSG("");
b551a063
DG
514 }
515
fb14d0d8
JR
516error:
517 free(event_list);
518end:
519 lttng_destroy_handle(handle);
520 return ret;
521}
522
523/*
524 * Machine interface
525 * List all ust event with their fields
526 */
527static int mi_list_ust_event_fields(struct lttng_event_field *fields, int count,
528 struct lttng_domain *domain)
529{
530 int ret, i;
531 pid_t cur_pid = 0;
532 char *cmdline = NULL;
533 int pid_element_open = 0;
534 int event_element_open = 0;
535 struct lttng_event cur_event;
536
537 /* Open domains element */
538 ret = mi_lttng_domains_open(writer);
539 if (ret) {
540 goto end;
541 }
542
543 /* Write domain */
544 ret = mi_lttng_domain(writer, domain, 1);
545 if (ret) {
546 goto end;
547 }
548
549 /* Open pids element */
550 ret = mi_lttng_pids_open(writer);
551 if (ret) {
552 goto end;
553 }
554
555 for (i = 0; i < count; i++) {
556 if (cur_pid != fields[i].event.pid) {
557 if (pid_element_open) {
558 if (event_element_open) {
485ca16f
DG
559
560 /* Close the previous field element and event. */
fb14d0d8
JR
561 ret = mi_lttng_close_multi_element(writer, 2);
562 if (ret) {
563 goto end;
564 }
565 event_element_open = 0;
566 }
567 /* Close the previous events, pid element */
568 ret = mi_lttng_close_multi_element(writer, 2);
569 if (ret) {
570 goto end;
571 }
572 pid_element_open = 0;
573 }
574
575 cur_pid = fields[i].event.pid;
ea5cbc00 576 cmdline = get_cmdline_by_pid(cur_pid);
fb14d0d8
JR
577 if (!pid_element_open) {
578 /* Open and write a pid element */
579 ret = mi_lttng_pid(writer, cur_pid, cmdline, 1);
580 if (ret) {
581 goto error;
582 }
583
584 /* Open events element */
585 ret = mi_lttng_events_open(writer);
586 if (ret) {
587 goto error;
588 }
589 pid_element_open = 1;
590 }
ea5cbc00 591 free(cmdline);
fb14d0d8
JR
592 /* Wipe current event since we are about to print a new PID. */
593 memset(&cur_event, 0, sizeof(cur_event));
b551a063 594 }
b551a063 595
fb14d0d8
JR
596 if (strcmp(cur_event.name, fields[i].event.name) != 0) {
597 if (event_element_open) {
598 /* Close the previous fields element and the previous event */
599 ret = mi_lttng_close_multi_element(writer, 2);
600 if (ret) {
601 goto end;
602 }
603 event_element_open = 0;
604 }
605
606 memcpy(&cur_event, &fields[i].event,
607 sizeof(cur_event));
b551a063 608
fb14d0d8
JR
609 if (!event_element_open) {
610 /* Open and write the event */
611 ret = mi_lttng_event(writer, &cur_event, 1);
612 if (ret) {
613 goto end;
614 }
615
616 /* Open a fields element */
617 ret = mi_lttng_event_fields_open(writer);
618 if (ret) {
619 goto end;
620 }
621 event_element_open = 1;
622 }
623 }
b551a063 624
fb14d0d8
JR
625 /* Print the event_field */
626 ret = mi_lttng_event_field(writer, &fields[i]);
627 if (ret) {
628 goto end;
629 }
630 }
b551a063 631
fb14d0d8
JR
632 /* Close pids, domain, domains */
633 ret = mi_lttng_close_multi_element(writer, 3);
634end:
635 return ret;
b551a063 636error:
fb14d0d8
JR
637 free(cmdline);
638 return ret;
b551a063 639}
f3ed775e 640
f37d259d
MD
641/*
642 * Ask session daemon for all user space tracepoint fields available.
643 */
644static int list_ust_event_fields(void)
645{
fb14d0d8 646 int i, size, ret = CMD_SUCCESS;
f37d259d
MD
647 struct lttng_domain domain;
648 struct lttng_handle *handle;
649 struct lttng_event_field *event_field_list;
650 pid_t cur_pid = 0;
ea5cbc00
CB
651 char *cmdline = NULL;
652
f37d259d
MD
653 struct lttng_event cur_event;
654
655 memset(&domain, 0, sizeof(domain));
656 memset(&cur_event, 0, sizeof(cur_event));
657
658 DBG("Getting UST tracing event fields");
659
660 domain.type = LTTNG_DOMAIN_UST;
661
662 handle = lttng_create_handle(NULL, &domain);
663 if (handle == NULL) {
fb14d0d8
JR
664 ret = CMD_ERROR;
665 goto end;
f37d259d
MD
666 }
667
668 size = lttng_list_tracepoint_fields(handle, &event_field_list);
669 if (size < 0) {
60e835ca 670 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
fb14d0d8
JR
671 ret = CMD_ERROR;
672 goto end;
f37d259d
MD
673 }
674
fb14d0d8
JR
675 if (lttng_opt_mi) {
676 /* Mi print */
677 ret = mi_list_ust_event_fields(event_field_list, size, &domain);
678 if (ret) {
679 ret = CMD_ERROR;
680 goto error;
681 }
682 } else {
683 /* Pretty print */
684 MSG("UST events:\n-------------");
f37d259d 685
fb14d0d8
JR
686 if (size == 0) {
687 MSG("None");
f37d259d 688 }
fb14d0d8
JR
689
690 for (i = 0; i < size; i++) {
691 if (cur_pid != event_field_list[i].event.pid) {
692 cur_pid = event_field_list[i].event.pid;
693 cmdline = get_cmdline_by_pid(cur_pid);
694 if (cmdline == NULL) {
695 ret = CMD_ERROR;
696 goto error;
697 }
698 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
699 free(cmdline);
700 /* Wipe current event since we are about to print a new PID. */
701 memset(&cur_event, 0, sizeof(cur_event));
702 }
703 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
704 print_events(&event_field_list[i].event);
705 memcpy(&cur_event, &event_field_list[i].event,
706 sizeof(cur_event));
707 }
708 print_event_field(&event_field_list[i]);
f37d259d 709 }
f37d259d 710
fb14d0d8
JR
711 MSG("");
712 }
f37d259d 713
fb14d0d8 714error:
f37d259d 715 free(event_field_list);
fb14d0d8 716end:
f37d259d 717 lttng_destroy_handle(handle);
fb14d0d8
JR
718 return ret;
719}
f37d259d 720
fb14d0d8
JR
721/*
722 * Machine interface
723 * Print a list of kernel events
724 */
725static int mi_list_kernel_events(struct lttng_event *events, int count,
726 struct lttng_domain *domain)
727{
728 int ret, i;
f37d259d 729
fb14d0d8
JR
730 /* Open domains element */
731 ret = mi_lttng_domains_open(writer);
732 if (ret) {
733 goto end;
734 }
735
736 /* Write domain */
737 ret = mi_lttng_domain(writer, domain, 1);
738 if (ret) {
739 goto end;
740 }
741
742 /* Open events */
743 ret = mi_lttng_events_open(writer);
744 if (ret) {
745 goto end;
746 }
747
748 for (i = 0; i < count; i++) {
d58bb917 749 ret = mi_lttng_event(writer, &events[i], 0);
fb14d0d8
JR
750 if (ret) {
751 goto end;
752 }
753 }
754
755 /* close events, domain and domains */
756 ret = mi_lttng_close_multi_element(writer, 3);
757 if (ret) {
758 goto end;
759 }
760
761end:
762 return ret;
f37d259d
MD
763}
764
f3ed775e 765/*
fb14d0d8 766 * Ask for all trace events in the kernel
f3ed775e 767 */
9f19cc17 768static int list_kernel_events(void)
f3ed775e 769{
fb14d0d8 770 int i, size, ret = CMD_SUCCESS;
b551a063
DG
771 struct lttng_domain domain;
772 struct lttng_handle *handle;
9f19cc17 773 struct lttng_event *event_list;
f3ed775e 774
441c16a7
MD
775 memset(&domain, 0, sizeof(domain));
776
b551a063
DG
777 DBG("Getting kernel tracing events");
778
779 domain.type = LTTNG_DOMAIN_KERNEL;
780
781 handle = lttng_create_handle(NULL, &domain);
782 if (handle == NULL) {
fb14d0d8 783 ret = CMD_ERROR;
b551a063
DG
784 goto error;
785 }
f3ed775e 786
cd80958d 787 size = lttng_list_tracepoints(handle, &event_list);
9f19cc17 788 if (size < 0) {
60e835ca 789 ERR("Unable to list kernel events: %s", lttng_strerror(size));
ef021732 790 lttng_destroy_handle(handle);
fb14d0d8 791 return CMD_ERROR;
f3ed775e
DG
792 }
793
fb14d0d8
JR
794 if (lttng_opt_mi) {
795 /* Mi print */
796 ret = mi_list_kernel_events(event_list, size, &domain);
797 if (ret) {
798 ret = CMD_ERROR;
799 goto end;
800 }
801 } else {
802 MSG("Kernel events:\n-------------");
f3ed775e 803
fb14d0d8
JR
804 for (i = 0; i < size; i++) {
805 print_events(&event_list[i]);
806 }
f3ed775e 807
fb14d0d8
JR
808 MSG("");
809 }
b551a063 810
fb14d0d8 811end:
f3ed775e
DG
812 free(event_list);
813
ef021732 814 lttng_destroy_handle(handle);
fb14d0d8 815 return ret;
b551a063
DG
816
817error:
ef021732 818 lttng_destroy_handle(handle);
fb14d0d8
JR
819 return ret;
820}
821
822/*
823 * Machine Interface
824 * Print a list of jul events
825 */
826static int mi_list_session_jul_events(struct lttng_event *events, int count)
827{
828 int ret, i;
829
830 /* Open events element */
831 ret = mi_lttng_events_open(writer);
832 if (ret) {
833 goto end;
834 }
835
836 for (i = 0; i < count; i++) {
837 ret = mi_lttng_event(writer, &events[i], 0);
838 if (ret) {
839 goto end;
840 }
841 }
842
843 /* Close events element */
844 ret = mi_lttng_writer_close_element(writer);
845
846end:
847 return ret;
f3ed775e
DG
848}
849
3c6a091f
DG
850/*
851 * List JUL events for a specific session using the handle.
852 *
853 * Return CMD_SUCCESS on success else a negative value.
854 */
855static int list_session_jul_events(void)
856{
fb14d0d8 857 int ret = CMD_SUCCESS, count, i;
3c6a091f
DG
858 struct lttng_event *events = NULL;
859
860 count = lttng_list_events(handle, "", &events);
861 if (count < 0) {
fb14d0d8
JR
862 ret = CMD_ERROR;
863 ERR("%s", lttng_strerror(count));
3c6a091f
DG
864 goto error;
865 }
866
fb14d0d8
JR
867 if (lttng_opt_mi) {
868 /* Mi print */
869 ret = mi_list_session_jul_events(events, count);
870 if (ret) {
871 ret = CMD_ERROR;
872 goto end;
873 }
874 } else {
875 /* Pretty print */
876 MSG("Events (Logger name):\n---------------------");
877 if (count == 0) {
878 MSG("%sNone\n", indent6);
879 goto end;
880 }
881
882 for (i = 0; i < count; i++) {
883 MSG("%s- %s%s (loglevel%s %s)", indent4, events[i].name,
884 enabled_string(events[i].enabled),
885 logleveltype_string(events[i].loglevel_type),
136f2f81 886 mi_lttng_loglevel_string(events[i].loglevel));
fb14d0d8
JR
887 }
888
889 MSG("");
890 }
891
892end:
893 free(events);
894error:
895 return ret;
896}
897
898/*
899 * Machine interface
900 * print a list of event
901 */
902static int mi_list_events(struct lttng_event *events, int count)
903{
904 int ret, i;
905
906 /* Open events element */
907 ret = mi_lttng_events_open(writer);
908 if (ret) {
3c6a091f
DG
909 goto end;
910 }
911
912 for (i = 0; i < count; i++) {
fb14d0d8
JR
913 ret = mi_lttng_event(writer, &events[i], 0);
914 if (ret) {
915 goto end;
916 }
3c6a091f
DG
917 }
918
fb14d0d8
JR
919 /* Close events element */
920 ret = mi_lttng_writer_close_element(writer);
3c6a091f
DG
921
922end:
3c6a091f
DG
923 return ret;
924}
925
f3ed775e 926/*
9f19cc17 927 * List events of channel of session and domain.
f3ed775e 928 */
cd80958d 929static int list_events(const char *channel_name)
f3ed775e 930{
fb14d0d8 931 int ret = CMD_SUCCESS, count, i;
9f19cc17 932 struct lttng_event *events = NULL;
f3ed775e 933
cd80958d 934 count = lttng_list_events(handle, channel_name, &events);
f3ed775e 935 if (count < 0) {
fb14d0d8
JR
936 ret = CMD_ERROR;
937 ERR("%s", lttng_strerror(count));
f3ed775e
DG
938 goto error;
939 }
940
fb14d0d8
JR
941 if (lttng_opt_mi) {
942 /* Mi print */
943 ret = mi_list_events(events, count);
944 if (ret) {
945 ret = CMD_ERROR;
946 goto end;
947 }
948 } else {
949 /* Pretty print */
950 MSG("\n%sEvents:", indent4);
951 if (count == 0) {
952 MSG("%sNone\n", indent6);
953 goto end;
954 }
f3ed775e 955
fb14d0d8
JR
956 for (i = 0; i < count; i++) {
957 print_events(&events[i]);
958 }
f3ed775e 959
fb14d0d8
JR
960 MSG("");
961 }
9f19cc17 962end:
0e428499 963 free(events);
f3ed775e
DG
964error:
965 return ret;
966}
967
968/*
9f19cc17
DG
969 * Pretty print channel
970 */
971static void print_channel(struct lttng_channel *channel)
972{
464dd62d 973 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
9f19cc17
DG
974
975 MSG("%sAttributes:", indent4);
a5bbe8f6
DG
976 MSG("%soverwrite mode: %d", indent6, channel->attr.overwrite);
977 MSG("%ssubbufers size: %" PRIu64, indent6, channel->attr.subbuf_size);
9f19cc17 978 MSG("%snumber of subbufers: %" PRIu64, indent6, channel->attr.num_subbuf);
a5bbe8f6
DG
979 MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
980 MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
2f785fe7
DG
981 MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
982 MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
9f19cc17
DG
983 switch (channel->attr.output) {
984 case LTTNG_EVENT_SPLICE:
985 MSG("%soutput: splice()", indent6);
986 break;
987 case LTTNG_EVENT_MMAP:
988 MSG("%soutput: mmap()", indent6);
989 break;
990 }
991}
992
fb14d0d8
JR
993/*
994 * Machine interface
995 * Print a list of channel
996 *
997 */
998static int mi_list_channels(struct lttng_channel *channels, int count,
999 const char *channel_name)
1000{
1001 int i, ret;
1002 unsigned int chan_found = 0;
1003
1004 /* Open channels element */
1005 ret = mi_lttng_channels_open(writer);
1006 if (ret) {
1007 goto error;
1008 }
1009
1010 for (i = 0; i < count; i++) {
1011 if (channel_name != NULL) {
1012 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1013 chan_found = 1;
1014 } else {
1015 continue;
1016 }
1017 }
1018
1019 /* Write channel element and leave it open */
1020 ret = mi_lttng_channel(writer, &channels[i], 1);
1021 if (ret) {
1022 goto error;
1023 }
1024
1025 /* Listing events per channel */
1026 ret = list_events(channels[i].name);
1027 if (ret) {
1028 goto error;
1029 }
1030
1031 /* Closing the channel element we opened earlier */
1032 ret = mi_lttng_writer_close_element(writer);
1033 if (ret) {
1034 goto error;
1035 }
1036
1037 if (chan_found) {
1038 break;
1039 }
1040 }
1041
1042 /* Close channels element */
1043 ret = mi_lttng_writer_close_element(writer);
1044 if (ret) {
1045 goto error;
1046 }
1047
1048error:
1049 return ret;
1050}
1051
9f19cc17
DG
1052/*
1053 * List channel(s) of session and domain.
f3ed775e 1054 *
9f19cc17 1055 * If channel_name is NULL, all channels are listed.
f3ed775e 1056 */
cd80958d 1057static int list_channels(const char *channel_name)
f3ed775e 1058{
9f19cc17
DG
1059 int count, i, ret = CMD_SUCCESS;
1060 unsigned int chan_found = 0;
1061 struct lttng_channel *channels = NULL;
f3ed775e 1062
3e25cb20 1063 DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
9f19cc17 1064
cd80958d 1065 count = lttng_list_channels(handle, &channels);
f3ed775e 1066 if (count < 0) {
c7d620a2
DG
1067 switch (-count) {
1068 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
fb14d0d8
JR
1069 if (lttng_opt_mi) {
1070 /* When printing mi this is not an error
1071 * but an empty channels element */
1072 count = 0;
1073 } else {
1074 ret = CMD_SUCCESS;
1075 WARN("No kernel channel");
1076 goto error_channels;
1077 }
c7d620a2
DG
1078 break;
1079 default:
1080 /* We had a real error */
fb14d0d8
JR
1081 ret = CMD_ERROR;
1082 ERR("%s", lttng_strerror(count));
1083 goto error_channels;
60e835ca 1084 break;
c7d620a2 1085 }
f3ed775e
DG
1086 }
1087
fb14d0d8
JR
1088 if (lttng_opt_mi) {
1089 /* Mi print */
1090 ret = mi_list_channels(channels, count, channel_name);
1091 if (ret) {
1092 ret = CMD_ERROR;
1093 goto error;
1094 }
1095 } else {
1096 /* Pretty print */
1097 if (channel_name == NULL) {
1098 MSG("Channels:\n-------------");
1099 }
9f19cc17 1100
fb14d0d8
JR
1101 for (i = 0; i < count; i++) {
1102 if (channel_name != NULL) {
1103 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1104 chan_found = 1;
1105 } else {
1106 continue;
1107 }
1108 }
1109 print_channel(&channels[i]);
1110
1111 /* Listing events per channel */
1112 ret = list_events(channels[i].name);
1113 if (ret) {
1114 goto error;
1115 }
1116
1117 if (chan_found) {
1118 break;
9f19cc17
DG
1119 }
1120 }
9f19cc17 1121
fb14d0d8
JR
1122 if (!chan_found && channel_name != NULL) {
1123 ret = CMD_ERROR;
1124 ERR("Channel %s not found", channel_name);
1125 goto error;
9f19cc17 1126 }
fb14d0d8
JR
1127 }
1128error:
1129 free(channels);
9f19cc17 1130
fb14d0d8
JR
1131error_channels:
1132 return ret;
1133}
1134
1135/*
1136 * Machine interface
1137 * Find the session with session_name as name
1138 * and print his informations.
1139 */
1140static int mi_list_session(const char *session_name,
1141 struct lttng_session *sessions, int count)
1142{
1143 int ret, i;
1144 unsigned int session_found = 0;
1145
1146 if (session_name == NULL) {
1147 ret = -LTTNG_ERR_SESS_NOT_FOUND;
1148 goto end;
1149 }
1150
1151 for (i = 0; i < count; i++) {
1152 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
1153 /* We need to leave it open to append other informations
1154 * like domain, channel, events etc.*/
1155 session_found = 1;
1156 ret = mi_lttng_session(writer, &sessions[i], 1);
1157 if (ret) {
1158 goto end;
1159 }
9f19cc17 1160 break;
f3ed775e 1161 }
f3ed775e
DG
1162 }
1163
fb14d0d8
JR
1164 if (!session_found) {
1165 ERR("Session '%s' not found", session_name);
1166 ret = -LTTNG_ERR_SESS_NOT_FOUND;
1167 goto end;
9f19cc17 1168 }
f3ed775e 1169
fb14d0d8
JR
1170end:
1171 return ret;
1172}
f3ed775e 1173
fb14d0d8
JR
1174/*
1175 * Machine interface
1176 * List all availables session
1177 */
1178static int mi_list_sessions(struct lttng_session *sessions, int count)
1179{
1180 int ret, i;
ae856491 1181
fb14d0d8
JR
1182 /* Opening sessions element */
1183 ret = mi_lttng_sessions_open(writer);
1184 if (ret) {
1185 goto end;
1186 }
1187
1188 /* Listing sessions */
1189 for (i = 0; i < count; i++) {
1190 ret = mi_lttng_session(writer, &sessions[i], 0);
1191 if (ret) {
1192 goto end;
1193 }
1194 }
1195
1196 /* Closing sessions element */
1197 ret = mi_lttng_writer_close_element(writer);
1198 if (ret) {
1199 goto end;
1200 }
1201
1202end:
f3ed775e
DG
1203 return ret;
1204}
1205
1206/*
9f19cc17 1207 * List available tracing session. List only basic information.
f3ed775e 1208 *
9f19cc17 1209 * If session_name is NULL, all sessions are listed.
f3ed775e 1210 */
9f19cc17 1211static int list_sessions(const char *session_name)
f3ed775e 1212{
fb14d0d8
JR
1213 int ret = CMD_SUCCESS;
1214 int count, i;
9f19cc17
DG
1215 unsigned int session_found = 0;
1216 struct lttng_session *sessions;
1217
1218 count = lttng_list_sessions(&sessions);
1219 DBG("Session count %d", count);
1220 if (count < 0) {
fb14d0d8
JR
1221 ret = CMD_ERROR;
1222 ERR("%s", lttng_strerror(count));
d32fb093 1223 goto end;
9f19cc17
DG
1224 }
1225
fb14d0d8
JR
1226 if (lttng_opt_mi) {
1227 /* Mi */
1228 if (session_name == NULL) {
1229 /* List all session */
1230 ret = mi_list_sessions(sessions, count);
1231 } else {
1232 /* Note : this return an open session element */
1233 ret = mi_list_session(session_name, sessions, count);
1234 }
1235 if (ret) {
1236 ret = CMD_ERROR;
1237 goto error;
1238 }
1239 } else {
1240 /* Pretty print */
1241 if (count == 0) {
1242 MSG("Currently no available tracing session");
1243 ret = CMD_ERROR;
1244 goto end;
1245 }
9f19cc17 1246
fb14d0d8
JR
1247 if (session_name == NULL) {
1248 MSG("Available tracing sessions:");
1249 }
1250
1251
1252 for (i = 0; i < count; i++) {
1253 if (session_name != NULL) {
1254 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
1255 session_found = 1;
1256 MSG("Tracing session %s: [%s%s]", session_name,
1257 active_string(sessions[i].enabled),
1258 snapshot_string(sessions[i].snapshot_mode));
1259 MSG("%sTrace path: %s\n", indent4, sessions[i].path);
1260 break;
1261 }
1262 } else {
1263 MSG(" %d) %s (%s) [%s%s]", i + 1,
1264 sessions[i].name, sessions[i].path,
2cbf8fed
DG
1265 active_string(sessions[i].enabled),
1266 snapshot_string(sessions[i].snapshot_mode));
2f785fe7
DG
1267 MSG("%sTrace path: %s", indent4, sessions[i].path);
1268 MSG("%sLive timer interval (usec): %u\n", indent4,
1269 sessions[i].live_timer_interval);
9f19cc17
DG
1270 break;
1271 }
fb14d0d8
JR
1272 }
1273
1274 if (!session_found && session_name != NULL) {
1275 ERR("Session '%s' not found", session_name);
1276 ret = CMD_ERROR;
1277 goto error;
1278 }
1279
1280 if (session_name == NULL) {
1281 MSG("\nUse lttng list <session_name> for more details");
9f19cc17
DG
1282 }
1283 }
1284
fb14d0d8 1285error:
9f19cc17 1286 free(sessions);
fb14d0d8
JR
1287end:
1288 return ret;
1289}
9f19cc17 1290
fb14d0d8
JR
1291
1292/*
1293 * Machine Interface
1294 * list available domain(s) for a session.
1295 */
1296static int mi_list_domains(struct lttng_domain *domains, int count)
1297{
1298 int i, ret;
1299 /* Open domains element */
1300 ret = mi_lttng_domains_open(writer);
1301 if (ret) {
1302 goto end;
9f19cc17
DG
1303 }
1304
fb14d0d8
JR
1305 for (i = 0; i < count; i++) {
1306 ret = mi_lttng_domain(writer, &domains[i] , 0);
1307 if (ret) {
1308 goto end;
1309 }
9f19cc17 1310 }
f3ed775e 1311
fb14d0d8
JR
1312 /* Closing domains element */
1313 ret = mi_lttng_writer_close_element(writer);
1314 if (ret) {
1315 goto end;
1316 }
d32fb093 1317end:
f3ed775e
DG
1318 return ret;
1319}
f3ed775e
DG
1320
1321/*
9f19cc17 1322 * List available domain(s) for a session.
f3ed775e 1323 */
330be774 1324static int list_domains(const char *session_name)
f3ed775e 1325{
9f19cc17
DG
1326 int i, count, ret = CMD_SUCCESS;
1327 struct lttng_domain *domains = NULL;
1328
9f19cc17 1329
330be774 1330 count = lttng_list_domains(session_name, &domains);
9f19cc17 1331 if (count < 0) {
fb14d0d8
JR
1332 ret = CMD_ERROR;
1333 ERR("%s", lttng_strerror(count));
9f19cc17
DG
1334 goto end;
1335 }
1336
fb14d0d8
JR
1337 if (lttng_opt_mi) {
1338 /* Mi output */
1339 ret = mi_list_domains(domains, count);
1340 if (ret) {
1341 ret = CMD_ERROR;
1342 goto error;
1343 }
1344 } else {
1345 /* Pretty print */
1346 MSG("Domains:\n-------------");
1347 if (count == 0) {
1348 MSG(" None");
1349 goto end;
1350 }
1351
1352 for (i = 0; i < count; i++) {
1353 switch (domains[i].type) {
1354 case LTTNG_DOMAIN_KERNEL:
1355 MSG(" - Kernel");
1356 break;
1357 case LTTNG_DOMAIN_UST:
1358 MSG(" - UST global");
1359 break;
1360 case LTTNG_DOMAIN_JUL:
1361 MSG(" - JUL (Java Util Logging)");
1362 break;
1363 default:
1364 break;
1365 }
9f19cc17
DG
1366 }
1367 }
1368
fb14d0d8 1369error:
9f19cc17
DG
1370 free(domains);
1371
fb14d0d8 1372end:
9f19cc17 1373 return ret;
f3ed775e 1374}
f3ed775e
DG
1375
1376/*
9f19cc17 1377 * The 'list <options>' first level command
f3ed775e
DG
1378 */
1379int cmd_list(int argc, const char **argv)
1380{
c617c0c6 1381 int opt, ret = CMD_SUCCESS;
9f19cc17 1382 const char *session_name;
f3ed775e 1383 static poptContext pc;
9f19cc17
DG
1384 struct lttng_domain domain;
1385 struct lttng_domain *domains = NULL;
f3ed775e 1386
441c16a7
MD
1387 memset(&domain, 0, sizeof(domain));
1388
9f19cc17 1389 if (argc < 1) {
f3ed775e 1390 usage(stderr);
ca1c3607 1391 ret = CMD_ERROR;
f3ed775e
DG
1392 goto end;
1393 }
1394
1395 pc = poptGetContext(NULL, argc, argv, long_options, 0);
1396 poptReadDefaultConfig(pc, 0);
1397
1398 while ((opt = poptGetNextOpt(pc)) != -1) {
1399 switch (opt) {
1400 case OPT_HELP:
ca1c3607 1401 usage(stdout);
f3ed775e 1402 goto end;
eeac7d46
MD
1403 case OPT_USERSPACE:
1404 opt_userspace = 1;
eeac7d46 1405 break;
679b4943
SM
1406 case OPT_LIST_OPTIONS:
1407 list_cmd_options(stdout, long_options);
679b4943 1408 goto end;
f3ed775e
DG
1409 default:
1410 usage(stderr);
1411 ret = CMD_UNDEFINED;
1412 goto end;
1413 }
1414 }
1415
fb14d0d8
JR
1416 /* Mi check */
1417 if (lttng_opt_mi) {
1418 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
1419 if (!writer) {
1420 ret = CMD_ERROR;
1421 goto end;
1422 }
1423
1424 /* Open command element */
1425 ret = mi_lttng_writer_command_open(writer,
1426 mi_lttng_element_command_list);
1427 if (ret) {
1428 ret = CMD_ERROR;
1429 goto end;
1430 }
1431
1432 /* Open output element */
1433 ret = mi_lttng_writer_open_element(writer,
1434 mi_lttng_element_command_output);
1435 if (ret) {
1436 ret = CMD_ERROR;
1437 goto end;
1438 }
1439 }
1440
9f19cc17
DG
1441 /* Get session name (trailing argument) */
1442 session_name = poptGetArg(pc);
b551a063 1443 DBG2("Session name: %s", session_name);
9f19cc17 1444
cd80958d
DG
1445 if (opt_kernel) {
1446 domain.type = LTTNG_DOMAIN_KERNEL;
b551a063
DG
1447 } else if (opt_userspace) {
1448 DBG2("Listing userspace global domain");
1449 domain.type = LTTNG_DOMAIN_UST;
3c6a091f
DG
1450 } else if (opt_jul) {
1451 DBG2("Listing JUL domain");
1452 domain.type = LTTNG_DOMAIN_JUL;
cd80958d
DG
1453 }
1454
3c6a091f 1455 if (opt_kernel || opt_userspace || opt_jul) {
aa5de748
MD
1456 handle = lttng_create_handle(session_name, &domain);
1457 if (handle == NULL) {
1458 ret = CMD_FATAL;
1459 goto end;
1460 }
cd80958d
DG
1461 }
1462
9f19cc17 1463 if (session_name == NULL) {
3c6a091f 1464 if (!opt_kernel && !opt_userspace && !opt_jul) {
b551a063 1465 ret = list_sessions(NULL);
fb14d0d8 1466 if (ret) {
b551a063
DG
1467 goto end;
1468 }
1469 }
9f19cc17
DG
1470 if (opt_kernel) {
1471 ret = list_kernel_events();
fb14d0d8 1472 if (ret) {
9f19cc17
DG
1473 goto end;
1474 }
b551a063
DG
1475 }
1476 if (opt_userspace) {
f37d259d
MD
1477 if (opt_fields) {
1478 ret = list_ust_event_fields();
1479 } else {
1480 ret = list_ust_events();
1481 }
fb14d0d8 1482 if (ret) {
9f19cc17
DG
1483 goto end;
1484 }
1485 }
3c6a091f
DG
1486 if (opt_jul) {
1487 ret = list_jul_events();
fb14d0d8 1488 if (ret) {
3c6a091f
DG
1489 goto end;
1490 }
1491 }
9f19cc17
DG
1492 } else {
1493 /* List session attributes */
fb14d0d8
JR
1494 if (lttng_opt_mi) {
1495 /* Open element sessions
1496 * Present for xml consistency */
1497 ret = mi_lttng_sessions_open(writer);
1498 if (ret) {
1499 goto end;
1500 }
1501 }
1502 /* MI: the ouptut of list_sessions is an unclosed session element */
9f19cc17 1503 ret = list_sessions(session_name);
fb14d0d8 1504 if (ret) {
9f19cc17
DG
1505 goto end;
1506 }
1507
1508 /* Domain listing */
1509 if (opt_domain) {
330be774 1510 ret = list_domains(session_name);
9f19cc17
DG
1511 goto end;
1512 }
1513
fb14d0d8 1514 /* Channel listing */
1c3de747 1515 if (opt_kernel || opt_userspace) {
fb14d0d8
JR
1516 if (lttng_opt_mi) {
1517 /* Add of domains and domain element for xml
1518 * consistency and validation
1519 */
1520 ret = mi_lttng_domains_open(writer);
1521 if (ret) {
1522 goto end;
1523 }
1524
1525 /* Open domain and leave it open for
1526 * nested channels printing */
1527 ret = mi_lttng_domain(writer, &domain, 1);
1528 if (ret) {
1529 goto end;
1530 }
1531
1532 }
1533
cd80958d 1534 ret = list_channels(opt_channel);
fb14d0d8
JR
1535 if (ret) {
1536 goto end;
1537 }
1538
1539 if (lttng_opt_mi) {
1540 /* Close domain and domain element */
1541 ret = mi_lttng_close_multi_element(writer, 2);
1542 }
1543 if (ret) {
9f19cc17
DG
1544 goto end;
1545 }
fb14d0d8
JR
1546
1547
9f19cc17 1548 } else {
c617c0c6
MD
1549 int i, nb_domain;
1550
9f19cc17 1551 /* We want all domain(s) */
330be774 1552 nb_domain = lttng_list_domains(session_name, &domains);
b551a063 1553 if (nb_domain < 0) {
fb14d0d8
JR
1554 ret = CMD_ERROR;
1555 ERR("%s", lttng_strerror(nb_domain));
9f19cc17
DG
1556 goto end;
1557 }
1558
fb14d0d8
JR
1559 if (lttng_opt_mi) {
1560 ret = mi_lttng_domains_open(writer);
1561 if (ret) {
1562 ret = CMD_ERROR;
1563 goto end;
1564 }
1565 }
1566
b551a063 1567 for (i = 0; i < nb_domain; i++) {
9f19cc17
DG
1568 switch (domains[i].type) {
1569 case LTTNG_DOMAIN_KERNEL:
1570 MSG("=== Domain: Kernel ===\n");
1571 break;
b551a063
DG
1572 case LTTNG_DOMAIN_UST:
1573 MSG("=== Domain: UST global ===\n");
88c5f0d8
DG
1574 MSG("Buffer type: %s\n",
1575 domains[i].buf_type ==
1576 LTTNG_BUFFER_PER_PID ? "per PID" : "per UID");
b551a063 1577 break;
3c6a091f
DG
1578 case LTTNG_DOMAIN_JUL:
1579 MSG("=== Domain: JUL (Java Util Logging) ===\n");
1580 break;
9f19cc17
DG
1581 default:
1582 MSG("=== Domain: Unimplemented ===\n");
1583 break;
1584 }
1585
fb14d0d8
JR
1586 if (lttng_opt_mi) {
1587 ret = mi_lttng_domain(writer, &domains[i], 1);
1588 if (ret) {
1589 ret = CMD_ERROR;
1590 goto end;
1591 }
1592 }
1593
cd80958d 1594 /* Clean handle before creating a new one */
aa5de748
MD
1595 if (handle) {
1596 lttng_destroy_handle(handle);
1597 }
cd80958d
DG
1598
1599 handle = lttng_create_handle(session_name, &domains[i]);
1600 if (handle == NULL) {
ca1c3607 1601 ret = CMD_FATAL;
cd80958d
DG
1602 goto end;
1603 }
1604
3c6a091f
DG
1605 if (domains[i].type == LTTNG_DOMAIN_JUL) {
1606 ret = list_session_jul_events();
fb14d0d8 1607 if (ret) {
3c6a091f
DG
1608 goto end;
1609 }
1610 continue;
1611 }
1612
cd80958d 1613 ret = list_channels(opt_channel);
fb14d0d8
JR
1614 if (ret) {
1615 goto end;
1616 }
1617
1618 if (lttng_opt_mi) {
1619 /* Close domain element */
1620 ret = mi_lttng_writer_close_element(writer);
1621 if (ret) {
1622 ret = CMD_ERROR;
1623 goto end;
1624 }
1625 }
1626
1627 }
1628 if (lttng_opt_mi) {
1629 /* Close the domains, session and sessions element */
1630 ret = mi_lttng_close_multi_element(writer, 3);
1631 if (ret) {
1632 ret = CMD_ERROR;
9f19cc17
DG
1633 goto end;
1634 }
1635 }
1636 }
f3ed775e
DG
1637 }
1638
fb14d0d8
JR
1639 /* Mi closing */
1640 if (lttng_opt_mi) {
1641 /* Close output element */
1642 ret = mi_lttng_writer_close_element(writer);
1643 if (ret) {
1644 ret = CMD_ERROR;
1645 goto end;
1646 }
1647
1648 /* Command element close */
1649 ret = mi_lttng_writer_command_close(writer);
1650 if (ret) {
1651 ret = CMD_ERROR;
1652 goto end;
1653 }
1654 }
f3ed775e 1655end:
fb14d0d8
JR
1656 /* Mi clean-up */
1657 if (writer && mi_lttng_writer_destroy(writer)) {
1658 /* Preserve original error code */
1659 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
1660 }
1661
0e428499 1662 free(domains);
aa5de748
MD
1663 if (handle) {
1664 lttng_destroy_handle(handle);
1665 }
cd80958d 1666
ca1c3607 1667 poptFreeContext(pc);
f3ed775e
DG
1668 return ret;
1669}
This page took 0.122815 seconds and 5 git commands to generate.