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@xxxxxxxxxx> 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; --