qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Add support for a configuration file


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH] Add support for a configuration file
Date: Tue, 13 May 2008 16:19:05 -0500

There has been an awful lot of discussion about a configuration file with
almost no general agreement except that one is strongly desired.

I thought about it a bit, and I think a nice step would be to simply allow
the current configuration parameters to be stored in a file using a pretty
familiar format.

I think this is pretty useful as-is.  I think it also gives us a reasonable
way to move forward that will keep everyone pretty happy.

Here's a short example:

qemu-system-x86_64 -hda ~/images/linux.img -snapshot -vnc :2

Would become `foo.qemu':

 # Main disk image
 hda=/home/anthony/images/linux.img

 # Redirect disk writes to a temporary image
 snapshot

 # Make the graphical display available on port 5902
 vnc=:2

With:

qemu-system-x86_64 -config foo.qemu

Signed-off-by: Anthony Liguori <address@hidden>

diff --git a/qemu-doc.texi b/qemu-doc.texi
index cca483c..4861fc0 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -395,6 +395,12 @@ Sets the @var{name} of the guest.
 This name will be display in the SDL window caption.
 The @var{name} will also be used for the VNC server.
 
address@hidden -config @var{file}
+Reads configuration options from @var{file}.  The format of @var{file} is the
+same as the command line options, except no dash ``-'' is required.  Options
+that take an argument are in the format @var{option=value}.  A pound ``#''
+character can be used as a comment.
+
 @end table
 
 Display options:
diff --git a/vl.c b/vl.c
index 67712f0..2eb39dd 100644
--- a/vl.c
+++ b/vl.c
@@ -7276,6 +7276,7 @@ static void help(int exitcode)
            "-clock          force the use of the given methods for timer 
alarm.\n"
            "                To see what timers are available use -clock ?\n"
            "-startdate      select initial date of the clock\n"
+          "-config FILE    read command line options from FILE\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -7379,6 +7380,7 @@ enum {
     QEMU_OPTION_old_param,
     QEMU_OPTION_clock,
     QEMU_OPTION_startdate,
+    QEMU_OPTION_config,
 };
 
 typedef struct QEMUOption {
@@ -7490,6 +7492,7 @@ const QEMUOption qemu_options[] = {
 #endif
     { "clock", HAS_ARG, QEMU_OPTION_clock },
     { "startdate", HAS_ARG, QEMU_OPTION_startdate },
+    { "config", HAS_ARG, QEMU_OPTION_config },
     { NULL },
 };
 
@@ -7665,9 +7668,106 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 }
 #endif
 
+static char **insert_opts(char **old_argv, int *old_argc, int index,
+                         char **argv, int argc)
+{
+    char **new_argv;
+
+    /* Allocate larger array */
+    new_argv = realloc(old_argv, (*old_argc + argc) * sizeof(old_argv[0]));
+    if (new_argv == NULL) {
+       fprintf(stderr, "allocate failed in insert_opts\n");
+       exit(1);
+    }
+
+    /* move elements after insertion point to end of array */
+    memmove(new_argv+index + argc, new_argv + index,
+           (*old_argc - index) * sizeof(argv[0]));
+
+    /* copy in new elements */
+    memcpy(new_argv + index, argv, argc * sizeof(argv[0]));
+
+    *old_argc += argc;
+
+    if (0) { /* for debugging */
+       int i;
+       printf("argv[] = {");
+       for (i = 0; i < *old_argc; i++) {
+           if (i)
+               printf(", ");
+           printf("\"%s\"", new_argv[i]);
+       }
+       printf("}\n");
+    }
+
+    return new_argv;
+}
+
+static char **parse_config_file(const char *file, int *pargc)
+{
+    FILE *f;
+    char buffer[4096];
+    char **argv = NULL;
+    int argc = 0;
+
+    f = fopen(file, "r");
+    if (f == NULL)
+       return NULL;
+
+    while (fgets(buffer, sizeof(buffer), f)) {
+       char *ptr = buffer;
+       char *tok, *key, *val;
+       char *targv[2];
+       int targc = 0;
+
+       /* skip whitespace */
+       while (isspace(*ptr)) ptr++;
+
+       /* skip comments or empty lines */
+       if (*ptr == '#' || *ptr == 0)
+           continue;
+
+       /* trim new line and carriage return if necessary */
+       tok = strchr(ptr, '\n');
+       if (tok)
+           *tok = 0;
+       tok = strchr(ptr, '\r');
+       if (tok)
+           *tok = 0;
+
+       /* check if it has an argument */
+       tok = strchr(ptr, '=');
+       if (tok)
+           *tok = 0;
+
+       /* add key */
+       if (asprintf(&key, "--%s", ptr) == -1)
+           return NULL;
+       targv[targc++] = key;
+
+       /* add argument (optionally) */
+       if (tok) {
+           if (asprintf(&val, "%s", tok + 1) == -1)
+               return NULL;
+           targv[targc++] = val;
+       }
+
+       /* insert new arguments */
+       argv = insert_opts(argv, &argc, argc, targv, targc);
+       if (argv == NULL)
+           return NULL;
+    }
+
+    fclose(f);
+
+    *pargc = argc;
+
+    return argv;
+}
+
 #define MAX_NET_CLIENTS 32
 
-int main(int argc, char **argv)
+int main(int orig_argc, char **orig_argv)
 {
 #ifdef CONFIG_GDBSTUB
     int use_gdbstub;
@@ -7700,6 +7800,10 @@ int main(int argc, char **argv)
     int fds[2];
     const char *pid_file = NULL;
     VLANState *vlan;
+    char **argv = NULL;
+    int argc = 0;
+
+    argv = insert_opts(argv, &argc, 0, orig_argv, orig_argc);
 
     LIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
@@ -8297,6 +8401,20 @@ int main(int argc, char **argv)
                     }
                 }
                 break;
+           case QEMU_OPTION_config: {
+               char **config_argv;
+               int config_argc;
+
+               config_argv = parse_config_file(optarg, &config_argc);
+               if (config_argv == NULL) {
+                   fprintf(stderr, "failed to parse config file `%s'\n", 
optarg);
+                   exit(1);
+               }
+
+               argv = insert_opts(argv, &argc, optind,
+                                  config_argv, config_argc);
+               free(config_argv);
+               } break;
             }
         }
     }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]