static char *run(const char *cmd, int *exitstatus) { pid_t pid; int p[2]; char *ret; int status; if (pipe(p) != 0) err(1, "creating pipe"); pid = fork(); if (pid == -1) err(1, "forking"); if (pid == 0) { if (dup2(p[1], STDOUT_FILENO) != STDOUT_FILENO || dup2(p[1], STDERR_FILENO) != STDERR_FILENO || close(p[0]) != 0 || close(STDIN_FILENO) != 0 || open("/dev/null", O_RDONLY) != STDIN_FILENO) exit(128); status = system(cmd); if (WIFEXITED(status)) exit(WEXITSTATUS(status)); /* Here's a hint... */ exit(128 + WTERMSIG(status)); } close(p[1]); ret = grab_fd(p[0]); /* This shouldn't fail... */ if (waitpid(pid, &status, 0) != pid) err(1, "Failed to wait for child"); close(p[0]); if (WIFEXITED(status)) *exitstatus = WEXITSTATUS(status); else *exitstatus = -WTERMSIG(status); return ret; }
/* arg* may be null */ static char *ask_process(const tal_t *ctx, const char *name, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5) { char *output; int fds[2], status; if (pipe(fds) != 0) return NULL; switch (fork()) { case -1: return NULL; case 0: close(fds[0]); dup2(fds[1], STDOUT_FILENO); execlp(name, name, arg1, arg2, arg3, arg4, arg5, NULL); exit(errno); } close(fds[1]); output = grab_fd(ctx, fds[0]); close_noerr(fds[0]); wait(&status); if (!WIFEXITED(status)) { output = tal_free(output); errno = EINTR; } else if (WEXITSTATUS(status)) { output = tal_free(output); errno = WEXITSTATUS(status); } return output; }
char *run_with_timeout(const void *ctx, const char *cmd, bool *ok, unsigned *timeout_ms) { pid_t pid; int p[2]; char *ret; int status, ms; struct timeval start, end; *ok = false; if (pipe(p) != 0) return talloc_asprintf(ctx, "Failed to create pipe: %s", strerror(errno)); if (tools_verbose) printf("Running: %s\n", cmd); gettimeofday(&start, NULL); pid = fork(); if (pid == -1) { close_noerr(p[0]); close_noerr(p[1]); return talloc_asprintf(ctx, "Failed to fork: %s", strerror(errno)); return NULL; } if (pid == 0) { struct itimerval itim; if (dup2(p[1], STDOUT_FILENO) != STDOUT_FILENO || dup2(p[1], STDERR_FILENO) != STDERR_FILENO || close(p[0]) != 0 || close(STDIN_FILENO) != 0 || open("/dev/null", O_RDONLY) != STDIN_FILENO) exit(128); signal(SIGALRM, killme); itim.it_interval.tv_sec = itim.it_interval.tv_usec = 0; itim.it_value.tv_sec = *timeout_ms / 1000; itim.it_value.tv_usec = (*timeout_ms % 1000) * 1000; setitimer(ITIMER_REAL, &itim, NULL); status = system(cmd); if (WIFEXITED(status)) exit(WEXITSTATUS(status)); /* Here's a hint... */ exit(128 + WTERMSIG(status)); } close(p[1]); ret = grab_fd(ctx, p[0], NULL); /* This shouldn't fail... */ if (waitpid(pid, &status, 0) != pid) err(1, "Failed to wait for child"); gettimeofday(&end, NULL); if (end.tv_usec < start.tv_usec) { end.tv_usec += 1000000; end.tv_sec--; } ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000; if (ms > *timeout_ms) *timeout_ms = 0; else *timeout_ms -= ms; close(p[0]); if (tools_verbose) { printf("%s", ret); printf("Finished: %u ms, %s %u\n", ms, WIFEXITED(status) ? "exit status" : "killed by signal", WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)); } *ok = (WIFEXITED(status) && WEXITSTATUS(status) == 0); return ret; }