Message ID | 20170222152851.20099-5-jgross@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Feb 22, 2017 at 04:28:48PM +0100, Juergen Gross wrote: > The Xenstore protocol supports the XS_CONTROL command for triggering > various actions in the Xenstore daemon. Enhance that support by using > a command table and adding a help function. > > Support multiple control commands in the associated xenstore-control > program used to issue XS_CONTROL commands. > > Signed-off-by: Juergen Gross <jgross@suse.com> > --- > tools/xenstore/xenstore_control.c | 65 +++++++++++++++++------- > tools/xenstore/xenstored_control.c | 100 +++++++++++++++++++++++++++++++++---- > 2 files changed, 135 insertions(+), 30 deletions(-) > > diff --git a/tools/xenstore/xenstore_control.c b/tools/xenstore/xenstore_control.c > index 0a108df..e42d478 100644 > --- a/tools/xenstore/xenstore_control.c > +++ b/tools/xenstore/xenstore_control.c > @@ -7,29 +7,56 @@ > > int main(int argc, char **argv) > { > - struct xs_handle * xsh; > + struct xs_handle *xsh; > + char *par = NULL; > + char *ret; > + unsigned int p, len = 0; > + int rc = 0; > > - if (argc < 2 || > - strcmp(argv[1], "check")) > - { > - fprintf(stderr, > - "Usage:\n" > - "\n" > - " %s check\n" > - "\n", argv[0]); > - return 2; > - } > + if (argc < 2) { > + fprintf(stderr, "Usage:\n" > + "%s <command> [<arg>...]\n", argv[0]); > + return 2; > + } > > - xsh = xs_daemon_open(); > + for (p = 2; p < argc; p++) > + len += strlen(argv[p]) + 1; > + if (len) { > + par = malloc(len); par is never freed. I would also suggest to use goto style error handling. > + if (!par) { > + fprintf(stderr, "Allocation error.\n"); > + return 1; > + } > + len = 0; > + for (p = 2; p < argc; p++) { > + memcpy(par + len, argv[p], strlen(argv[p]) + 1); > + len += strlen(argv[p]) + 1; > + } > + } > > - if (xsh == NULL) { > - fprintf(stderr, "Failed to contact Xenstored.\n"); > - return 1; > - } > + xsh = xs_open(0); > + if (xsh == NULL) { > + fprintf(stderr, "Failed to contact Xenstored.\n"); > + return 1; > + } > > - xs_debug_command(xsh, argv[1], NULL, 0); > + ret = xs_debug_command(xsh, argv[1], par, len); Should be xs_control_command now. > + if (!ret) { > + rc = 3; > + if (errno == EINVAL) { > + ret = xs_debug_command(xsh, "help", NULL, 0); The rest looks good. Wei.
On 23/02/17 12:06, Wei Liu wrote: > On Wed, Feb 22, 2017 at 04:28:48PM +0100, Juergen Gross wrote: >> The Xenstore protocol supports the XS_CONTROL command for triggering >> various actions in the Xenstore daemon. Enhance that support by using >> a command table and adding a help function. >> >> Support multiple control commands in the associated xenstore-control >> program used to issue XS_CONTROL commands. >> >> Signed-off-by: Juergen Gross <jgross@suse.com> >> --- >> tools/xenstore/xenstore_control.c | 65 +++++++++++++++++------- >> tools/xenstore/xenstored_control.c | 100 +++++++++++++++++++++++++++++++++---- >> 2 files changed, 135 insertions(+), 30 deletions(-) >> >> diff --git a/tools/xenstore/xenstore_control.c b/tools/xenstore/xenstore_control.c >> index 0a108df..e42d478 100644 >> --- a/tools/xenstore/xenstore_control.c >> +++ b/tools/xenstore/xenstore_control.c >> @@ -7,29 +7,56 @@ >> >> int main(int argc, char **argv) >> { >> - struct xs_handle * xsh; >> + struct xs_handle *xsh; >> + char *par = NULL; >> + char *ret; >> + unsigned int p, len = 0; >> + int rc = 0; >> >> - if (argc < 2 || >> - strcmp(argv[1], "check")) >> - { >> - fprintf(stderr, >> - "Usage:\n" >> - "\n" >> - " %s check\n" >> - "\n", argv[0]); >> - return 2; >> - } >> + if (argc < 2) { >> + fprintf(stderr, "Usage:\n" >> + "%s <command> [<arg>...]\n", argv[0]); >> + return 2; >> + } >> >> - xsh = xs_daemon_open(); >> + for (p = 2; p < argc; p++) >> + len += strlen(argv[p]) + 1; >> + if (len) { >> + par = malloc(len); > > par is never freed. You are right. Will correct. > I would also suggest to use goto style error handling. Okay. >> + if (!par) { >> + fprintf(stderr, "Allocation error.\n"); >> + return 1; >> + } >> + len = 0; >> + for (p = 2; p < argc; p++) { >> + memcpy(par + len, argv[p], strlen(argv[p]) + 1); >> + len += strlen(argv[p]) + 1; >> + } >> + } >> >> - if (xsh == NULL) { >> - fprintf(stderr, "Failed to contact Xenstored.\n"); >> - return 1; >> - } >> + xsh = xs_open(0); >> + if (xsh == NULL) { >> + fprintf(stderr, "Failed to contact Xenstored.\n"); >> + return 1; >> + } >> >> - xs_debug_command(xsh, argv[1], NULL, 0); >> + ret = xs_debug_command(xsh, argv[1], par, len); > > Should be xs_control_command now. Of course. Will change. > >> + if (!ret) { >> + rc = 3; >> + if (errno == EINVAL) { >> + ret = xs_debug_command(xsh, "help", NULL, 0); > > The rest looks good. Thanks, Juergen
diff --git a/tools/xenstore/xenstore_control.c b/tools/xenstore/xenstore_control.c index 0a108df..e42d478 100644 --- a/tools/xenstore/xenstore_control.c +++ b/tools/xenstore/xenstore_control.c @@ -7,29 +7,56 @@ int main(int argc, char **argv) { - struct xs_handle * xsh; + struct xs_handle *xsh; + char *par = NULL; + char *ret; + unsigned int p, len = 0; + int rc = 0; - if (argc < 2 || - strcmp(argv[1], "check")) - { - fprintf(stderr, - "Usage:\n" - "\n" - " %s check\n" - "\n", argv[0]); - return 2; - } + if (argc < 2) { + fprintf(stderr, "Usage:\n" + "%s <command> [<arg>...]\n", argv[0]); + return 2; + } - xsh = xs_daemon_open(); + for (p = 2; p < argc; p++) + len += strlen(argv[p]) + 1; + if (len) { + par = malloc(len); + if (!par) { + fprintf(stderr, "Allocation error.\n"); + return 1; + } + len = 0; + for (p = 2; p < argc; p++) { + memcpy(par + len, argv[p], strlen(argv[p]) + 1); + len += strlen(argv[p]) + 1; + } + } - if (xsh == NULL) { - fprintf(stderr, "Failed to contact Xenstored.\n"); - return 1; - } + xsh = xs_open(0); + if (xsh == NULL) { + fprintf(stderr, "Failed to contact Xenstored.\n"); + return 1; + } - xs_debug_command(xsh, argv[1], NULL, 0); + ret = xs_debug_command(xsh, argv[1], par, len); + if (!ret) { + rc = 3; + if (errno == EINVAL) { + ret = xs_debug_command(xsh, "help", NULL, 0); + if (ret) + fprintf(stderr, "Command not supported. Valid commands are:\n" + "%s\n", ret); + else + fprintf(stderr, "Error when executing command.\n"); + } else + fprintf(stderr, "Error %d when trying to execute command.\n", + errno); + } else if (strlen(ret) > 0) + printf("%s\n", ret); - xs_daemon_close(xsh); + xs_close(xsh); - return 0; + return rc; } diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_control.c index f169d23..3080e47 100644 --- a/tools/xenstore/xenstored_control.c +++ b/tools/xenstore/xenstored_control.c @@ -17,30 +17,108 @@ */ #include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> #include "utils.h" +#include "talloc.h" #include "xenstored_core.h" #include "xenstored_control.h" +struct cmd_s { + char *cmd; + int (*func)(void *, struct connection *, char **, int); + char *pars; +}; + +static int do_control_check(void *ctx, struct connection *conn, + char **vec, int num) +{ + if (num) + return EINVAL; + + check_store(); + + send_ack(conn, XS_CONTROL); + return 0; +} + +static int do_control_print(void *ctx, struct connection *conn, + char **vec, int num) +{ + if (num != 1) + return EINVAL; + + xprintf("control: %s", vec[0]); + + send_ack(conn, XS_CONTROL); + return 0; +} + +static int do_control_help(void *, struct connection *, char **, int); + +static struct cmd_s cmds[] = { + { "check", do_control_check, "" }, + { "print", do_control_print, "<string>" }, + { "help", do_control_help, "" }, +}; + +static int do_control_help(void *ctx, struct connection *conn, + char **vec, int num) +{ + int cmd, len = 0; + char *resp; + + if (num) + return EINVAL; + + for (cmd = 0; cmd < ARRAY_SIZE(cmds); cmd++) { + len += strlen(cmds[cmd].cmd) + 1; + len += strlen(cmds[cmd].pars) + 1; + } + len++; + + resp = talloc_array(ctx, char, len); + if (!resp) + return ENOMEM; + + len = 0; + for (cmd = 0; cmd < ARRAY_SIZE(cmds); cmd++) { + strcpy(resp + len, cmds[cmd].cmd); + len += strlen(cmds[cmd].cmd); + resp[len] = '\t'; + len++; + strcpy(resp + len, cmds[cmd].pars); + len += strlen(cmds[cmd].pars); + resp[len] = '\n'; + len++; + } + resp[len] = 0; + + send_reply(conn, XS_CONTROL, resp, len); + return 0; +} + int do_control(struct connection *conn, struct buffered_data *in) { int num; + int cmd; + char **vec; if (conn->id != 0) return EACCES; num = xs_count_strings(in->buffer, in->used); + vec = talloc_array(in, char *, num); + if (!vec) + return ENOMEM; + if (get_strings(in, vec, num) != num) + return EIO; - if (streq(in->buffer, "print")) { - if (num < 2) - return EINVAL; - xprintf("control: %s", in->buffer + strlen(in->buffer) + 1); - } + for (cmd = 0; cmd < ARRAY_SIZE(cmds); cmd++) + if (streq(vec[0], cmds[cmd].cmd)) + return cmds[cmd].func(in, conn, vec + 1, num - 1); - if (streq(in->buffer, "check")) - check_store(); - - send_ack(conn, XS_CONTROL); - - return 0; + return EINVAL; }
The Xenstore protocol supports the XS_CONTROL command for triggering various actions in the Xenstore daemon. Enhance that support by using a command table and adding a help function. Support multiple control commands in the associated xenstore-control program used to issue XS_CONTROL commands. Signed-off-by: Juergen Gross <jgross@suse.com> --- tools/xenstore/xenstore_control.c | 65 +++++++++++++++++------- tools/xenstore/xenstored_control.c | 100 +++++++++++++++++++++++++++++++++---- 2 files changed, 135 insertions(+), 30 deletions(-)