diff options
-rw-r--r-- | include/ktrace.h | 3 | ||||
-rw-r--r-- | src/create.c | 38 | ||||
-rw-r--r-- | src/enable.c | 44 | ||||
-rw-r--r-- | src/help.c | 179 |
4 files changed, 180 insertions, 84 deletions
diff --git a/include/ktrace.h b/include/ktrace.h index cb0d537..3319423 100644 --- a/include/ktrace.h +++ b/include/ktrace.h @@ -16,8 +16,11 @@ struct ktrace_commands { const char *command; const char *usage; const char *help; + struct ktrace_commands *link; }; +int ktrace_help(struct ccli *ccli, const char *arg1, const char *arg2); + int help_completion(struct ccli *ccli, const char *command, const char *line, int word, char *match, char ***list, void *data); diff --git a/src/create.c b/src/create.c index 1cd1236..7b11e8a 100644 --- a/src/create.c +++ b/src/create.c @@ -4,13 +4,6 @@ */ #include "ktrace.h" - -static void create_usage(struct ccli *ccli) -{ - ccli_printf(ccli, "usage: create <type> <type-command>\n" - " <type> : kprobe, eprobe, synthetic_event\n"); -} - static int add_type_offset(struct ccli *ccli, char *p, char **pvar, char *line) { long long offset; @@ -135,7 +128,7 @@ static int create_kprobe(struct ccli *ccli, void *data, int i; if (argc < 3) { - ccli_printf(ccli, "# usage: create kprobe name function/address fields\n"); + ktrace_help(ccli, "create", "kprobe"); return 0; } @@ -223,10 +216,8 @@ static int create_eprobe(struct ccli *ccli, void *data, int ret; int i; - if (argc < 3) { - ccli_printf(ccli, "# usage: create eprobe name system/event fields\n"); - return 0; - } + if (argc < 3) + return ktrace_help(ccli, "create", "eprobe"); name = argv[0]; @@ -264,21 +255,6 @@ static int create_eprobe(struct ccli *ccli, void *data, return 0; } -static int usage_synthetic(struct ccli *ccli) -{ - ccli_printf(ccli, "# usage: create synthetic name system/event.field1[,field2,..] system2/event2.field1[,field2,..] field1=systemX/eventX.field[ field2=systemX/eventX.field ...]\n" - "# Where the synthetic event is created when the fields of system/event\n" - "# match system/event2 fields. Then add the fields of the synthetic event\n" - "# on how they will map to the other fields.\n#\n" - "# A synthetic event field may also equal timestamps:\n" - "# start=system/event.TIMESTAMP\n" - "# start=system/event.TIMESTAMP_USECS\n#\n" - "# Or even a delta:\n" - "# delta=system/event.TIMESTAMP-system2/event2.TIMESTAMP\n" - ); - return 0; -} - static char *check_ts(char *val) { if (strcmp(val, "TIMESTAMP") == 0) @@ -425,7 +401,7 @@ static int create_synthetic(struct ccli *ccli, void *data, int i; if (argc < 4) - return usage_synthetic(ccli); + return ktrace_help(ccli, "create", "synthetic"); name = argv[0]; @@ -523,10 +499,8 @@ free_fields: int cmd_create(struct ccli *ccli, const char *command, const char *line, void *data, int argc, char **argv) { - if (argc < 2) { - create_usage(ccli); - return 0; - } + if (argc < 2) + return ktrace_help(ccli, "create", NULL); if (strcmp(argv[1], "kprobe") == 0) return create_kprobe(ccli, data, argc - 2, argv + 2); diff --git a/src/enable.c b/src/enable.c index f588f1a..d978bc4 100644 --- a/src/enable.c +++ b/src/enable.c @@ -4,18 +4,6 @@ */ #include "ktrace.h" -static void enable_usage(struct ccli *ccli) -{ - ccli_printf(ccli, "usage: enable <type> <type-command>\n" - " <type> : tracing, event\n"); -} - -static void disable_usage(struct ccli *ccli) -{ - ccli_printf(ccli, "usage: disable <type> <type-command>\n" - " <type> : tracing, event\n"); -} - static int enable_tracing(struct ccli *ccli, void *data, int argc, char **argv) { @@ -79,10 +67,8 @@ static int enable_event(struct ccli *ccli, void *data, { char *file; - if (argc < 1) { - ccli_printf(ccli, "usage: enable event system/event\n"); - return 0; - } + if (argc < 1) + return ktrace_help(ccli, "enable", "event"); file = get_event(ccli, data, argv[0]); if (file) @@ -96,10 +82,8 @@ static int disable_event(struct ccli *ccli, void *data, { char *file; - if (argc < 1) { - ccli_printf(ccli, "usage: enable event system/event\n"); - return 0; - } + if (argc < 1) + return ktrace_help(ccli, "disable", "event"); file = get_event(ccli, data, argv[0]); if (file) @@ -111,10 +95,8 @@ static int disable_event(struct ccli *ccli, void *data, int cmd_enable(struct ccli *ccli, const char *command, const char *line, void *data, int argc, char **argv) { - if (argc < 2) { - enable_usage(ccli); - return 0; - } + if (argc < 2) + return ktrace_help(ccli, "enable", NULL); if (strcmp(argv[1], "tracing") == 0) return enable_tracing(ccli, data, argc - 2, argv + 2); @@ -122,18 +104,14 @@ int cmd_enable(struct ccli *ccli, const char *command, const char *line, if (strcmp(argv[1], "event") == 0) return enable_event(ccli, data, argc - 2, argv + 2); - enable_usage(ccli); - - return 0; + return ktrace_help(ccli, "enable", NULL); } int cmd_disable(struct ccli *ccli, const char *command, const char *line, void *data, int argc, char **argv) { - if (argc < 2) { - disable_usage(ccli); - return 0; - } + if (argc < 2) + return ktrace_help(ccli, "disable", NULL); if (strcmp(argv[1], "tracing") == 0) return disable_tracing(ccli, data, argc - 2, argv + 2); @@ -141,9 +119,7 @@ int cmd_disable(struct ccli *ccli, const char *command, const char *line, if (strcmp(argv[1], "event") == 0) return disable_event(ccli, data, argc - 2, argv + 2); - enable_usage(ccli); - - return 0; + return ktrace_help(ccli, "disable", NULL); } static int disenable_event_completion(struct ccli *ccli, void *data, @@ -4,6 +4,79 @@ */ #include "ktrace.h" +static struct ktrace_commands create_cmds[] = +{ + { + "kprobe", + "create kprobe name function/address fields", + "# Create a kprobe with 'name' at a function or an address given.\n" + "# followed by a set of fields." + }, + { + "eprobe", + "create eprobe name system/event fields", + "# Create an event on top of another event.\n" + "# Where 'name' is the new event.\n" + "# 'system/event' is the event to attach to.\n" + "# Followed by the fields to display", + }, + { + "synthetic", + "create synthetic name system/event.field1[,field2,..] system2/event2.field1[,field2,..] field1=systemX/eventX.field[ field2=systemX/eventX.field ...]", + "# Where the synthetic event is created when the fields of system/event\n" + "# match system/event2 fields. Then add the fields of the synthetic event\n" + "# on how they will map to the other fields.\n#\n" + "# A synthetic event field may also equal timestamps:\n" + "# start=system/event.TIMESTAMP\n" + "# start=system/event.TIMESTAMP_USECS\n#\n" + "# Or even a delta:\n" + "# delta=system/event.TIMESTAMP-system2/event2.TIMESTAMP" + }, + { + NULL + } +}; + +static struct ktrace_commands enable_cmds[] = +{ + { + "tracing", + "enable tracing", + " Makes the ring buffer writable" + }, + { + "event", + "enable event (all|system|system/event)", + " Enable an event.\n" + " Key word 'all' will enable all events\n" + " Specify just a system to enable all events within that system.\n" + " Specify system/event, with '/' to separate the two, to enable just one event." + }, + { + NULL + } +}; + +static struct ktrace_commands disable_cmds[] = +{ + { + "tracing", + "disable tracing", + " Disable writing to the ring buffer" + }, + { + "event", + "disable event (all|system|system/event)", + " Disable an event.\n" + " Key word 'all' will disable all events\n" + " Specify just a system to disable all events within that system.\n" + " Specify system/event, with '/' to separate the two, to disable just one event." + }, + { + NULL + } +}; + static struct ktrace_commands ktrace_cmds[] = { { @@ -12,29 +85,53 @@ static struct ktrace_commands ktrace_cmds[] = " kprobe - to create a kernel probe event.\n" " eprobe - to create an event on top of another event.\n" " synthetic - to create a synthetic event", + .link = create_cmds }, { "enable", "enable (tracing|event)", " tracing - to enable tracing if it is stopped.\n" - " event - to enable an event" + " event - to enable an event", + .link = enable_cmds }, { "disable", "disable (tracing|event)", " tracing - to disable tracing, just stops writing to the ring buffer.\n" - " event - stop an event." + " event - stop an event.", + .link = disable_cmds + }, + { + NULL } }; -int cmd_help(struct ccli *ccli, const char *command, const char *line, - void *data, int argc, char **argv) +static int help_cmd(struct ccli *ccli, const char *arg, + struct ktrace_commands *commands) { int l = 1; int i; - if (argc < 2) { - for (i = 0; l > 0 && i < ARRAY_SIZE(ktrace_cmds); i++) { + for (i = 0; l > 0 && commands[i].command; i++) { + if (strcmp(arg, commands[i].command) == 0) { + l = ccli_page(ccli, l, "usage: %s\n", + commands[i].usage); + l = ccli_page(ccli, l, "%s\n", + commands[i].help); + return 0; + } + } + ccli_printf(ccli, "Command %s not found\n", arg); + return 0; +} + +int ktrace_help(struct ccli *ccli, const char *arg1, const char *arg2) +{ + int l = 1; + int i; + + if (!arg1) { + for (i = 0; l > 0 && ktrace_cmds[i].command; i++) { if (i) l = ccli_page(ccli, l, "\n"); l = ccli_page(ccli, l, "command: %s\n", @@ -47,32 +144,78 @@ int cmd_help(struct ccli *ccli, const char *command, const char *line, return 0; } - for (i = 0; l > 0 && i < ARRAY_SIZE(ktrace_cmds); i++) { - if (strcmp(argv[1], ktrace_cmds[i].command) == 0) { + if (!arg2) + return help_cmd(ccli, arg1, ktrace_cmds); + + for (i = 0; l > 0 && ktrace_cmds[i].command; i++) { + if (strcmp(arg1, ktrace_cmds[i].command) == 0) { + if (ktrace_cmds[i].link) + return help_cmd(ccli, arg2, ktrace_cmds[i].link); l = ccli_page(ccli, l, "usage: %s\n", - ktrace_cmds[i].usage); + ktrace_cmds[i].usage); l = ccli_page(ccli, l, "%s\n", - ktrace_cmds[i].help); + ktrace_cmds[i].help); return 0; } + ccli_printf(ccli, "Command %s not found\n", arg1); } + return 0; } +int cmd_help(struct ccli *ccli, const char *command, const char *line, + void *data, int argc, char **argv) +{ + if (argc < 2) + return ktrace_help(ccli, NULL, NULL); + + if (argc < 3) + return ktrace_help(ccli, argv[1], NULL); + + return ktrace_help(ccli, argv[1], argv[2]); +} + +static int help_complete(struct ccli *ccli, char ***list, + struct ktrace_commands *commands) +{ + int cnt = 0; + int ret = 0; + int i; + + for (i = 0; ret >= 0 && commands[i].command; i++) + ret = ccli_list_add(ccli, list, &cnt, commands[i].command); + + return ret; +} + int help_completion(struct ccli *ccli, const char *command, const char *line, int word, char *match, char ***list, void *data) { - int cnt = 0; + char **argv; int ret = 0; + int argc; int i; - if (word == 1) { - for (i = 0; ret >= 0 && i < ARRAY_SIZE(ktrace_cmds); i++) - ret = ccli_list_add(ccli, list, &cnt, - ktrace_cmds[i].command); - return ret; + if (word > 2) + return 0; + + if (word == 1) + return help_complete(ccli, list, ktrace_cmds); + + argc = ccli_line_parse(line, &argv); + if (argc < 1) + return 0; + + ret = 0; + for (i = 0; argc > 1 && ktrace_cmds[i].command; i++) { + if (strcmp(argv[1], ktrace_cmds[i].command) == 0) { + if (!ktrace_cmds[i].link) + break; + ret = help_complete(ccli, list, ktrace_cmds[i].link); + break; + } } - return 0; + ccli_argv_free(argv); + return ret; } - |