--- /dev/null
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <common/spawn-viewer.h>
+#include "../command.h"
+
+static char *opt_session_name;
+static char *opt_viewer;
+static char *opt_trace_path;
+
+#ifdef LTTNG_EMBED_HELP
+static const char help_msg[] =
+#include <lttng-view.1.h>
+;
+#endif
+
+enum {
+ OPT_HELP = 1,
+ OPT_LIST_OPTIONS,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
+ {"viewer", 'e', POPT_ARG_STRING, &opt_viewer, 0, 0, 0},
+ {"trace-path", 't', POPT_ARG_STRING, &opt_trace_path, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/* Is the session we are trying to view is in live mode. */
+static int session_live_mode;
+
+/*
+ * Build the live path we need for the lttng live view.
+ */
+static char *build_live_path(char *session_name)
+{
+ int ret;
+ char *path = NULL;
+ char hostname[LTTNG_HOST_NAME_MAX];
+
+ ret = gethostname(hostname, sizeof(hostname));
+ if (ret < 0) {
+ PERROR("gethostname");
+ goto error;
+ }
+
+ ret = asprintf(&path, "net://localhost/host/%s/%s", hostname,
+ session_name);
+ if (ret < 0) {
+ PERROR("asprintf live path");
+ goto error;
+ }
+
+error:
+ return path;
+}
+
+/*
+ * Exec viewer if found and use session name path.
+ */
+static int view_trace(void)
+{
+ int ret;
+ char *session_name, *trace_path = NULL;
+ struct lttng_session *sessions = NULL;
+ bool free_trace_path = false;
+
+ /*
+ * Safety net. If lttng is suid at some point for *any* useless reasons,
+ * this prevent any bad execution of binaries.
+ */
+ if (getuid() != 0) {
+ if (getuid() != geteuid()) {
+ ERR("UID does not match effective UID.");
+ ret = CMD_ERROR;
+ goto error;
+ } else if (getgid() != getegid()) {
+ ERR("GID does not match effective GID.");
+ ret = CMD_ERROR;
+ goto error;
+ }
+ }
+
+ /* User define trace path override the session name */
+ if (opt_trace_path) {
+ session_name = NULL;
+ } else if(opt_session_name == NULL) {
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+ } else {
+ session_name = opt_session_name;
+ }
+
+ DBG("Viewing trace for session %s", session_name);
+
+ if (session_name) {
+ int i, count, found = 0;
+
+ /* Getting all sessions */
+ count = lttng_list_sessions(&sessions);
+ if (count < 0) {
+ ERR("Unable to list sessions. Session name %s not found.",
+ session_name);
+ MSG("Is there a session daemon running?");
+ ret = CMD_ERROR;
+ goto free_error;
+ }
+
+ /* Find our session listed by the session daemon */
+ for (i = 0; i < count; i++) {
+ if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ MSG("Session name %s not found", session_name);
+ ret = CMD_ERROR;
+ goto free_sessions;
+ }
+
+ session_live_mode = sessions[i].live_timer_interval;
+
+ DBG("Session live mode set to %d", session_live_mode);
+
+ if (sessions[i].enabled && !session_live_mode) {
+ WARN("Session %s is running. Please stop it before reading it.",
+ session_name);
+ ret = CMD_ERROR;
+ goto free_sessions;
+ }
+
+ /* If the timer interval is set we are in live mode. */
+ if (session_live_mode) {
+ trace_path = build_live_path(session_name);
+ if (!trace_path) {
+ ret = CMD_ERROR;
+ goto free_sessions;
+ }
+ free_trace_path = true;
+ } else {
+ /* Get file system session path. */
+ trace_path = sessions[i].path;
+ }
+ } else {
+ trace_path = opt_trace_path;
+ }
+
+ MSG("Trace directory: %s\n", trace_path);
+
+ ret = spawn_viewer(trace_path, opt_viewer, session_live_mode);
+ if (ret < 0) {
+ /* Don't set ret so lttng can interpret the sessiond error. */
+ goto free_sessions;
+ }
+
+free_sessions:
+ if (session_live_mode && free_trace_path) {
+ free(trace_path);
+ }
+ free(sessions);
+free_error:
+ if (opt_session_name == NULL) {
+ free(session_name);
+ }
+error:
+ return ret;
+}
+
+/*
+ * The 'view <options>' first level command
+ */
+int cmd_view(int argc, const char **argv)
+{
+ int opt, ret = CMD_SUCCESS;
+ static poptContext pc;
+ const char *leftover = NULL;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ if (lttng_opt_mi) {
+ WARN("mi does not apply to view command");
+ }
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ SHOW_HELP();
+ goto end;
+ case OPT_LIST_OPTIONS:
+ list_cmd_options(stdout, long_options);
+ goto end;
+ default:
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_session_name = (char*) poptGetArg(pc);
+
+ leftover = poptGetArg(pc);
+ if (leftover) {
+ ERR("Unknown argument: %s", leftover);
+ ret = CMD_ERROR;
+ goto end;
+ }
+
+ ret = view_trace();
+
+end:
+ poptFreeContext(pc);
+ return ret;
+}