diff options
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/actions.h | 2 | ||||
-rw-r--r-- | daemon/command.c | 101 | ||||
-rw-r--r-- | daemon/stubs.c | 65 |
4 files changed, 169 insertions, 0 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 400f1641..1c52f7ae 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -21,6 +21,7 @@ noinst_PROGRAMS = guestfsd guestfsd_SOURCES = \ actions.h \ augeas.c \ + command.c \ daemon.h \ devsparts.c \ dir.c \ diff --git a/daemon/actions.h b/daemon/actions.h index d53729bf..90aeb8d0 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -70,3 +70,5 @@ extern char **do_mounts (void); extern int do_umount_all (void); extern int do_lvm_remove_all (void); extern char *do_file (const char *path); +extern char *do_command (char * const* const arguments); +extern char **do_command_lines (char * const* const arguments); diff --git a/daemon/command.c b/daemon/command.c new file mode 100644 index 00000000..589ca769 --- /dev/null +++ b/daemon/command.c @@ -0,0 +1,101 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 Red Hat Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../src/guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" + +char * +do_command (char * const * const argv) +{ + char *out, *err; + int r; + + /* We need a root filesystem mounted to do this. */ + NEED_ROOT (NULL); + + /* Conveniently, argv is already a NULL-terminated argv-style array + * of parameters, so we can pass it straight in to our internal + * commandv. We just have to check the list is non-empty. + */ + if (argv[0] == NULL) { + reply_with_error ("command: passed an empty list"); + return NULL; + } + + CHROOT_IN; + r = commandv (&out, &err, argv); + CHROOT_OUT; + + if (r == -1) { + reply_with_error ("%s", err); + free (out); + free (err); + return NULL; + } + + free (err); + + return out; /* Caller frees. */ +} + +char ** +do_command_lines (char * const * const argv) +{ + char *out; + char **lines = NULL; + int size = 0, alloc = 0; + char *p, *pend; + + out = do_command (argv); + if (out == NULL) + return NULL; + + /* Now convert the output to a list of lines. */ + p = out; + while (p) { + pend = strchr (p, '\n'); + if (pend) { + *pend = '\0'; + pend++; + } + + /* Final \n? Don't return an empty final element. */ + if (pend && *pend == '\0') break; + + if (add_string (&lines, &size, &alloc, p) == -1) { + free (out); + return NULL; + } + + p = pend; + } + + free (out); + + if (add_string (&lines, &size, &alloc, NULL) == -1) + return NULL; + + return lines; +} diff --git a/daemon/stubs.c b/daemon/stubs.c index af0f14c3..9a0dc912 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -1164,6 +1164,65 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_file_args, (char *) &args); } +static void command_stub (XDR *xdr_in) +{ + char *r; + struct guestfs_command_args args; + char **arguments; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_command_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "command"); + return; + } + args.arguments.arguments_val = realloc (args.arguments.arguments_val, sizeof (char *) * (args.arguments.arguments_len+1)); + args.arguments.arguments_val[args.arguments.arguments_len] = NULL; + arguments = args.arguments.arguments_val; + + r = do_command (arguments); + if (r == NULL) + /* do_command has already called reply_with_error */ + goto done; + + struct guestfs_command_ret ret; + ret.output = r; + reply ((xdrproc_t) &xdr_guestfs_command_ret, (char *) &ret); + free (r); +done: + xdr_free ((xdrproc_t) xdr_guestfs_command_args, (char *) &args); +} + +static void command_lines_stub (XDR *xdr_in) +{ + char **r; + struct guestfs_command_lines_args args; + char **arguments; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_command_lines_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "command_lines"); + return; + } + args.arguments.arguments_val = realloc (args.arguments.arguments_val, sizeof (char *) * (args.arguments.arguments_len+1)); + args.arguments.arguments_val[args.arguments.arguments_len] = NULL; + arguments = args.arguments.arguments_val; + + r = do_command_lines (arguments); + if (r == NULL) + /* do_command_lines has already called reply_with_error */ + goto done; + + struct guestfs_command_lines_ret ret; + ret.lines.lines_len = count_strings (r); + ret.lines.lines_val = r; + reply ((xdrproc_t) &xdr_guestfs_command_lines_ret, (char *) &ret); + free_strings (r); +done: + xdr_free ((xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -1314,6 +1373,12 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_FILE: file_stub (xdr_in); break; + case GUESTFS_PROC_COMMAND: + command_stub (xdr_in); + break; + case GUESTFS_PROC_COMMAND_LINES: + command_lines_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); } |