int virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen) { int pipefd[2]; int len; if (pipe(pipefd) < 0) return -1; pid_t pid = fork(); switch (pid) { case 0: VIR_FORCE_CLOSE(pipefd[0]); virtTestCaptureProgramExecChild(argv, pipefd[1]); VIR_FORCE_CLOSE(pipefd[1]); _exit(1); case -1: return -1; default: VIR_FORCE_CLOSE(pipefd[1]); len = virFileReadLimFD(pipefd[0], maxlen, buf); VIR_FORCE_CLOSE(pipefd[0]); if (virPidWait(pid, NULL) < 0) return -1; return len; } }
static int daemonForkIntoBackground(const char *argv0) { int statuspipe[2]; if (pipe(statuspipe) < 0) return -1; pid_t pid = fork(); switch (pid) { case 0: { /* intermediate child */ int stdinfd = -1; int stdoutfd = -1; int nextpid; VIR_FORCE_CLOSE(statuspipe[0]); if ((stdinfd = open("/dev/null", O_RDONLY)) < 0) goto cleanup; if ((stdoutfd = open("/dev/null", O_WRONLY)) < 0) goto cleanup; if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO) goto cleanup; if (dup2(stdoutfd, STDOUT_FILENO) != STDOUT_FILENO) goto cleanup; if (dup2(stdoutfd, STDERR_FILENO) != STDERR_FILENO) goto cleanup; if (stdinfd > STDERR_FILENO && VIR_CLOSE(stdinfd) < 0) goto cleanup; if (stdoutfd > STDERR_FILENO && VIR_CLOSE(stdoutfd) < 0) goto cleanup; if (setsid() < 0) goto cleanup; nextpid = fork(); switch (nextpid) { case 0: /* grandchild */ return statuspipe[1]; case -1: /* error */ goto cleanup; default: /* intermediate child succeeded */ _exit(EXIT_SUCCESS); } cleanup: VIR_FORCE_CLOSE(stdoutfd); VIR_FORCE_CLOSE(stdinfd); VIR_FORCE_CLOSE(statuspipe[1]); _exit(EXIT_FAILURE); } case -1: /* error in parent */ goto error; default: { /* parent */ int ret; char status; VIR_FORCE_CLOSE(statuspipe[1]); /* We wait to make sure the first child forked successfully */ if (virPidWait(pid, NULL) < 0) goto error; /* If we get here, then the grandchild was spawned, so we * must exit. Block until the second child initializes * successfully */ again: ret = read(statuspipe[0], &status, 1); if (ret == -1 && errno == EINTR) goto again; VIR_FORCE_CLOSE(statuspipe[0]); if (ret != 1) { char ebuf[1024]; fprintf(stderr, _("%s: error: unable to determine if daemon is " "running: %s\n"), argv0, virStrerror(errno, ebuf, sizeof(ebuf))); exit(EXIT_FAILURE); } else if (status != 0) { fprintf(stderr, _("%s: error: %s. Check /var/log/messages or run " "without --daemon for more info.\n"), argv0, virDaemonErrTypeToString(status)); exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); } } error: VIR_FORCE_CLOSE(statuspipe[0]); VIR_FORCE_CLOSE(statuspipe[1]); return -1; }