X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;ds=sidebyside;f=ust%2Fust.c;h=789dfe0feeb7c8d44da14ebc97ae23cef75969c3;hb=dc2f5ffa5138aebbe520eebac1e038cff653fbe7;hp=2f7a6bd76c3f7ff6e202bd0dc43971dcd201050f;hpb=52c51a47e4b002d741c89de8dc786da59e894a1a;p=ust.git diff --git a/ust/ust.c b/ust/ust.c index 2f7a6bd..789dfe0 100644 --- a/ust/ust.c +++ b/ust/ust.c @@ -1,28 +1,75 @@ +/* Copyright (C) 2009 Pierre-Marc Fournier + * + * 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 #include #include #include -#include #include #include "ustcomm.h" +#include "ustcmd.h" +#include "usterr.h" + +enum command { + START_TRACE, + STOP_TRACE, + START, + DESTROY, + LIST_MARKERS, + ENABLE_MARKER, + DISABLE_MARKER, + GET_ONLINE_PIDS, + UNKNOWN +}; struct ust_opts { - char *cmd; + enum command cmd; pid_t *pids; - int take_reply; + char *regex; }; +char *progname = NULL; + +void usage(void) +{ + 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\ + --start-trace\t\t\tStart tracing\n\ + --stop-trace\t\t\tStop tracing\n\ + --destroy-trace\t\t\tDestroy the trace\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\ +\ +"); +} + int parse_opts_long(int argc, char **argv, struct ust_opts *opts) { int c; - int digit_optind = 0; - opts->cmd = NULL; opts->pids = NULL; - opts->take_reply = 0; + opts->regex = NULL; while (1) { - int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"start-trace", 0, 0, 1000}, @@ -34,10 +81,13 @@ int parse_opts_long(int argc, char **argv, struct ust_opts *opts) {"enable-marker", 1, 0, 1007}, {"disable-marker", 1, 0, 1008}, {"start", 0, 0, 1009}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 1010}, + {"online-pids", 0, 0, 1011}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "", long_options, &option_index); + c = getopt_long(argc, argv, "h", long_options, &option_index); if (c == -1) break; @@ -50,41 +100,60 @@ int parse_opts_long(int argc, char **argv, struct ust_opts *opts) break; case 1000: - opts->cmd = strdup("trace_start"); + opts->cmd = START_TRACE; break; case 1001: - opts->cmd = strdup("trace_stop"); + opts->cmd = STOP_TRACE; break; case 1009: - opts->cmd = strdup("start"); + opts->cmd = START; break; case 1002: - opts->cmd = strdup("trace_destroy"); + opts->cmd = DESTROY; break; case 1004: - opts->cmd = strdup("list_markers"); - opts->take_reply = 1; + opts->cmd = LIST_MARKERS; break; case 1007: - asprintf(&opts->cmd, "enable_marker %s", optarg); + opts->cmd = ENABLE_MARKER; + opts->regex = strdup(optarg); break; case 1008: - asprintf(&opts->cmd, "disable_marker %s", optarg); + opts->cmd = DISABLE_MARKER; + opts->regex = strdup(optarg); + break; + case 1011: + opts->cmd = GET_ONLINE_PIDS; break; + case 'h': + usage(); + exit(0); + case 1010: + printf("Version 0.1\n"); default: - /* unknown option or other error; error is printed by getopt, just return */ + /* unknown option or other error; error is + printed by getopt, just return */ + opts->cmd = UNKNOWN; return 1; } } - if(argc - optind > 0) { + if (argc - optind > 0 && opts->cmd != GET_ONLINE_PIDS) { int i; int pididx=0; opts->pids = malloc((argc-optind+1) * sizeof(pid_t)); for(i=optind; ipids[pididx++] = atoi(argv[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; } @@ -92,29 +161,9 @@ int parse_opts_long(int argc, char **argv, struct ust_opts *opts) return 0; } -char *progname = NULL; - -void usage(void) -{ - fprintf(stderr, "usage: %s [OPTIONS] OPERATION PID...\n", progname); - fprintf(stderr, "\nControl the tracing of a process that supports LTTng Userspace Tracing.\n\ -\n\ -Operations:\n\ -\t--start-trace\tStart tracing\n\ -\t--stop-trace\tStop tracing\n\ -\t--destroy-trace\tDestroy the trace\n\ -\t--enable-marker CHANNEL_NAME/MARKER_NAME\tEnable a marker\n\ -\t--disable-marker CHANNEL_NAME/MARKER_NAME\tDisable a marker\n\ -\t--list-markers\tList the markers of the process and their state\n\ -\n\ -"); -} - int main(int argc, char *argv[]) { pid_t *pidit; - //char *msg = argv[2]; - struct ustcomm_connection conn; int result; struct ust_opts opts; @@ -128,46 +177,123 @@ int main(int argc, char *argv[]) result = parse_opts_long(argc, argv, &opts); if(result) { + fprintf(stderr, "\n"); usage(); exit(EXIT_FAILURE); } - if(opts.pids == NULL) { + if(opts.pids == NULL && opts.cmd != GET_ONLINE_PIDS) { fprintf(stderr, "No pid specified.\n"); usage(); exit(EXIT_FAILURE); } - if(opts.cmd == NULL) { + if(opts.cmd == UNKNOWN) { fprintf(stderr, "No command specified.\n"); usage(); 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); + } pidit = opts.pids; + struct marker_status *cmsf = NULL; while(*pidit != -1) { - char *reply; - char **preply; - - if(opts.take_reply) - preply = &reply; - else - preply = NULL; - - result = ustcomm_connect_app(*pidit, &conn); - if(result) { - fprintf(stderr, "error connecting to process\n"); - exit(EXIT_FAILURE); + switch (opts.cmd) { + case START_TRACE: + result = ustcmd_start_trace(*pidit); + if (result) { + ERR("error while trying to for trace with PID %u\n", (unsigned int) *pidit); + break; + } + //printf("sucessfully started trace for PID %u\n", (unsigned int) *pidit); + break; + + case STOP_TRACE: + result = ustcmd_stop_trace(*pidit); + if (result) { + ERR("error while trying to stop trace for PID %u\n", (unsigned int) *pidit); + break; + } + //printf("sucessfully stopped trace for PID %u\n", (unsigned int) *pidit); + break; + + case START: + result = ustcmd_setup_and_start(*pidit); + if (result) { + ERR("error while trying to setup/start trace for PID %u\n", (unsigned int) *pidit); + break; + } + //printf("sucessfully setup/started trace for PID %u\n", (unsigned int) *pidit); + break; + + case DESTROY: + result = ustcmd_destroy_trace(*pidit); + if (result) { + ERR("error while trying to destroy trace with PID %u\n", (unsigned int) *pidit); + break; + } + //printf("sucessfully destroyed trace for PID %u\n", (unsigned int) *pidit); + break; + + case LIST_MARKERS: + cmsf = NULL; + if (ustcmd_get_cmsf(&cmsf, *pidit)) { + fprintf(stderr, + "error while trying to list markers for" + " PID %u\n", (unsigned int) *pidit); + break; + } + unsigned int 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 ENABLE_MARKER: + if(opts.regex) + ustcmd_set_marker_state(opts.regex, 1, *pidit); + break; + case DISABLE_MARKER: + if(opts.regex) + ustcmd_set_marker_state(opts.regex, 0, *pidit); + break; + + default: + ERR("unknown command\n"); + break; } - ustcomm_send_request(&conn, opts.cmd, preply); - if(opts.take_reply) - printf("%s", reply); pidit++; } - free(opts.pids); - free(opts.cmd); + if (opts.pids != NULL) { + free(opts.pids); + } + if (opts.regex != NULL) { + free(opts.regex); + } return 0; } +