+/*
+ * get_cmdline_by_pid
+ *
+ * Get command line from /proc for a specific pid.
+ *
+ * On success, return an allocated string pointer pointing to
+ * the proc cmdline.
+ * On error, return NULL.
+ */
+static char *get_cmdline_by_pid(pid_t pid)
+{
+ int ret;
+ FILE *fp;
+ char *cmdline = NULL;
+ char path[24]; /* Can't go bigger than /proc/65535/cmdline */
+
+ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ goto end;
+ }
+
+ /* Caller must free() *cmdline */
+ cmdline = malloc(PATH_MAX);
+ ret = fread(cmdline, 1, PATH_MAX, fp);
+ fclose(fp);
+
+end:
+ return cmdline;
+}
+
+/*
+ * validate_options
+ *
+ * Make sure that all options passed to the command line are compatible with
+ * each others.
+ *
+ * On error, return -1
+ * On success, return 0
+ */
+static int validate_options(void)
+{
+ /* If listing options, jump validation */
+ if (opt_list_apps || opt_list_session) {
+ goto end;
+ }
+ /* Conflicting command */
+ if (opt_start_trace && opt_stop_trace) {
+ ERR("Can't use --start and --stop together.");
+ goto error;
+ /* If no PID specified and trace_kernel is off */
+ } else if ((opt_trace_pid == 0 && !opt_trace_kernel) &&
+ (opt_create_trace || opt_start_trace || opt_stop_trace || opt_destroy_trace)) {
+ ERR("Please specify for which tracer (-k or -p PID).");
+ goto error;
+ /* List traces, we need a session name */
+ } else if (opt_list_traces && opt_session_name == NULL) {
+ ERR("Can't use -t without -s, --session option.");
+ goto error;
+ /* Can't set event for both kernel and userspace at the same time */
+ } else if (opt_event_list != NULL && (opt_trace_kernel && opt_trace_pid)) {
+ ERR("Please don't use --event for both kernel and userspace.\nOne at a time to enable events.");
+ goto error;
+ /* Don't need a trace name for kernel tracig */
+ } else if (opt_trace_name != NULL && opt_trace_kernel) {
+ ERR("For action on a kernel trace, please don't specify a trace name.");
+ goto error;
+ } else if (opt_destroy_trace && opt_session_name == NULL) {
+ ERR("Please specify a session in order to destroy a trace");
+ goto error;
+ } else if (opt_create_trace || opt_destroy_trace) {
+ /* Both kernel and user-space are denied for these options */
+ if (opt_trace_pid != 0 && opt_trace_kernel) {
+ ERR("Kernel and user-space trace creation and destruction can't be used together.");
+ goto error;
+ /* Need a trace name for user-space tracing */
+ } else if (opt_trace_name == NULL && opt_trace_pid != 0) {
+ ERR("Please specify a trace name for user-space tracing");
+ goto error;
+ }
+ } else if (opt_stop_trace && opt_trace_pid != 0 && opt_trace_name == NULL) {
+ ERR("Please specify a trace name for user-space tracing");
+ goto error;
+ }
+
+ /* If start trace, auto start tracing */
+ if (opt_start_trace) {
+ DBG("Requesting auto tracing");
+ auto_trace = 1;
+ }
+
+ /* If no session, auto create one */
+ if (opt_session_name == NULL) {
+ DBG("Requesting an auto session creation");
+ auto_session = 1;
+ }
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * spawn_sessiond
+ *
+ * Spawn a session daemon by forking and execv.
+ */
+static int spawn_sessiond(char *pathname)
+{
+ int ret = 0;
+ pid_t pid;
+
+ MSG("Spawning session daemon");
+ pid = fork();
+ if (pid == 0) {
+ /*
+ * Spawn session daemon and tell
+ * it to signal us when ready.
+ */
+ execlp(pathname, "ltt-sessiond", "--sig-parent", "--quiet", NULL);
+ /* execlp only returns if error happened */
+ if (errno == ENOENT) {
+ ERR("No session daemon found. Use --sessiond-path.");
+ } else {
+ perror("execlp");
+ }
+ kill(getppid(), SIGTERM); /* unpause parent */
+ exit(EXIT_FAILURE);
+ } else if (pid > 0) {
+ /* Wait for ltt-sessiond to start */
+ pause();
+ goto end;
+ } else {
+ perror("fork");
+ ret = -1;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+