Re-factor out qemudExec() so that it can be used to
launch dnsmasq.
Note, exec() doesn't take an argc argument, just a
null-terminated argv, so there's no need for
qemudBuildCommandLine() to return argc.
Note, Dan originally folded this into his qemu patches, but
it looks to have since been lost.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
Index: libvirt/qemud/conf.c
===================================================================
--- libvirt.orig/qemud/conf.c
+++ libvirt/qemud/conf.c
@@ -775,16 +775,15 @@ static int qemudParseXML(struct qemud_se
*/
int qemudBuildCommandLine(struct qemud_server *server,
struct qemud_vm *vm,
- char ***argv,
- int *argc) {
- int n = -1, i;
+ char ***argv) {
+ int len, n = -1, i;
char memory[50];
char vcpus[50];
char boot[QEMUD_MAX_BOOT_DEVS+1];
struct qemud_vm_disk_def *disk = vm->def.disks;
struct qemud_vm_net_def *net = vm->def.nets;
- *argc = 1 + /* qemu */
+ len = 1 + /* qemu */
2 + /* machine type */
(vm->def.virtType == QEMUD_VIRT_QEMU ? 1 : 0) + /* Disable kqemu */
2 * vm->def.ndisks + /* disks*/
@@ -803,7 +802,7 @@ int qemudBuildCommandLine(struct qemud_s
sprintf(memory, "%d", vm->def.memory/1024);
sprintf(vcpus, "%d", vm->def.vcpus);
- if (!(*argv = malloc(sizeof(char *) * (*argc +1))))
+ if (!(*argv = malloc(sizeof(char *) * (len+1))))
goto no_memory;
if (!((*argv)[++n] = strdup(vm->def.os.binary)))
goto no_memory;
Index: libvirt/qemud/qemud.c
===================================================================
--- libvirt.orig/qemud/qemud.c
+++ libvirt/qemud/qemud.c
@@ -324,103 +324,110 @@ static int qemudDispatchServer(struct qe
}
-int qemudStartVMDaemon(struct qemud_server *server,
- struct qemud_vm *vm) {
- char **argv = NULL;
- int argc = 0;
- int pid;
- int i, ret = -1;
- int stdinfd = -1;
+static int
+qemudExec(struct qemud_server *server, char **argv,
+ int *retpid, int *outfd, int *errfd) {
+ int pid, null;
int pipeout[2] = {-1,-1};
int pipeerr[2] = {-1,-1};
- if (vm->def.vncPort < 0)
- vm->def.vncActivePort = 5900 + server->nextvmid;
- else
- vm->def.vncActivePort = vm->def.vncPort;
-
- if (qemudBuildCommandLine(server, vm, &argv, &argc) < 0)
- return -1;
-
- if (1) { /* XXX debug stuff */
- QEMUD_DEBUG("Spawn QEMU '");
- for (i = 0 ; i < argc; i++) {
- QEMUD_DEBUG("%s", argv[i]);
- if (i == (argc-1)) {
- QEMUD_DEBUG("'\n");
- } else {
- QEMUD_DEBUG(" ");
- }
- }
- }
-
- if ((stdinfd = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
- qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot open %s",
_PATH_DEVNULL);
+ if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
+ qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot open %s :
%s",
+ _PATH_DEVNULL, strerror(errno));
goto cleanup;
}
- if (pipe(pipeout) < 0) {
- qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot create
pipe");
- goto cleanup;
- }
-
- if (pipe(pipeerr) < 0) {
- qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot create
pipe");
+ if ((outfd != NULL && pipe(pipeout) < 0) ||
+ (errfd != NULL && pipe(pipeerr) < 0)) {
+ qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot create pipe :
%s",
+ strerror(errno));
goto cleanup;
}
if ((pid = fork()) < 0) {
- qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot fork child
process");
+ qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot fork child process
: %s",
+ strerror(errno));
goto cleanup;
}
if (pid) { /* parent */
- close(stdinfd);
- close(pipeout[1]);
- close(pipeerr[1]);
- qemudSetNonBlock(pipeout[0]);
- qemudSetNonBlock(pipeerr[0]);
- vm->def.id = server->nextvmid++;
- vm->pid = pid;
- vm->stdout = pipeout[0];
- vm->stderr = pipeerr[0];
-
- } else { /* child */
- int null;
- if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0)
- _exit(1);
-
- if (close(pipeout[0]) < 0)
- _exit(1);
- if (close(pipeerr[0]) < 0)
- _exit(1);
-
- if (dup2(stdinfd, STDIN_FILENO) < 0)
- _exit(1);
- if (dup2(pipeout[1], STDOUT_FILENO) < 0)
- _exit(1);
- if (dup2(pipeerr[1], STDERR_FILENO) < 0)
- _exit(1);
-
- int open_max = sysconf (_SC_OPEN_MAX);
- for (i = 0; i < open_max; i++)
- if (i != STDOUT_FILENO &&
- i != STDERR_FILENO &&
- i != STDIN_FILENO)
- close(i);
+ close(null);
+ if (outfd) {
+ close(pipeout[1]);
+ qemudSetNonBlock(pipeout[0]);
+ *outfd = pipeout[0];
+ }
+ if (errfd) {
+ close(pipeerr[1]);
+ qemudSetNonBlock(pipeerr[0]);
+ *errfd = pipeerr[0];
+ }
+ *retpid = pid;
+ return 0;
+ }
- execvp(argv[0], argv);
+ /* child */
+ if (pipeout[0] > 0 && close(pipeout[0]) < 0)
+ _exit(1);
+ if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
_exit(1);
- }
- ret = 0;
+ if (dup2(null, STDIN_FILENO) < 0)
+ _exit(1);
+ if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
+ _exit(1);
+ if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
+ _exit(1);
+
+ int i, open_max = sysconf (_SC_OPEN_MAX);
+ for (i = 0; i < open_max; i++)
+ if (i != STDOUT_FILENO &&
+ i != STDERR_FILENO &&
+ i != STDIN_FILENO)
+ close(i);
+
+ execvp(argv[0], argv);
+
+ _exit(1);
+
+ return 0;
cleanup:
+ if (pipeerr[0] > 0)
+ close(pipeerr[0] > 0);
+ if (pipeerr[1])
+ close(pipeerr[1] > 0);
+ if (pipeout[0])
+ close(pipeout[0] > 0);
+ if (pipeout[1])
+ close(pipeout[1] > 0);
+ if (null > 0)
+ close(null);
+ return -1;
+}
+
+
+int qemudStartVMDaemon(struct qemud_server *server,
+ struct qemud_vm *vm) {
+ char **argv = NULL;
+ int i, ret = -1;
+
+ if (vm->def.vncPort < 0)
+ vm->def.vncActivePort = 5900 + server->nextvmid;
+ else
+ vm->def.vncActivePort = vm->def.vncPort;
+
+ if (qemudBuildCommandLine(server, vm, &argv) < 0)
+ return -1;
+
+ if (qemudExec(server, argv, &vm->pid, &vm->stdout, &vm->stderr)
== 0) {
+ vm->def.id = server->nextvmid++;
+ ret = 0;
+ }
- for (i = 0 ; i < argc ; i++) {
+ for (i = 0 ; argv[i] ; i++)
free(argv[i]);
- }
free(argv);
return ret;
--