move ltt-control out of trunk/ltt-control
[ltt-control.git] / trunk / ltt-control / lttctl / lttctl.c
diff --git a/trunk/ltt-control/lttctl/lttctl.c b/trunk/ltt-control/lttctl/lttctl.c
deleted file mode 100644 (file)
index e08280a..0000000
+++ /dev/null
@@ -1,833 +0,0 @@
-/* lttctl
- *
- * Linux Trace Toolkit Control
- *
- * Small program that controls LTT through libltt.
- *
- * Copyright 2005 -
- *     Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
- *
- * Copyright 2008 FUJITSU
- *     Zhao Lei <zhaolei@cn.fujitsu.com>
- *     Gui Jianfeng <guijianfeng@cn.fujitsu.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <liblttctl/lttctl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <string.h>
-#include <limits.h>
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#define OPT_MAX                        (1024)
-#define OPT_NAMELEN            (256)
-#define OPT_VALSTRINGLEN       (256)
-
-enum opt_type {
-       CHANNEL,
-};
-
-struct channel_option {
-       char chan_name[OPT_NAMELEN];
-       int enable;
-       int overwrite;
-       int bufnum;
-       int bufsize;
-};
-
-struct lttctl_option {
-       union {
-               struct channel_option chan_opt;
-       } opt_mode;
-       enum opt_type type;
-       struct lttctl_option *next;
-};
-
-struct lttctl_option *opt_head, *last_opt;
-
-static int opt_create;
-static int opt_destroy;
-static int opt_start;
-static int opt_pause;
-static int opt_help;
-static const char *opt_transport;
-static const char *opt_write;
-static int opt_append;
-static unsigned int opt_dump_threads;
-static char channel_root_default[PATH_MAX];
-static const char *opt_channel_root;
-static const char *opt_tracename;
-
-/* Args :
- *
- */
-static void show_arguments(void)
-{
-       printf("Linux Trace Toolkit Trace Control " VERSION"\n");
-       printf("\n");
-       printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
-       printf("\n");
-       printf("Examples:\n");
-       printf("  lttctl -c trace1                 "
-               "# Create a trace named trace1.\n");
-       printf("  lttctl -s trace1                 "
-               "# start a trace named trace1.\n");
-       printf("  lttctl -p trace1                 "
-               "# pause a trace named trace1.\n");
-       printf("  lttctl -d trace1                 "
-               "# Destroy a trace named trace1.\n");
-       printf("  lttctl -C -w /tmp/trace1 trace1  "
-               "# Create a trace named trace1, start it and\n"
-               "                                   "
-               "# write non-overwrite channels' data to\n"
-               "                                   "
-               "# /tmp/trace1, debugfs must be mounted for\n"
-               "                                   "
-               "# auto-find\n");
-       printf("  lttctl -D -w /tmp/trace1 trace1  "
-               "# Pause and destroy a trace named trace1 and\n"
-               "                                   "
-               "# write overwrite channels' data to\n"
-               "                                   "
-               "# /tmp/trace1, debugfs must be mounted for\n"
-               "                                   "
-               "# auto-find\n");
-       printf("\n");
-       printf(" Basic options:\n");
-       printf("  -c, --create\n");
-       printf("        Create a trace.\n");
-       printf("  -d, --destroy\n");
-       printf("        Destroy a trace.\n");
-       printf("  -s, --start\n");
-       printf("        Start a trace.\n");
-       printf("  -p, --pause\n");
-       printf("        Pause a trace.\n");
-       printf("  -h, --help\n");
-       printf("        Show this help.\n");
-       printf("\n");
-       printf(" Advanced options:\n");
-       printf("  --transport TRANSPORT\n");
-       printf("        Set trace's transport. (ex. relay-locked or relay)\n");
-       printf("  -o, --option OPTION\n");
-       printf("        Set options, following operations are supported:\n");
-       printf("        channel.<channelname>.enable=\n");
-       printf("        channel.<channelname>.overwrite=\n");
-       printf("        channel.<channelname>.bufnum=\n");
-       printf("        channel.<channelname>.bufsize= (in bytes, rounded to "
-              "next power of 2)\n");
-       printf("        <channelname> can be set to all for all channels\n");
-       printf("\n");
-       printf(" Integration options:\n");
-       printf("  -C, --create_start\n");
-       printf("        Create and start a trace.\n");
-       printf("  -D, --pause_destroy\n");
-       printf("        Pause and destroy a trace.\n");
-       printf("  -w, --write PATH\n");
-       printf("        Path for write trace datas.\n");
-       printf("        For -c, -C, -d, -D options\n");
-       printf("  -a, --append\n");
-       printf("        Append to trace, For -w option\n");
-       printf("  -n, --dump_threads NUMBER\n");
-       printf("        Number of lttd threads, For -w option\n");
-       printf("  --channel_root PATH\n");
-       printf("        Set channels root path, For -w option."
-               " (ex. /mnt/debugfs/ltt)\n");
-       printf("\n");
-}
-
-/*
- * Separate option name to 3 fields
- * Ex:
- *  Input: name = channel.cpu.bufsize
- *  Output: name1 = channel
- *          name2 = cpu
- *          name3 = bufsize
- *  Ret: 0 on success
- *       1 on fail
- *
- * Note:
- *  Make sure that name1~3 longer than OPT_NAMELEN.
- *  name1~3 can be NULL to discard value
- *
- */
-static int separate_opt(const char *name, char *name1, char *name2, char *name3)
-{
-       char *p;
-
-       if (!name)
-               return 1;
-
-       /* segment1 */
-       p = strchr(name, '.');
-       if (!p)
-               return 1;
-       if (p - name >= OPT_NAMELEN)
-               return 1;
-       if (name1) {
-               memcpy(name1, name, p - name);
-               name1[p - name] = 0;
-       }
-       name = p + 1;
-
-       /* segment2 */
-       p = strchr(name, '.');
-       if (!p)
-               return 1;
-       if (p - name >= OPT_NAMELEN)
-               return 1;
-       if (name2) {
-               memcpy(name2, name, p - name);
-               name2[p - name] = 0;
-       }
-       name = p + 1;
-
-       /* segment3 */
-       if (strlen(name) >= OPT_NAMELEN)
-               return 1;
-       if (name3)
-               strcpy(name3, name);
-
-       return 0;
-}
-
-static void init_channel_opt(struct channel_option *opt, char *opt_name)
-{
-       if (opt && opt_name) {
-               opt->enable = -1;
-               opt->overwrite = -1;
-               opt->bufnum = -1;
-               opt->bufsize = -1;
-               strcpy(opt->chan_name, opt_name);
-       }
-}
-
-static struct lttctl_option *find_insert_channel_opt(char *opt_name)
-{
-       struct lttctl_option *iter, *new_opt;
-
-       if (!opt_head) {
-               opt_head = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
-               init_channel_opt(&opt_head->opt_mode.chan_opt, opt_name);
-               opt_head->type = CHANNEL;
-               opt_head->next = NULL;
-               last_opt = opt_head;
-               return opt_head;
-       }
-
-       for (iter = opt_head; iter; iter = iter->next) {
-               if (iter->type != CHANNEL)
-                       continue;
-               if (!strcmp(iter->opt_mode.chan_opt.chan_name, opt_name))
-                       return iter;
-       }
-
-       new_opt = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
-       init_channel_opt(&new_opt->opt_mode.chan_opt, opt_name);
-       new_opt->type = CHANNEL;
-       new_opt->next = NULL;
-       last_opt->next = new_opt;
-       last_opt = new_opt;
-       return new_opt;
-}
-
-int set_channel_opt(struct channel_option *opt, char *opt_name, char *opt_valstr)
-{
-       int opt_val, ret;
-
-       if (!strcmp("enable", opt_name)) {
-               if (opt_valstr[1] != 0) {
-                       return -EINVAL;
-               }
-               if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
-                   || opt_valstr[0] == '1')
-                       opt_val = 1;
-               else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
-                        || opt_valstr[0] == '0')
-                       opt_val = 0;
-               else {
-                       return -EINVAL;
-               }
-
-               opt->enable = opt_val;
-               return 0;
-       } else if (!strcmp("overwrite", opt_name)) {
-               if (opt_valstr[1] != 0) {
-                       return -EINVAL;
-               }
-               if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
-                   || opt_valstr[0] == '1')
-                       opt_val = 1;
-               else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
-                        || opt_valstr[0] == '0')
-                       opt_val = 0;
-               else {
-                       return -EINVAL;
-               }
-
-               opt->overwrite = opt_val;
-               return 0;
-
-       } else if (!strcmp("bufnum", opt_name)) {
-               ret = sscanf(opt_valstr, "%d", &opt_val);
-               if (ret != 1 || opt_val < 0) {
-                       return -EINVAL;
-               }
-               
-               opt->bufnum = opt_val;
-               return 0;
-       } else if (!strcmp("bufsize", opt_name)) {
-               ret = sscanf(opt_valstr, "%d", &opt_val);
-               if (ret != 1 || opt_val < 0) {
-                       return -EINVAL;
-               }
-               
-               opt->bufsize = opt_val;
-               return 0;
-       } else {
-               return -EINVAL;
-       }
-
-}
-
-static int parst_opt(const char *optarg)
-{
-       int ret;
-       char opt_name[OPT_NAMELEN * 3];
-       char opt_valstr[OPT_VALSTRINGLEN];
-       char *p;
-
-       char name1[OPT_NAMELEN];
-       char name2[OPT_NAMELEN];
-       char name3[OPT_NAMELEN];
-
-       int opt_intval;
-       int opt_val;
-       unsigned int opt_uintval;
-       struct lttctl_option *opt;
-
-       if (!optarg) {
-               fprintf(stderr, "Option empty\n");
-               return -EINVAL;
-       }
-
-       /* Get option name and val_str */
-       p = strchr(optarg, '=');
-       if (!p) {
-               fprintf(stderr, "Option format error: %s\n", optarg);
-               return -EINVAL;
-       }
-
-       if (p - optarg >= sizeof(opt_name)/sizeof(opt_name[0])) {
-               fprintf(stderr, "Option name too long: %s\n", optarg);
-               return -EINVAL;
-       }
-
-       if (strlen(p+1) >= OPT_VALSTRINGLEN) {
-               fprintf(stderr, "Option value too long: %s\n", optarg);
-               return -EINVAL;
-       }
-
-       memcpy(opt_name, optarg, p - optarg);
-       opt_name[p - optarg] = 0;
-       strcpy(opt_valstr, p+1);
-
-       /* separate option name into 3 fields */
-       ret = separate_opt(opt_name, name1, name2, name3);
-       if (ret != 0) {
-               fprintf(stderr, "Option name error1: %s\n", optarg);
-               return -EINVAL;
-       }
-       
-       if (!strcmp("channel", name1)) {
-               opt = find_insert_channel_opt(name2);
-               if ((ret = set_channel_opt(&opt->opt_mode.chan_opt, 
-                                          name3, opt_valstr) != 0)) {
-                       fprintf(stderr, "Option name error2: %s\n", optarg);
-                       return ret;
-               }
-       } else {
-               fprintf(stderr, "Option name error3: %s\n", optarg);
-               return -EINVAL;
-       }
-       
-       return 0;
-}
-
-/* parse_arguments
- *
- * Parses the command line arguments.
- *
- * Returns -1 if the arguments were correct, but doesn't ask for program
- * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
- */
-static int parse_arguments(int argc, char **argv)
-{
-       int ret = 0;
-       
-       static struct option longopts[] = {
-               {"create",              no_argument,            NULL,   'c'},
-               {"destroy",             no_argument,            NULL,   'd'},
-               {"start",               no_argument,            NULL,   's'},
-               {"pause",               no_argument,            NULL,   'p'},
-               {"help",                no_argument,            NULL,   'h'},
-               {"transport",           required_argument,      NULL,   2},
-               {"option",              required_argument,      NULL,   'o'},
-               {"create_start",        no_argument,            NULL,   'C'},
-               {"pause_destroy",       no_argument,            NULL,   'D'},
-               {"write",               required_argument,      NULL,   'w'},
-               {"append",              no_argument,            NULL,   'a'},
-               {"dump_threads",        required_argument,      NULL,   'n'},
-               {"channel_root",        required_argument,      NULL,   3},
-               { NULL,                 0,                      NULL,   0 },
-       };
-
-       /*
-        * Enable all channels in default
-        * To make novice users happy
-        */
-       parst_opt("channel.all.enable=1");
-
-       opterr = 1; /* Print error message on getopt_long */
-       while (1) {
-               int c;
-               c = getopt_long(argc, argv, "cdspho:CDw:an:", longopts, NULL);
-               if (-1 == c) {
-                       /* parse end */
-                       break;
-               }
-               switch (c) {
-               case 'c':
-                       opt_create = 1;
-                       break;
-               case 'd':
-                       opt_destroy = 1;
-                       break;
-               case 's':
-                       opt_start = 1;
-                       break;
-               case 'p':
-                       opt_pause = 1;
-                       break;
-               case 'h':
-                       opt_help = 1;
-                       break;
-               case 2:
-                       if (!opt_transport) {
-                               opt_transport = optarg;
-                       } else {
-                               fprintf(stderr,
-                                       "Please specify only 1 transport\n");
-                               return -EINVAL;
-                       }
-                       break;
-               case 'o':
-                       ret = parst_opt(optarg);
-                       if (ret)
-                               return ret;
-                       break;
-               case 'C':
-                       opt_create = 1;
-                       opt_start = 1;
-                       break;
-               case 'D':
-                       opt_pause = 1;
-                       opt_destroy = 1;
-                       break;
-               case 'w':
-                       if (!opt_write) {
-                               opt_write = optarg;
-                       } else {
-                               fprintf(stderr,
-                                       "Please specify only 1 write dir\n");
-                               return -EINVAL;
-                       }
-                       break;
-               case 'a':
-                       opt_append = 1;
-                       break;
-               case 'n':
-                       if (opt_dump_threads) {
-                               fprintf(stderr,
-                                       "Please specify only 1 dump threads\n");
-                               return -EINVAL;
-                       }
-
-                       ret = sscanf(optarg, "%u", &opt_dump_threads);
-                       if (ret != 1) {
-                               fprintf(stderr,
-                                       "Dump threads not positive number\n");
-                               return -EINVAL;
-                       }
-                       break;
-               case 3:
-                       if (!opt_channel_root) {
-                               opt_channel_root = optarg;
-                       } else {
-                               fprintf(stderr,
-                                       "Please specify only 1 channel root\n");
-                               return -EINVAL;
-                       }
-                       break;
-               case '?':
-                       return -EINVAL;
-               default:
-                       break;
-               };
-       };
-
-       /* Don't check args when user needs help */
-       if (opt_help)
-               return 0;
-
-       /* Get tracename */
-       if (optind < argc - 1) {
-               fprintf(stderr, "Please specify only 1 trace name\n");
-               return -EINVAL;
-       }
-       if (optind > argc - 1) {
-               fprintf(stderr, "Please specify trace name\n");
-               return -EINVAL;
-       }
-       opt_tracename = argv[optind];
-
-       /*
-        * Check arguments
-        */
-       if (!opt_create && !opt_start && !opt_destroy && !opt_pause) {
-               fprintf(stderr,
-                       "Please specify a option of "
-                       "create, destroy, start, or pause\n");
-               return -EINVAL;
-       }
-
-       if ((opt_create || opt_start) && (opt_destroy || opt_pause)) {
-               fprintf(stderr,
-                       "Create and start conflict with destroy and pause\n");
-               return -EINVAL;
-       }
-
-       if (opt_create) {
-               if (!opt_transport)
-                       opt_transport = "relay";
-       }
-
-       if (opt_transport) {
-               if (!opt_create) {
-                       fprintf(stderr,
-                               "Transport option must be combine with create"
-                               " option\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (opt_write) {
-               if (!opt_create && !opt_destroy) {
-                       fprintf(stderr,
-                               "Write option must be combine with create or"
-                               " destroy option\n");
-                       return -EINVAL;
-               }
-
-               if (!opt_channel_root)
-                       if (getdebugfsmntdir(channel_root_default) == 0) {
-                               strcat(channel_root_default, "/ltt");
-                               opt_channel_root = channel_root_default;
-                       } else {
-                               fprintf(stderr,
-                                       "Channel_root is necessary for -w"
-                                       " option, but neither --channel_root"
-                                       " option\n"
-                                       "specified, nor debugfs's mount dir"
-                                       " found, mount debugfs also failed\n");
-                               return -EINVAL;
-                       }
-
-               if (opt_dump_threads == 0)
-                       opt_dump_threads = 1;
-       }
-
-       if (opt_append) {
-               if (!opt_write) {
-                       fprintf(stderr,
-                               "Append option must be combine with write"
-                               " option\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (opt_dump_threads) {
-               if (!opt_write) {
-                       fprintf(stderr,
-                               "Dump_threads option must be combine with write"
-                               " option\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (opt_channel_root) {
-               if (!opt_write) {
-                       fprintf(stderr,
-                               "Channel_root option must be combine with write"
-                               " option\n");
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-static void show_info(void)
-{
-       printf("Linux Trace Toolkit Trace Control " VERSION"\n");
-       printf("\n");
-       if (opt_tracename != NULL) {
-               printf("Controlling trace : %s\n", opt_tracename);
-               printf("\n");
-       }
-}
-
-static int lttctl_channel_setup(struct channel_option *opt)
-{
-       int ret;
-
-       if (opt->enable != -1) {
-               if ((ret = lttctl_set_channel_enable(opt_tracename,
-                                                    opt->chan_name,
-                                                    opt->enable)) != 0)
-                       return ret;
-       } 
-       if (opt->overwrite != -1) {
-               if ((ret = lttctl_set_channel_overwrite(opt_tracename,
-                                                       opt->chan_name,
-                                                       opt->overwrite)) != 0)
-                       return ret;
-       }
-       if (opt->bufnum != -1) {
-               if ((ret = lttctl_set_channel_subbuf_num(opt_tracename,
-                                                        opt->chan_name,
-                                                        opt->bufnum)) != 0)
-                       return ret;
-       }
-       if (opt->bufsize != -1) {
-               if ((ret = lttctl_set_channel_subbuf_size(opt_tracename,
-                                                         opt->chan_name,
-                                                         opt->bufsize)) != 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int lttctl_create_trace(void)
-{
-       int ret;
-       int i;
-       struct lttctl_option *opt;
-
-       ret = lttctl_setup_trace(opt_tracename);
-       if (ret)
-               goto setup_trace_fail;
-
-       for (opt = opt_head; opt; opt = opt->next) {
-               if (opt->type != CHANNEL)
-                       continue;
-               ret = lttctl_channel_setup(&opt->opt_mode.chan_opt);
-               if (ret)
-                       goto set_option_fail;;
-       }
-
-       ret = lttctl_set_trans(opt_tracename, opt_transport);
-       if (ret)
-               goto set_option_fail;
-
-       ret = lttctl_alloc_trace(opt_tracename);
-       if (ret)
-               goto alloc_trace_fail;
-
-       return 0;
-
-alloc_trace_fail:
-set_option_fail:
-       lttctl_destroy_trace(opt_tracename);
-setup_trace_fail:
-       return ret;
-}
-
-/*
- * Start a lttd daemon to write trace datas
- * Dump overwrite channels on overwrite!=0
- * Dump normal(non-overwrite) channels on overwrite=0
- *
- * ret: 0 on success
- *      !0 on fail
- */
-static int lttctl_daemon(int overwrite)
-{
-       pid_t pid;
-       int status;
-
-       pid = fork();
-       if (pid < 0) {
-               perror("Error in forking for lttd daemon");
-               return errno;
-       }
-
-       if (pid == 0) {
-               /* child */
-               char *argv[16];
-               int argc = 0;
-               char channel_path[PATH_MAX];
-               char thread_num[16];
-
-               /* prog path */
-               argv[argc] = getenv("LTT_DAEMON");
-               if (argv[argc] == NULL)
-                       argv[argc] = PACKAGE_BIN_DIR "/lttd";
-               argc++;
-
-               /* -t option */
-               argv[argc] = "-t";
-               argc++;
-               /*
-                * we allow modify of opt_write's content in new process
-                * for get rid of warning of assign char * to const char *
-                */
-               argv[argc] = (char *)opt_write;
-               argc++;
-
-               /* -c option */
-               strcpy(channel_path, opt_channel_root);
-               strcat(channel_path, "/");
-               strcat(channel_path, opt_tracename);
-               argv[argc] = "-c";
-               argc++;
-               argv[argc] = channel_path;
-               argc++;
-
-               /* -N option */
-               sprintf(thread_num, "%u", opt_dump_threads);
-               argv[argc] = "-N";
-               argc++;
-               argv[argc] = thread_num;
-               argc++;
-
-               /* -a option */
-               if (opt_append) {
-                       argv[argc] = "-a";
-                       argc++;
-               }
-
-               /* -d option */
-               argv[argc] = "-d";
-               argc++;
-
-               /* overwrite option */
-               if (overwrite) {
-                       argv[argc] = "-f";
-                       argc++;
-               } else {
-                       argv[argc] = "-n";
-                       argc++;
-               }
-
-               argv[argc] = NULL;
-
-               execvp(argv[0], argv);
-
-               perror("Error in executing the lttd daemon");
-               exit(errno);
-       }
-
-       /* parent */
-       if (waitpid(pid, &status, 0) == -1) {
-               perror("Error in waitpid\n");
-               return errno;
-       }
-
-       if (!WIFEXITED(status)) {
-               fprintf(stderr, "lttd process interrupted\n");
-               return status;
-       }
-
-       if (WEXITSTATUS(status))
-               fprintf(stderr, "lttd process running failed\n");
-
-       return WEXITSTATUS(status);
-}
-
-int main(int argc, char **argv)
-{
-       int ret;
-
-       ret = parse_arguments(argc, argv);
-       /* If user needs show help, we disregard other options */
-       if (opt_help) {
-               show_arguments();
-               return 0;
-       }
-
-       /* exit program if arguments wrong */
-       if (ret)
-               return 1;
-
-       show_info();
-
-       ret = lttctl_init();
-       if (ret != 0)
-               return ret;
-
-       if (opt_create) {
-               printf("lttctl: Creating trace\n");
-               ret = lttctl_create_trace();
-               if (ret)
-                       goto op_fail;
-
-               if (opt_write) {
-                       printf("lttctl: Forking lttd\n");
-                       ret = lttctl_daemon(0);
-                       if (ret)
-                               goto op_fail;
-               }
-       }
-
-       if (opt_start) {
-               printf("lttctl: Starting trace\n");
-               ret = lttctl_start(opt_tracename);
-               if (ret)
-                       goto op_fail;
-       }
-
-       if (opt_pause) {
-               printf("lttctl: Pausing trace\n");
-               ret = lttctl_pause(opt_tracename);
-               if (ret)
-                       goto op_fail;
-       }
-
-       if (opt_destroy) {
-               if (opt_write) {
-                       printf("lttctl: Forking lttd\n");
-                       ret = lttctl_daemon(1);
-                       if (ret)
-                               goto op_fail;
-               }
-
-               printf("lttctl: Destroying trace\n");
-               ret = lttctl_destroy_trace(opt_tracename);
-               if (ret)
-                       goto op_fail;
-       }
-
-op_fail:
-       lttctl_destroy();
-
-       return ret;
-}
This page took 0.03218 seconds and 4 git commands to generate.