diff mbox

[v3,4/7] xenstore: enhance control command support

Message ID 20170222152851.20099-5-jgross@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jürgen Groß Feb. 22, 2017, 3:28 p.m. UTC
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(-)

Comments

Wei Liu Feb. 23, 2017, 11:06 a.m. UTC | #1
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.
Jürgen Groß Feb. 24, 2017, 5:50 a.m. UTC | #2
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 mbox

Patch

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;
 }