[ltt-dev] [UST PATCH] ustctl cli rewrite

David Goulet david.goulet at polymtl.ca
Mon Jan 10 11:28:30 EST 2011



On 11-01-10 11:25 AM, Nils Carlson wrote:
> You mean, why not create a list somewhere in the program containing all
> structs that my macros generate?
>
> Mostly because this way I don't have to... This way scales better, you
> just add new commands by writing the function and including it in the
> macro.
>
> Do you see any reason to create a static list?

Not really. Actually, it's quite ingenious and very easy to implement 
new command that way. I was just wondering if there was any "precise 
reason" for that.

Don't you think however that the new command definition should be in a 
header file (ustctl.h or command.h or ...) because right now, it's 
difficult for someone (code developer) to go through the already define 
command quickly and, for now, it makes ustctl.c quite big. (We will have 
to previously define all function prototype before.. but a small cost 
for clarity)... Just a thought.

I agree to ack this patch but before, we should at least put some 
comments before you merge it. (at least in cli.h to explain the macro 
and other structure like cli_arg_ops and cli_cmd).

Thanks!
David

>
> /Nils
>
> On Mon, 10 Jan 2011, David Goulet wrote:
>
>> Hey Nils,
>>
>> I'm wondering why you choose to define each command through a section
>> (__cli_cmds) and generate them at runtime. Is there a reason why you
>> choose *not* to create the command list statically instead of the malloc
>> you use in your "constructor"?
>>
>> Thanks
>> David
>>
>> On 11-01-07 10:38 AM, Nils Carlson wrote:
>>> This is a first attempt, man and info still need to be updated. I wanted
>>> to get the structure in place before we start adding new commands.
>>>
>>> Commands no longer accept a list of pids, instead enable/disable-marker
>>> can accept a list of markers.
>>>
>>> Are the cli.h and cli.c something that could be re-used for LTTng?
>>>
>>> /Nils
>>>
>>> Nils Carlson wrote:
>>>> Completely re-write the ustctl cli making it behave in a similar
>>>> fashion to git. This makes more sense than using long-options
>>>> as commands.
>>>>
>>>> Signed-off-by: Nils Carlson <nils.carlson at ericsson.com>
>>>> ---
>>>> ustctl/Makefile.am | 2 +-
>>>> ustctl/cli.c | 202 ++++++++++++
>>>> ustctl/cli.h | 59 ++++
>>>> ustctl/ustctl.c | 896
>>>> +++++++++++++++++++++++++++++-----------------------
>>>> 4 files changed, 769 insertions(+), 390 deletions(-)
>>>> create mode 100644 ustctl/cli.c
>>>> create mode 100644 ustctl/cli.h
>>>>
>>>> diff --git a/ustctl/Makefile.am b/ustctl/Makefile.am
>>>> index 49e46f0..20320eb 100644
>>>> --- a/ustctl/Makefile.am
>>>> +++ b/ustctl/Makefile.am
>>>> @@ -5,7 +5,7 @@ AM_CFLAGS = -fno-strict-aliasing
>>>> bin_PROGRAMS = ustctl
>>>>
>>>> ustctl_SOURCES = \
>>>> - ustctl.c
>>>> + ustctl.c cli.c cli.h
>>>>
>>>> ustctl_CFLAGS = -DUST_COMPONENT=ustctl -fno-strict-aliasing
>>>>
>>>> diff --git a/ustctl/cli.c b/ustctl/cli.c
>>>> new file mode 100644
>>>> index 0000000..3b14174
>>>> --- /dev/null
>>>> +++ b/ustctl/cli.c
>>>> @@ -0,0 +1,202 @@
>>>> +/* Copyright (C) 2011 Ericsson AB, Nils Carlson
>>>> <nils.carlson at ericsson.com>
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2.1 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, write to the Free Software
>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>>> 02110-1301 USA
>>>> + */
>>>> +
>>>> +#define _GNU_SOURCE
>>>> +#include <stdio.h>
>>>> +#include <stdlib.h>
>>>> +#include <string.h>
>>>> +#include "cli.h"
>>>> +
>>>> +/* This dummy command is needed to create the sections in cli.o before
>>>> + * other .o files have these sections, usefull for development.
>>>> + */
>>>> +static int _dummy(int argc, char *argv[]) {
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(_dummy,
>>>> + "_dummy",
>>>> + NULL,
>>>> + NULL,
>>>> + 0,
>>>> + 0);
>>>> +
>>>> +
>>>> +extern struct cli_cmd __start___cli_cmds[]
>>>> __attribute__((visibility("hidden")));
>>>> +extern struct cli_cmd __stop___cli_cmds[]
>>>> __attribute__((visibility("hidden")));
>>>> +
>>>> +static struct cli_cmd **cli_cmd_list;
>>>> +static int cli_cmd_list_size;
>>>> +
>>>> +static char *process_name;
>>>> +
>>>> +static int compute_cli_cmds_size(void)
>>>> +{
>>>> + long cli_cmds_start, cli_cmds_end;
>>>> +
>>>> + cli_cmds_start = (long)__start___cli_cmds;
>>>> + cli_cmds_end = (long)__stop___cli_cmds;
>>>> +
>>>> + return (cli_cmds_end - cli_cmds_start) / sizeof(struct cli_cmd);
>>>> +}
>>>> +
>>>> +static void __attribute__((constructor)) generate_cli_cmd_list(int
>>>> argc, char *argv[])
>>>> +{
>>>> + struct cli_cmd *cli_cmd;
>>>> + int section_size, i;
>>>> +
>>>> + process_name = basename(argv[0]);
>>>> +
>>>> + section_size = compute_cli_cmds_size();
>>>> +
>>>> + cli_cmd_list = malloc(section_size * sizeof(void *));
>>>> + if (!cli_cmd_list) {
>>>> + fprintf(stderr, "Failed to allocate command list!");
>>>> + exit(EXIT_FAILURE);
>>>> + }
>>>> +
>>>> + cli_cmd_list_size = 0;
>>>> +
>>>> + cli_cmd = __start___cli_cmds;
>>>> + for (i = 0; i < section_size; i++) {
>>>> + if (&cli_cmd[i] == &__dummy_cli_cmd) {
>>>> + continue;
>>>> + }
>>>> +
>>>> + if (cli_cmd[i].name) {
>>>> + cli_cmd_list[cli_cmd_list_size++] = &cli_cmd[i];
>>>> + }
>>>> + }
>>>> +}
>>>> +
>>>> +struct cli_cmd *find_cli_cmd(const char *command)
>>>> +{
>>>> + int i;
>>>> +
>>>> + for (i = 0; i < cli_cmd_list_size; i++) {
>>>> + if (!strcmp(cli_cmd_list[i]->name, command)) {
>>>> + return cli_cmd_list[i];
>>>> + }
>>>> + }
>>>> +
>>>> + return NULL;
>>>> +}
>>>> +
>>>> +static int cmpcli_cmds(const void *p1, const void *p2)
>>>> +{
>>>> + return strcmp(* (char * const *) ((struct cli_cmd *)p1)->name,
>>>> + * (char * const *) ((struct cli_cmd *)p2)->name);
>>>> +}
>>>> +
>>>> +#define HELP_BUFFER_SIZE 4096
>>>> +
>>>> +static void print_cmd_help(const char *prefix, const char *infix,
>>>> + struct cli_cmd *cli_cmd)
>>>> +{
>>>> + if (cli_cmd->help_text) {
>>>> + fprintf(stderr, "%s%s%s",
>>>> + prefix,
>>>> + infix,
>>>> + cli_cmd->help_text);
>>>> + } else if (cli_cmd->description) {
>>>> + fprintf(stderr, "%s%s%s\n%s\n",
>>>> + prefix,
>>>> + infix,
>>>> + cli_cmd->name,
>>>> + cli_cmd->description);
>>>> + } else {
>>>> + fprintf(stderr, "No help available for %s\n",
>>>> + cli_cmd->name);
>>>> + }
>>>> +}
>>>> +
>>>> +void list_cli_cmds(int option)
>>>> +{
>>>> + int i;
>>>> +
>>>> + qsort(cli_cmd_list, cli_cmd_list_size, sizeof(void *), cmpcli_cmds);
>>>> +
>>>> + for (i = 0; i < cli_cmd_list_size; i++) {
>>>> + switch (option) {
>>>> + case CLI_SIMPLE_LIST:
>>>> + fprintf(stderr, "%s ", cli_cmd_list[i]->name);
>>>> + break;
>>>> + case CLI_DESCRIPTIVE_LIST:
>>>> + fprintf(stderr, " %-25s%s\n", cli_cmd_list[i]->name,
>>>> + cli_cmd_list[i]->description);
>>>> + break;
>>>> + case CLI_EXTENDED_LIST:
>>>> + print_cmd_help("", "", cli_cmd_list[i]);
>>>> + fprintf(stderr, "\n");
>>>> + break;
>>>> + }
>>>> + }
>>>> +
>>>> + if (option == CLI_SIMPLE_LIST) {
>>>> + fprintf(stderr, "\n");
>>>> + }
>>>> +}
>>>> +
>>>> +int cli_print_help(const char *command)
>>>> +{
>>>> + struct cli_cmd *cli_cmd;
>>>> +
>>>> + cli_cmd = find_cli_cmd(command);
>>>> + if (!cli_cmd) {
>>>> + return -1;
>>>> + }
>>>> +
>>>> + print_cmd_help(process_name, " ", cli_cmd);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void cli_check_argc(const char *command, int args,
>>>> + int operator, int desired_args)
>>>> +{
>>>> + switch(operator) {
>>>> + case CLI_EQ:
>>>> + if (args != desired_args)
>>>> + goto print_error;
>>>> + break;
>>>> + case CLI_GE:
>>>> + if (args < desired_args)
>>>> + goto print_error;
>>>> + break;
>>>> + }
>>>> +
>>>> + return;
>>>> +
>>>> +print_error:
>>>> + fprintf(stderr, "%s %s requires %s%d argument%s, see usage.\n",
>>>> + process_name, command, operator == CLI_EQ ? "" : "at least ",
>>>> + desired_args, desired_args > 1 ? "s" : "");
>>>> + cli_print_help(command);
>>>> + exit(EXIT_FAILURE);
>>>> +}
>>>> +
>>>> +
>>>> +void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[])
>>>> +{
>>>> + cli_check_argc(cmd->name, argc - 1, cmd->args_op, cmd->desired_args);
>>>> +
>>>> + if (cmd->function(argc, argv)) {
>>>> + exit(EXIT_FAILURE);
>>>> + }
>>>> +
>>>> + exit(EXIT_SUCCESS);
>>>> +}
>>>> diff --git a/ustctl/cli.h b/ustctl/cli.h
>>>> new file mode 100644
>>>> index 0000000..2845fba
>>>> --- /dev/null
>>>> +++ b/ustctl/cli.h
>>>> @@ -0,0 +1,59 @@
>>>> +/* Copyright (C) 2011 Ericsson AB, Nils Carlson
>>>> <nils.carlson at ericsson.com>
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2.1 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, write to the Free Software
>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>>> 02110-1301 USA
>>>> + */
>>>> +#ifndef _CLI_H
>>>> +#define _CLI_H
>>>> +
>>>> +struct cli_cmd {
>>>> + const char *name;
>>>> + const char *description;
>>>> + const char *help_text;
>>>> + int (*function)(int, char **);
>>>> + int desired_args;
>>>> + int args_op;
>>>> +} __attribute__((aligned(8)));
>>>> +
>>>> +#define DEFINE_CLI_CMD(function, name, description, help, args,
>>>> args_op) \
>>>> + static struct cli_cmd _##function##_cli_cmd \
>>>> + __attribute__((section("__cli_cmds"), aligned(8), used)) = { \
>>>> + name, \
>>>> + description, \
>>>> + help, \
>>>> + function, \
>>>> + args, \
>>>> + args_op, \
>>>> + };
>>>> +
>>>> +struct cli_cmd *find_cli_cmd(const char *command);
>>>> +
>>>> +enum cli_list_opts {
>>>> + CLI_SIMPLE_LIST,
>>>> + CLI_DESCRIPTIVE_LIST,
>>>> + CLI_EXTENDED_LIST,
>>>> +};
>>>> +
>>>> +void list_cli_cmds(int option);
>>>> +
>>>> +int cli_print_help(const char *command);
>>>> +
>>>> +enum cli_arg_ops {
>>>> + CLI_EQ,
>>>> + CLI_GE,
>>>> +};
>>>> +
>>>> +void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[]);
>>>> +
>>>> +#endif /* _CLI_H */
>>>> diff --git a/ustctl/ustctl.c b/ustctl/ustctl.c
>>>> index aad3834..7475ebe 100644
>>>> --- a/ustctl/ustctl.c
>>>> +++ b/ustctl/ustctl.c
>>>> @@ -1,4 +1,5 @@
>>>> /* Copyright (C) 2009 Pierre-Marc Fournier
>>>> + * Copyright (C) 2011 Ericsson AB, Nils Carlson
>>>> <nils.carlson at ericsson.com>
>>>> *
>>>> * This library is free software; you can redistribute it and/or
>>>> * modify it under the terms of the GNU Lesser General Public
>>>> @@ -24,153 +25,27 @@
>>>>
>>>> #include "ust/ustcmd.h"
>>>> #include "usterr.h"
>>>> +#include "cli.h"
>>>>
>>>> -enum command {
>>>> - CREATE_TRACE=1000,
>>>> - ALLOC_TRACE,
>>>> - START_TRACE,
>>>> - STOP_TRACE,
>>>> - DESTROY_TRACE,
>>>> - LIST_MARKERS,
>>>> - LIST_TRACE_EVENTS,
>>>> - ENABLE_MARKER,
>>>> - DISABLE_MARKER,
>>>> - GET_ONLINE_PIDS,
>>>> - SET_SUBBUF_SIZE,
>>>> - SET_SUBBUF_NUM,
>>>> - GET_SUBBUF_SIZE,
>>>> - GET_SUBBUF_NUM,
>>>> - GET_SOCK_PATH,
>>>> - SET_SOCK_PATH,
>>>> - FORCE_SWITCH,
>>>> - UNKNOWN
>>>> -};
>>>> -
>>>> -struct ust_opts {
>>>> - enum command cmd;
>>>> - pid_t *pids;
>>>> - char *regex;
>>>> -};
>>>> -
>>>> -char *progname = NULL;
>>>> -
>>>> -void usage(void)
>>>> +void usage(const char *process_name)
>>>> {
>>>> - fprintf(stderr, "usage: %s COMMAND PIDs...\n", progname);
>>>> - fprintf(stderr, "\nControl the tracing of a process that supports
>>>> LTTng Userspace Tracing.\n\
>>>> -\n\
>>>> -Commands:\n\
>>>> - --create-trace\t\t\tCreate trace\n\
>>>> - --alloc-trace\t\t\tAlloc trace\n\
>>>> - --start-trace\t\t\tStart tracing\n\
>>>> - --stop-trace\t\t\tStop tracing\n\
>>>> - --destroy-trace\t\t\tDestroy the trace\n\
>>>> - --set-subbuf-size \"CHANNEL/bytes\"\tSet the size of subbuffers per
>>>> channel\n\
>>>> - --set-subbuf-num \"CHANNEL/n\"\tSet the number of subbuffers per
>>>> channel\n\
>>>> - --set-sock-path\t\t\tSet the path of the daemon socket\n\
>>>> - --get-subbuf-size \"CHANNEL\"\t\tGet the size of subbuffers per
>>>> channel\n\
>>>> - --get-subbuf-num \"CHANNEL\"\t\tGet the number of subbuffers per
>>>> channel\n\
>>>> - --get-sock-path\t\t\tGet the path of the daemon socket\n\
>>>> - --enable-marker \"CHANNEL/MARKER\"\tEnable a marker\n\
>>>> - --disable-marker \"CHANNEL/MARKER\"\tDisable a marker\n\
>>>> - --list-markers\t\t\tList the markers of the process,
>>>> their\n\t\t\t\t\t state and format string\n\
>>>> - --list-trace-events\t\t\tList the trace-events of the process\n\
>>>> - --force-switch\t\t\tForce a subbuffer switch\n\
>>>> -\
>>>> -");
>>>> -}
>>>> -
>>>> -int parse_opts_long(int argc, char **argv, struct ust_opts *opts)
>>>> -{
>>>> - int c;
>>>> -
>>>> - opts->pids = NULL;
>>>> - opts->regex = NULL;
>>>> -
>>>> - while (1) {
>>>> - int option_index = 0;
>>>> - static struct option long_options[] = {
>>>> - { "create-trace", 0, 0, CREATE_TRACE },
>>>> - { "alloc-trace", 0, 0, ALLOC_TRACE },
>>>> - { "start-trace", 0, 0, START_TRACE },
>>>> - { "stop-trace", 0, 0, STOP_TRACE },
>>>> - { "destroy-trace", 0, 0, DESTROY_TRACE },
>>>> - { "list-markers", 0, 0, LIST_MARKERS },
>>>> - { "list-trace-events", 0, 0, LIST_TRACE_EVENTS},
>>>> - { "enable-marker", 1, 0, ENABLE_MARKER },
>>>> - { "disable-marker", 1, 0, DISABLE_MARKER },
>>>> - { "help", 0, 0, 'h' },
>>>> - { "online-pids", 0, 0, GET_ONLINE_PIDS },
>>>> - { "set-subbuf-size", 1, 0, SET_SUBBUF_SIZE },
>>>> - { "set-subbuf-num", 1, 0, SET_SUBBUF_NUM },
>>>> - { "get-subbuf-size", 1, 0, GET_SUBBUF_SIZE },
>>>> - { "get-subbuf-num", 1, 0, GET_SUBBUF_NUM },
>>>> - { "get-sock-path", 0, 0, GET_SOCK_PATH },
>>>> - { "set-sock-path", 1, 0, SET_SOCK_PATH },
>>>> - { "force-switch", 0, 0, FORCE_SWITCH },
>>>> - { 0, 0, 0, 0 }
>>>> - };
>>>> -
>>>> - c = getopt_long(argc, argv, "h", long_options, &option_index);
>>>> - if (c == -1)
>>>> - break;
>>>> -
>>>> - if(c >= 1000)
>>>> - opts->cmd = c;
>>>> -
>>>> - switch (c) {
>>>> - case 0:
>>>> - printf("option %s", long_options[option_index].name);
>>>> - if (optarg)
>>>> - printf(" with arg %s", optarg);
>>>> - printf("\n");
>>>> - break;
>>>> -
>>>> - case ENABLE_MARKER:
>>>> - case DISABLE_MARKER:
>>>> - case SET_SUBBUF_SIZE:
>>>> - case SET_SUBBUF_NUM:
>>>> - case GET_SUBBUF_SIZE:
>>>> - case GET_SUBBUF_NUM:
>>>> - case SET_SOCK_PATH:
>>>> - opts->regex = strdup(optarg);
>>>> - break;
>>>> -
>>>> - case 'h':
>>>> - usage();
>>>> - exit(0);
>>>> -
>>>> - case '?':
>>>> - fprintf(stderr, "Invalid argument\n\n");
>>>> - usage();
>>>> - exit(1);
>>>> - }
>>>> - }
>>>> -
>>>> - if (argc - optind > 0 && opts->cmd != GET_ONLINE_PIDS) {
>>>> - int i;
>>>> - int pididx=0;
>>>> - opts->pids = zmalloc((argc-optind+1) * sizeof(pid_t));
>>>> -
>>>> - for(i=optind; i<argc; i++) {
>>>> - /* don't take any chances, use a long long */
>>>> - long long tmp;
>>>> - char *endptr;
>>>> - tmp = strtoull(argv[i], &endptr, 10);
>>>> - if(*endptr != '\0') {
>>>> - ERR("The pid \"%s\" is invalid.", argv[i]);
>>>> - return 1;
>>>> - }
>>>> - opts->pids[pididx++] = (pid_t) tmp;
>>>> - }
>>>> - opts->pids[pididx] = -1;
>>>> - }
>>>> -
>>>> - return 0;
>>>> + fprintf(stderr, "Usage: %s COMMAND [ARGS]...\n", process_name);
>>>> + fprintf(stderr,
>>>> + "Control tracing within a process that supports UST,\n"
>>>> + " the Userspace Tracing libary\n"
>>>> + "Options:\n"
>>>> + " -h[<cmd>], --help[=<cmd>] "
>>>> + "help, for a command if provided\n"
>>>> + " -l, --list "
>>>> + "short list of commands\n"
>>>> + " -e, --extended-list "
>>>> + "extented list of commands with help\n"
>>>> + "Commands:\n");
>>>> + list_cli_cmds(CLI_DESCRIPTIVE_LIST);
>>>> }
>>>>
>>>> static int scan_ch_marker(const char *channel_marker, char **channel,
>>>> - char **marker)
>>>> + char **marker)
>>>> {
>>>> int result;
>>>>
>>>> @@ -191,9 +66,9 @@ static int scan_ch_marker(const char
>>>> *channel_marker, char **channel,
>>>> free(*marker);
>>>> }
>>>> return -1;
>>>> - } else {
>>>> - return 0;
>>>> }
>>>> +
>>>> + return 0;
>>>> }
>>>>
>>>> static int scan_ch_and_num(const char *ch_num, char **channel,
>>>> unsigned int *num)
>>>> @@ -214,286 +89,529 @@ static int scan_ch_and_num(const char *ch_num,
>>>> char **channel, unsigned int *num
>>>> }
>>>> return -1;
>>>> }
>>>> +
>>>> + return 0;
>>>> }
>>>>
>>>> char *trace = "auto";
>>>>
>>>> -int main(int argc, char *argv[])
>>>> +struct option options[] =
>>>> {
>>>> - pid_t *pidit;
>>>> - int result;
>>>> - int retval = EXIT_SUCCESS;
>>>> - char *tmp;
>>>> - struct ust_opts opts;
>>>> + {"help", 2, NULL, 'h'},
>>>> + {"list", 0, NULL, 'l'},
>>>> + {"extended-list", 0, NULL, 'e'},
>>>> + {NULL, 0, NULL, 0},
>>>> +};
>>>>
>>>> - progname = argv[0];
>>>> +int main(int argc, char *argv[])
>>>> +{
>>>> + struct cli_cmd *cli_cmd;
>>>> + int opt;
>>>>
>>>> if(argc <= 1) {
>>>> fprintf(stderr, "No operation specified.\n");
>>>> - usage();
>>>> + usage(argv[0]);
>>>> exit(EXIT_FAILURE);
>>>> }
>>>>
>>>> - result = parse_opts_long(argc, argv, &opts);
>>>> - if(result) {
>>>> - fprintf(stderr, "\n");
>>>> - usage();
>>>> - exit(EXIT_FAILURE);
>>>> + while ((opt = getopt_long(argc, argv, "+h::le",
>>>> + options, NULL)) != -1) {
>>>> + switch (opt) {
>>>> + case 'h':
>>>> + if (!optarg) {
>>>> + usage(argv[0]);
>>>> + } else {
>>>> + if (cli_print_help(optarg)) {
>>>> + fprintf(stderr, "No such command %s\n",
>>>> + optarg);
>>>> + }
>>>> + }
>>>> + exit(EXIT_FAILURE);
>>>> + break;
>>>> + case 'l':
>>>> + list_cli_cmds(CLI_SIMPLE_LIST);
>>>> + exit(EXIT_FAILURE);
>>>> + break;
>>>> + case 'e':
>>>> + list_cli_cmds(CLI_EXTENDED_LIST);
>>>> + exit(EXIT_FAILURE);
>>>> + default:
>>>> + fprintf(stderr, "Unknown option\n");
>>>> + break;
>>>> + }
>>>> }
>>>>
>>>> - if(opts.pids == NULL && opts.cmd != GET_ONLINE_PIDS) {
>>>> - fprintf(stderr, "No pid specified.\n");
>>>> - usage();
>>>> + cli_cmd = find_cli_cmd(argv[optind]);
>>>> + if (!cli_cmd) {
>>>> + fprintf(stderr, "No such command %s\n",
>>>> + argv[optind]);
>>>> exit(EXIT_FAILURE);
>>>> }
>>>> - if(opts.cmd == UNKNOWN) {
>>>> - fprintf(stderr, "No command specified.\n");
>>>> - usage();
>>>> +
>>>> + cli_dispatch_cmd(cli_cmd, argc - optind, &argv[optind]);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static pid_t parse_pid(const char *pid_string)
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + errno = 0;
>>>> + pid = strtoull(pid_string, NULL, 10);
>>>> + if (errno) {
>>>> + perror("Failed to parse pid");
>>>> exit(EXIT_FAILURE);
>>>> }
>>>> - if (opts.cmd == GET_ONLINE_PIDS) {
>>>> - pid_t *pp = ustcmd_get_online_pids();
>>>> - unsigned int i = 0;
>>>> -
>>>> - if (pp) {
>>>> - while (pp[i] != 0) {
>>>> - printf("%u\n", (unsigned int) pp[i]);
>>>> - ++i;
>>>> - }
>>>> - free(pp);
>>>> - }
>>>>
>>>> - exit(EXIT_SUCCESS);
>>>> - }
>>>> + return pid;
>>>> +}
>>>>
>>>> - pidit = opts.pids;
>>>> +static int list_markers(int argc, char *argv[])
>>>> +{
>>>> struct marker_status *cmsf = NULL;
>>>> + int i;
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_get_cmsf(&cmsf, pid)) {
>>>> + ERR("error while trying to list markers for PID %u\n", pid);
>>>> + return -1;
>>>> + }
>>>> + for (i = 0; cmsf[i].channel; i++) {
>>>> + printf("{PID: %u, channel/marker: %s/%s, "
>>>> + "state: %u, fmt: %s}\n",
>>>> + (unsigned int) pid,
>>>> + cmsf[i].channel,
>>>> + cmsf[i].marker,
>>>> + cmsf[i].state,
>>>> + cmsf[i].fs);
>>>> + }
>>>> + ustcmd_free_cmsf(cmsf);
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(list_markers,
>>>> + "list-markers",
>>>> + "List markers for a given pid",
>>>> + "list-markers <pid>\n"
>>>> + "List the markers in a process\n",
>>>> + 1,
>>>> + CLI_EQ);
>>>> +
>>>> +
>>>> +static int create_trace(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_create_trace(argv[2], pid)) {
>>>> + ERR("Failed to create trace %s for PID %u\n", argv[2], pid);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(create_trace,
>>>> + "create-trace",
>>>> + "Create a trace for a process",
>>>> + "create-trace <pid> <trace>\n"
>>>> + "Create a trace for a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +static int alloc_trace(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_alloc_trace(argv[2], pid)) {
>>>> + ERR("Failed to allocate trace %s for PID %u\n", argv[2], pid);
>>>> + return -1;
>>>> + }
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(alloc_trace,
>>>> + "alloc-trace",
>>>> + "Allocate a trace for a process",
>>>> + "alloc-trace <pid> <trace>\n"
>>>> + "Allocate a trace for a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +static int start_trace(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_start_trace(argv[2], pid)) {
>>>> + ERR("Failed to start trace %s for PID %u\n", argv[2], pid);
>>>> + return -1;
>>>> + }
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(start_trace,
>>>> + "start-trace",
>>>> + "Start a trace for a process",
>>>> + "start-trace <pid> <trace>\n"
>>>> + "Start a trace for a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +static int stop_trace(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_stop_trace(argv[2], pid)) {
>>>> + ERR("Failed to stop trace %s for PID %u\n", argv[2], pid);
>>>> + return -1;
>>>> + }
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(stop_trace,
>>>> + "stop-trace",
>>>> + "Stop a trace for a process",
>>>> + "stop-trace <pid> <trace>\n"
>>>> + "Stop a trace for a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +static int destroy_trace(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_destroy_trace(argv[2], pid)) {
>>>> + ERR("Failed to destroy trace %s for PID %u\n", argv[2], pid);
>>>> + return -1;
>>>> + }
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(destroy_trace,
>>>> + "destroy-trace",
>>>> + "Destroy a trace for a process",
>>>> + "destroy-trace <pid> <trace>\n"
>>>> + "Destroy a trace for a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +
>>>> +static int list_trace_events(int argc, char *argv[])
>>>> +{
>>>> struct trace_event_status *tes = NULL;
>>>> - unsigned int i = 0;
>>>> -
>>>> - while(*pidit != -1) {
>>>> - switch (opts.cmd) {
>>>> - case CREATE_TRACE:
>>>> - result = ustcmd_create_trace(trace, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to create trace with PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - break;
>>>> -
>>>> - case START_TRACE:
>>>> - result = ustcmd_start_trace(trace, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to for trace with PID %u\n", (unsigned int)
>>>> *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - break;
>>>> -
>>>> - case STOP_TRACE:
>>>> - result = ustcmd_stop_trace(trace, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to stop trace for PID %u\n", (unsigned int)
>>>> *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - break;
>>>> -
>>>> - case DESTROY_TRACE:
>>>> - result = ustcmd_destroy_trace(trace, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to destroy trace with PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - break;
>>>> -
>>>> - case LIST_MARKERS:
>>>> - cmsf = NULL;
>>>> - if (ustcmd_get_cmsf(&cmsf, *pidit)) {
>>>> - ERR("error while trying to list markers for PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - i = 0;
>>>> - while (cmsf[i].channel != NULL) {
>>>> - printf("{PID: %u, channel/marker: %s/%s, "
>>>> - "state: %u, fmt: %s}\n",
>>>> - (unsigned int) *pidit,
>>>> - cmsf[i].channel,
>>>> - cmsf[i].marker,
>>>> - cmsf[i].state,
>>>> - cmsf[i].fs);
>>>> - ++i;
>>>> - }
>>>> - ustcmd_free_cmsf(cmsf);
>>>> - break;
>>>> -
>>>> - case LIST_TRACE_EVENTS:
>>>> - tes = NULL;
>>>> - if (ustcmd_get_tes(&tes, *pidit)) {
>>>> - ERR("error while trying to list "
>>>> - "trace_events for PID %u\n",
>>>> - (unsigned int) *pidit);
>>>> - break;
>>>> - }
>>>> - i = 0;
>>>> - while (tes[i].name != NULL) {
>>>> - printf("{PID: %u, trace_event: %s}\n",
>>>> - (unsigned int) *pidit,
>>>> - tes[i].name);
>>>> - ++i;
>>>> - }
>>>> - ustcmd_free_tes(tes);
>>>> -
>>>> - break;
>>>> - case ENABLE_MARKER:
>>>> - if (opts.regex) {
>>>> - char *channel, *marker;
>>>> -
>>>> - if (scan_ch_marker(opts.regex,
>>>> - &channel, &marker)) {
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - if (ustcmd_set_marker_state(trace, channel, marker, 1, *pidit)) {
>>>> - PERROR("error while trying to enable marker %s with PID %u",
>>>> - opts.regex, (unsigned int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - }
>>>> + int i;
>>>> + pid_t pid;
>>>>
>>>> - break;
>>>> - case DISABLE_MARKER:
>>>> - if (opts.regex) {
>>>> - char *channel, *marker;
>>>> -
>>>> - if (scan_ch_marker(opts.regex,
>>>> - &channel, &marker)) {
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - if (ustcmd_set_marker_state(trace, channel, marker, 0, *pidit)) {
>>>> - ERR("error while trying to disable marker %s with PID %u\n",
>>>> - opts.regex, (unsigned int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - }
>>>> - break;
>>>> -
>>>> - case SET_SUBBUF_SIZE:
>>>> - if (opts.regex) {
>>>> - char *channel;
>>>> - unsigned int size;
>>>> - if (scan_ch_and_num(opts.regex, &channel, &size)) {
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> -
>>>> - if (ustcmd_set_subbuf_size(trace, channel, size, *pidit)) {
>>>> - ERR("error while trying to set the size of subbuffers with PID %u\n",
>>>> - (unsigned int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - }
>>>> - break;
>>>> -
>>>> - case SET_SUBBUF_NUM:
>>>> - if (opts.regex) {
>>>> - char *channel;
>>>> - unsigned int num;
>>>> - if (scan_ch_and_num(opts.regex, &channel, &num)) {
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> -
>>>> - if (num < 2) {
>>>> - ERR("Subbuffer count should be greater or equal to 2");
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - if (ustcmd_set_subbuf_num(trace, channel, num, *pidit)) {
>>>> - ERR("error while trying to set the number of subbuffers with PID
>>>> %u\n",
>>>> - (unsigned int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - }
>>>> - break;
>>>> -
>>>> - case GET_SUBBUF_SIZE:
>>>> - result = ustcmd_get_subbuf_size(trace, opts.regex, *pidit);
>>>> - if (result == -1) {
>>>> - ERR("error while trying to get_subuf_size with PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> + pid = parse_pid(argv[1]);
>>>>
>>>> - printf("the size of subbufers is %d\n", result);
>>>> - break;
>>>> + if (ustcmd_get_tes(&tes, pid)) {
>>>> + ERR("error while trying to list "
>>>> + "trace_events for PID %u\n",
>>>> + pid);
>>>> + return -1;
>>>> + }
>>>> + i = 0;
>>>> + for (i = 0; tes[i].name; i++) {
>>>> + printf("{PID: %u, trace_event: %s}\n",
>>>> + pid,
>>>> + tes[i].name);
>>>> + }
>>>> + ustcmd_free_tes(tes);
>>>>
>>>> - case GET_SUBBUF_NUM:
>>>> - result = ustcmd_get_subbuf_num(trace, opts.regex, *pidit);
>>>> - if (result == -1) {
>>>> - ERR("error while trying to get_subuf_num with PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> + return 0;
>>>> +}
>>>>
>>>> - printf("the number of subbufers is %d\n", result);
>>>> - break;
>>>> +DEFINE_CLI_CMD(list_trace_events,
>>>> + "list-trace-events",
>>>> + "List trace-events for a given pid",
>>>> + "list-trace-events <pid>\n"
>>>> + "List the trace-events in a process\n",
>>>> + 1,
>>>> + CLI_EQ);
>>>>
>>>> - case ALLOC_TRACE:
>>>> - result = ustcmd_alloc_trace(trace, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to alloc trace with PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - break;
>>>> -
>>>> - case GET_SOCK_PATH:
>>>> - result = ustcmd_get_sock_path(&tmp, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to get sock path for PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> - }
>>>> - printf("the socket path is %s\n", tmp);
>>>> - free(tmp);
>>>> - break;
>>>> -
>>>> - case SET_SOCK_PATH:
>>>> - result = ustcmd_set_sock_path(opts.regex, *pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to set sock path for PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - break;
>>>> +static int enable_marker(int argc, char *argv[])
>>>> +{
>>>> + int i, result = 0;
>>>> + pid_t pid;
>>>> + char *channel, *marker;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + for (i = 3; i < argc; i++) {
>>>> + channel = NULL;
>>>> + marker = NULL;
>>>> + if (scan_ch_marker(argv[i],
>>>> + &channel, &marker)) {
>>>> + result = -1;
>>>> + fprintf(stderr, "Failed to scan channel and marker from"
>>>> + " %s\n", argv[i]);
>>>> + if (channel)
>>>> + free(channel);
>>>> + if (marker)
>>>> + free(marker);
>>>> + }
>>>> + if (ustcmd_set_marker_state(argv[2], channel, marker, 1, pid)) {
>>>> + PERROR("error while trying to enable marker %s with PID %u",
>>>> + argv[i], pid);
>>>> + result = -1;
>>>> + }
>>>> + free(channel);
>>>> + free(marker);
>>>> + }
>>>>
>>>> - case FORCE_SWITCH:
>>>> - result = ustcmd_force_switch(*pidit);
>>>> - if (result) {
>>>> - ERR("error while trying to force switch for PID %u\n", (unsigned
>>>> int) *pidit);
>>>> - retval = EXIT_FAILURE;
>>>> - }
>>>> - break;
>>>> + return result;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(enable_marker,
>>>> + "enable-marker",
>>>> + "Enable markers for a given pid",
>>>> + "enable-marker <pid> <trace> <channel>/<marker>... \n"
>>>> + "Enable the listed markers for the trace in process pid\n",
>>>> + 3,
>>>> + CLI_GE);
>>>>
>>>> - default:
>>>> - ERR("unknown command\n");
>>>> - retval = EXIT_FAILURE;
>>>> - break;
>>>> +static int disable_marker(int argc, char *argv[])
>>>> +{
>>>> + int i, result = 0;
>>>> + pid_t pid;
>>>> + char *channel, *marker;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + for (i = 3; i < argc; i++) {
>>>> + channel = NULL;
>>>> + marker = NULL;
>>>> + if (scan_ch_marker(argv[i],
>>>> + &channel, &marker)) {
>>>> + fprintf(stderr, "Failed to scan channel and marker from"
>>>> + " %s\n", argv[i]);
>>>> + if (channel)
>>>> + free(channel);
>>>> + if (marker)
>>>> + free(marker);
>>>> + return -1;
>>>> + }
>>>> + if (ustcmd_set_marker_state(argv[2], channel, marker, 0, pid)) {
>>>> + PERROR("error while trying to disable marker %s with PID %u",
>>>> + argv[i], pid);
>>>> + result = -1;
>>>> }
>>>> + free(channel);
>>>> + free(marker);
>>>> + }
>>>> +
>>>> + return result;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(disable_marker,
>>>> + "disable-marker",
>>>> + "Disable markers for a given pid",
>>>> + "disable-marker <pid> <trace> <channel>/<marker>... \n"
>>>> + "Disable the listed markers for the trace in process pid\n",
>>>> + 3,
>>>> + CLI_GE);
>>>> +
>>>> +static int set_subbuf_size(int argc, char *argv[])
>>>> +{
>>>> + int result = 0;
>>>> + pid_t pid;
>>>> + char *channel = NULL;
>>>> + unsigned int size;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (scan_ch_and_num(argv[3], &channel, &size)) {
>>>> + fprintf(stderr, "Failed to scan channel and size from"
>>>> + " %s\n", argv[3]);
>>>> + if (channel)
>>>> + free(channel);
>>>> + return -1;
>>>> + }
>>>> + if (ustcmd_set_subbuf_size(argv[2], channel, size, pid)) {
>>>> + ERR("error while trying to set the size of subbuffers "
>>>> + "for PID %u\n",
>>>> + pid);
>>>> + result = -1;
>>>> + }
>>>> +
>>>> + free(channel);
>>>> +
>>>> + return result;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(set_subbuf_size,
>>>> + "set-subbuf-size",
>>>> + "Set the subbuffer size for a channel",
>>>> + "set-subbuf-size <pid> <trace> <channel>/<size> \n"
>>>> + "Set the subbuffer size for a channel\n",
>>>> + 3,
>>>> + CLI_EQ);
>>>> +
>>>> +static int set_subbuf_num(int argc, char *argv[])
>>>> +{
>>>> + int result = 0;
>>>> + pid_t pid;
>>>> + char *channel = NULL;
>>>> + unsigned int num;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (scan_ch_and_num(argv[3], &channel, &num)) {
>>>> + fprintf(stderr, "Failed to scan channel and number from"
>>>> + " %s\n", argv[3]);
>>>> + if (channel)
>>>> + free(channel);
>>>> + return -1;
>>>> + }
>>>> + if (ustcmd_set_subbuf_num(argv[2], channel, num, pid)) {
>>>> + ERR("error while trying to set the number of subbuffers for PID
>>>> %u\n",
>>>> + pid);
>>>> + result = -1;
>>>> + }
>>>> +
>>>> + free(channel);
>>>> +
>>>> + return result;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(set_subbuf_num,
>>>> + "set-subbuf-num",
>>>> + "Set the number of subbuffers for a channel",
>>>> + "set-subbuf-num <pid> <trace> <channel>/<num> \n"
>>>> + "Set the number of subbuffers for a channel\n",
>>>> + 3,
>>>> + CLI_EQ);
>>>> +
>>>> +static int get_subbuf_size(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> + unsigned int size;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if ((size = ustcmd_get_subbuf_size(argv[2], argv[3], pid)) < 0) {
>>>> + ERR("error while trying to get the subbuffer size from PID %u\n",
>>>> + pid);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + printf("The subbufer size is %d bytes\n", size);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(get_subbuf_size,
>>>> + "get-subbuf-size",
>>>> + "Get the subbuffer size for a channel",
>>>> + "get-subbuf-size <pid> <trace> <channel>\n"
>>>> + "Get the subbuffer size for a channel\n",
>>>> + 3,
>>>> + CLI_EQ);
>>>> +
>>>> +static int get_subbuf_num(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> + unsigned int num;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if ((num = ustcmd_get_subbuf_num(argv[2], argv[3], pid)) < 0) {
>>>> + ERR("error while trying to get the subbuffer size from PID %u\n",
>>>> + pid);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + printf("There are %u subbufers in each buffer\n", num);
>>>>
>>>> - pidit++;
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(get_subbuf_num,
>>>> + "get-subbuf-num",
>>>> + "Get the number of subbuffers for a channel",
>>>> + "get-subbuf-num <pid> <trace> <channel>\n"
>>>> + "Get the number of subbuffers for a channel\n",
>>>> + 3,
>>>> + CLI_EQ);
>>>> +
>>>> +static int set_sock_path(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_set_sock_path(argv[2], pid)) {
>>>> + ERR("error while trying to set sock path for PID %u\n", pid);
>>>> + return -1;
>>>> }
>>>>
>>>> - if (opts.pids != NULL) {
>>>> - free(opts.pids);
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(set_sock_path,
>>>> + "set-sock-path",
>>>> + "Set the path to the consumer daemon socket",
>>>> + "set-sock-path <pid> <sock-path>\n"
>>>> + "Set the path to the consumer daemon socket\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> +
>>>> +static int get_sock_path(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> + char *sock_path;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_get_sock_path(&sock_path, pid)) {
>>>> + ERR("error while trying to get sock path for PID %u\n", pid);
>>>> + return -1;
>>>> }
>>>> - if (opts.regex != NULL) {
>>>> - free(opts.regex);
>>>> + printf("The socket path is %s\n", sock_path);
>>>> + free(sock_path);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +DEFINE_CLI_CMD(get_sock_path,
>>>> + "get-sock-path",
>>>> + "Get the path to the consumer daemon socket",
>>>> + "get-sock-path <pid>\n"
>>>> + "Get the path to the consumer daemon socket\n",
>>>> + 1,
>>>> + CLI_EQ);
>>>> +
>>>> +static int force_subbuf_switch(int argc, char *argv[])
>>>> +{
>>>> + pid_t pid;
>>>> +
>>>> + pid = parse_pid(argv[1]);
>>>> +
>>>> + if (ustcmd_force_switch(pid)) {
>>>> + ERR("error while trying to force switch for PID %u\n", pid);
>>>> + return -1;
>>>> }
>>>>
>>>> - return retval;
>>>> + return 0;
>>>> }
>>>>
>>>> +DEFINE_CLI_CMD(force_subbuf_switch,
>>>> + "force-subbuf-switch",
>>>> + "Force a subbuffer switch",
>>>> + "force-subbuf-switch <pid> <trace>\n"
>>>> + "Force a subbuffer switch for a trace, currently this forces\n"
>>>> + "a subbuffer switch for all traces in a process\n",
>>>> + 2,
>>>> + CLI_EQ);
>>>> --
>>>> 1.7.1
>>>>
>>>
>>>
>>> _______________________________________________
>>> ltt-dev mailing list
>>> ltt-dev at lists.casi.polymtl.ca
>>> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>>
>> --
>> David Goulet
>> LTTng project, DORSAL Lab.
>>
>> PGP/GPG : 1024D/16BD8563
>> BE3C 672B 9331 9796 291A 14C6 4AF7 C14B 16BD 8563
>>

-- 
David Goulet
LTTng project, DORSAL Lab.

PGP/GPG : 1024D/16BD8563
BE3C 672B 9331 9796 291A  14C6 4AF7 C14B 16BD 8563




More information about the lttng-dev mailing list