[Top][All Lists]
[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;
}
}
}