diff mbox

[v2,2/5] xenstore: enhance control command support

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

Commit Message

Jürgen Groß Feb. 21, 2017, 3:07 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. Move all the XS_CONTROL
related code to a new source file xenstored_control.c.

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/Makefile            |   4 +-
 tools/xenstore/xenstore_control.c  |  65 +++++++++++++------
 tools/xenstore/xenstored_control.c | 124 +++++++++++++++++++++++++++++++++++++
 tools/xenstore/xenstored_control.h |  19 ++++++
 tools/xenstore/xenstored_core.c    |  27 +-------
 tools/xenstore/xenstored_core.h    |   2 +-
 6 files changed, 195 insertions(+), 46 deletions(-)
 create mode 100644 tools/xenstore/xenstored_control.c
 create mode 100644 tools/xenstore/xenstored_control.h

Comments

Wei Liu Feb. 22, 2017, 12:36 p.m. UTC | #1
On Tue, Feb 21, 2017 at 04:07:34PM +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. Move all the XS_CONTROL
> related code to a new source file xenstored_control.c.
> 
> Support multiple control commands in the associated xenstore-control
> program used to issue XS_CONTROL commands.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>

Can you please break the refactoring and enhancement into two patches.
That would be easier for me to review.
Jürgen Groß Feb. 22, 2017, 12:41 p.m. UTC | #2
On 22/02/17 13:36, Wei Liu wrote:
> On Tue, Feb 21, 2017 at 04:07:34PM +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. Move all the XS_CONTROL
>> related code to a new source file xenstored_control.c.
>>
>> Support multiple control commands in the associated xenstore-control
>> program used to issue XS_CONTROL commands.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
> 
> Can you please break the refactoring and enhancement into two patches.
> That would be easier for me to review.
> 

Okay.


Juergen
diff mbox

Patch

diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 36b6fd4..bdca108 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -23,7 +23,9 @@  LDFLAGS += $(LDFLAGS-y)
 CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
 CLIENTS += xenstore-write xenstore-ls xenstore-watch
 
-XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o hashtable.o
+XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o
+XENSTORED_OBJS += xenstored_transaction.o xenstored_control.o
+XENSTORED_OBJS += xs_lib.o talloc.o utils.o tdb.o hashtable.o
 
 XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_posix.o
 XENSTORED_OBJS_$(CONFIG_SunOS) = xenstored_solaris.o xenstored_posix.o xenstored_probes.o
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
new file mode 100644
index 0000000..3080e47
--- /dev/null
+++ b/tools/xenstore/xenstored_control.c
@@ -0,0 +1,124 @@ 
+/*
+    Interactive commands for Xen Store Daemon.
+    Copyright (C) 2017 Juergen Gross, SUSE Linux GmbH
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#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;
+
+	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);
+
+	return EINVAL;
+}
diff --git a/tools/xenstore/xenstored_control.h b/tools/xenstore/xenstored_control.h
new file mode 100644
index 0000000..207e0a6
--- /dev/null
+++ b/tools/xenstore/xenstored_control.h
@@ -0,0 +1,19 @@ 
+/*
+    Interactive commands for Xen Store Daemon.
+    Copyright (C) 2017 Juergen Gross, SUSE Linux GmbH
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; If not, see <http://www.gnu.org/licenses/>.
+*/
+
+int do_control(struct connection *conn, struct buffered_data *in);
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index e332d7f..e0f1261 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -51,6 +51,7 @@ 
 #include "xenstored_watch.h"
 #include "xenstored_transaction.h"
 #include "xenstored_domain.h"
+#include "xenstored_control.h"
 #include "tdb.h"
 
 #include "hashtable.h"
@@ -84,7 +85,6 @@  static TDB_CONTEXT *tdb_ctx = NULL;
 static bool trigger_talloc_report = false;
 
 static void corrupt(struct connection *conn, const char *fmt, ...);
-static void check_store(void);
 static const char *sockmsg_string(enum xsd_sockmsg_type type);
 
 #define log(...)							\
@@ -1261,29 +1261,6 @@  static int do_set_perms(struct connection *conn, struct buffered_data *in)
 	return 0;
 }
 
-static int do_control(struct connection *conn, struct buffered_data *in)
-{
-	int num;
-
-	if (conn->id != 0)
-		return EACCES;
-
-	num = xs_count_strings(in->buffer, in->used);
-
-	if (streq(in->buffer, "print")) {
-		if (num < 2)
-			return EINVAL;
-		xprintf("control: %s", in->buffer + get_string(in, 0));
-	}
-
-	if (streq(in->buffer, "check"))
-		check_store();
-
-	send_ack(conn, XS_CONTROL);
-
-	return 0;
-}
-
 static struct {
 	const char *str;
 	int (*func)(struct connection *conn, struct buffered_data *in);
@@ -1764,7 +1741,7 @@  static void clean_store(struct hashtable *reachable)
 }
 
 
-static void check_store(void)
+void check_store(void)
 {
 	char * root = talloc_strdup(NULL, "/");
 	struct hashtable * reachable =
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index f6a56f7..89c1d75 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -158,7 +158,7 @@  TDB_CONTEXT *tdb_context(struct connection *conn);
 bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb);
 
 struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
-
+void check_store(void);
 
 /* Is this a valid node name? */
 bool is_valid_nodename(const char *node);