+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_session_agent_events(events, count);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ } else {
+ /* Pretty print */
+ MSG("Events (Logger name):\n---------------------");
+ if (count == 0) {
+ MSG("%sNone\n", indent6);
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ MSG("%s- %s%s (loglevel%s %s)", indent4, events[i].name,
+ enabled_string(events[i].enabled),
+ logleveltype_string(events[i].loglevel_type),
+ mi_lttng_loglevel_string(events[i].loglevel));
+ }
+
+ MSG("");
+ }
+
+end:
+ free(events);
+error:
+ return ret;
+}
+
+/*
+ * Machine interface
+ * print a list of event
+ */
+static int mi_list_events(struct lttng_event *events, int count)
+{
+ int ret, i;
+
+ /* Open events element */
+ ret = mi_lttng_events_open(writer);
+ if (ret) {
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = mi_lttng_event(writer, &events[i], 0);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close events element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+/*
+ * List events of channel of session and domain.
+ */
+static int list_events(const char *channel_name)
+{
+ int ret = CMD_SUCCESS, count, i;
+ struct lttng_event *events = NULL;
+
+ count = lttng_list_events(handle, channel_name, &events);
+ if (count < 0) {
+ ret = CMD_ERROR;
+ ERR("%s", lttng_strerror(count));
+ goto error;
+ }
+
+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_events(events, count);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ } else {
+ /* Pretty print */
+ MSG("\n%sEvents:", indent4);
+ if (count == 0) {
+ MSG("%sNone\n", indent6);
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ print_events(&events[i]);
+ }
+
+ MSG("");
+ }
+end:
+ free(events);
+error:
+ return ret;
+}
+
+/*
+ * Pretty print channel
+ */
+static void print_channel(struct lttng_channel *channel)
+{
+ MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
+
+ MSG("%sAttributes:", indent4);
+ MSG("%soverwrite mode: %d", indent6, channel->attr.overwrite);
+ MSG("%ssubbufers size: %" PRIu64, indent6, channel->attr.subbuf_size);
+ MSG("%snumber of subbufers: %" PRIu64, indent6, channel->attr.num_subbuf);
+ MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
+ MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
+ MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
+ MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
+ switch (channel->attr.output) {
+ case LTTNG_EVENT_SPLICE:
+ MSG("%soutput: splice()", indent6);
+ break;
+ case LTTNG_EVENT_MMAP:
+ MSG("%soutput: mmap()", indent6);
+ break;
+ }
+}
+
+/*
+ * Machine interface
+ * Print a list of channel
+ *
+ */
+static int mi_list_channels(struct lttng_channel *channels, int count,
+ const char *channel_name)
+{
+ int i, ret;
+ unsigned int chan_found = 0;
+
+ /* Open channels element */
+ ret = mi_lttng_channels_open(writer);
+ if (ret) {
+ goto error;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (channel_name != NULL) {
+ if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
+ chan_found = 1;
+ } else {
+ continue;
+ }
+ }
+
+ /* Write channel element and leave it open */
+ ret = mi_lttng_channel(writer, &channels[i], 1);
+ if (ret) {
+ goto error;
+ }
+
+ /* Listing events per channel */
+ ret = list_events(channels[i].name);
+ if (ret) {
+ goto error;
+ }
+
+ /* Closing the channel element we opened earlier */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto error;
+ }
+
+ if (chan_found) {
+ break;
+ }
+ }
+
+ /* Close channels element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * List channel(s) of session and domain.
+ *
+ * If channel_name is NULL, all channels are listed.
+ */
+static int list_channels(const char *channel_name)
+{
+ int count, i, ret = CMD_SUCCESS;
+ unsigned int chan_found = 0;
+ struct lttng_channel *channels = NULL;
+
+ DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
+
+ count = lttng_list_channels(handle, &channels);
+ if (count < 0) {
+ switch (-count) {
+ case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
+ if (lttng_opt_mi) {
+ /* When printing mi this is not an error
+ * but an empty channels element */
+ count = 0;
+ } else {
+ ret = CMD_SUCCESS;
+ WARN("No kernel channel");
+ goto error_channels;
+ }
+ break;
+ default:
+ /* We had a real error */
+ ret = CMD_ERROR;
+ ERR("%s", lttng_strerror(count));
+ goto error_channels;
+ break;
+ }
+ }
+
+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_channels(channels, count, channel_name);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+ } else {
+ /* Pretty print */
+ if (channel_name == NULL) {
+ MSG("Channels:\n-------------");
+ }
+
+ for (i = 0; i < count; i++) {
+ if (channel_name != NULL) {
+ if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
+ chan_found = 1;
+ } else {
+ continue;
+ }
+ }
+ print_channel(&channels[i]);
+
+ /* Listing events per channel */
+ ret = list_events(channels[i].name);
+ if (ret) {
+ goto error;
+ }
+
+ if (chan_found) {
+ break;
+ }
+ }
+
+ if (!chan_found && channel_name != NULL) {
+ ret = CMD_ERROR;
+ ERR("Channel %s not found", channel_name);
+ goto error;
+ }
+ }
+error:
+ free(channels);
+
+error_channels:
+ return ret;
+}
+
+/*
+ * Machine interface
+ * Find the session with session_name as name
+ * and print his informations.
+ */
+static int mi_list_session(const char *session_name,
+ struct lttng_session *sessions, int count)
+{
+ int ret, i;
+ unsigned int session_found = 0;
+