#include "process.h" #include "debug.h" int child_count = 0; int do_fork(void) { int child, error; child = fork(); if (child < 0) { error = errno; pr_err("fork() failed: %s\n", strerror(error)); return -1; } if (child) { pr_info("Forked child %d\n", child); child_count++; return child; } /* reset child's child count */ child_count = 0; return 0; } int run(const char *cmd, char *const argv[]) { int child, error; if ((child = do_fork())) return child; execvp(cmd, argv); error = errno; pr_err("Failed to execv command %s: %s\n", cmd, strerror(error)); exit(1); return 0; } int harvest_zombies(int pid) { int status, error; if (child_count == 0) return 0; pid = waitpid(pid, &status, 0); if (pid < 0) { error = errno; pr_err("Error on wait(): %s\n", strerror(error)); } else pr_info("pid %d: exit code %d. Children left: %d\n", pid, status, --child_count); return 1; } /* * Runs a command cmd with params argv, connects stdin and stdout to * readfd and writefd * * Returns the pid of the executed process */ int run_piped(const char *cmd, char *const argv[], int *readfd, int *writefd) { int rfd[2], wfd[2], error, pid; if (pipe(rfd)) { error = errno; pr_err("pipe() failed: %s\n", strerror(error)); return -1; } if (pipe(wfd)) { error = errno; pr_err("pipe() failed: %s\n", strerror(error)); return -1; } pid = do_fork(); if (pid) { close(rfd[1]); close(wfd[0]); *readfd = rfd[0]; *writefd = wfd[1]; child_count++; return pid; } close(rfd[0]); close(wfd[1]); dup2(wfd[0], STDIN_FILENO); dup2(rfd[1], STDOUT_FILENO); /* Now we have redirected both stdin and stdout to parent process */ execvp(cmd, argv); error = errno; pr_err("Failed to execv command %s: %s\n", cmd, strerror(error)); exit(1); return 0; } /* * Runs a command cmd with params argv, connects stdin and stdout to * readfd and writefd * * Returns the pid of the executed process */ int run_piped_stream(const char *cmd, char *const argv[], FILE **readf, FILE **writef) { int rfd, wfd, pid, error; pid = run_piped(cmd, argv, &rfd, &wfd); if (readf) { *readf = fdopen(rfd, "r"); if (*readf == NULL) { error = errno; pr_err("Error opening file stream for fd %d: %s\n", rfd, strerror(error)); return -1; } } if (writef) { *writef = fdopen(wfd, "w"); if (*writef == NULL) { error = errno; pr_err("Error opening file stream for fd %d: %s\n", wfd, strerror(error)); return -1; } } return pid; }