summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Google) <rostedt@goodmis.org>2022-02-06 09:16:51 -0500
committerSteven Rostedt (Google) <rostedt@goodmis.org>2022-02-06 09:16:51 -0500
commitb49b8ec2d2fa393f5edf3f4419edd0488763db09 (patch)
tree94fdb2e9311a46d3f091052c8fda3efa36a2577e
parent92f2f92530a23ad7af0e14c65e077aeabfae8a9f (diff)
downloadktrace-b49b8ec2d2fa393f5edf3f4419edd0488763db09.tar.gz
ktrace: Use ktrace_help() for all help messagesHEADmaster
Consolidate the help messages into a ktrace_commands structure that can link to sub commands. Add a ktrace_help() helper function that can be called to print the commands and sub command help messages. This will be used for both the help command itself, and for improper usage of the commands that lack arguments. Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r--include/ktrace.h3
-rw-r--r--src/create.c38
-rw-r--r--src/enable.c44
-rw-r--r--src/help.c179
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,
diff --git a/src/help.c b/src/help.c
index 05ce439..0798088 100644
--- a/src/help.c
+++ b/src/help.c
@@ -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;
}
-