2 #include <sys/select.h>
7 static int child_count = 0;
8 static int parent_count = 0;
9 static int process_count = 0;
11 int get_child_count(void)
16 int get_parent_count(void)
21 int get_sibling_count(void)
32 pr_err("fork() failed: %s\n", strerror(error));
38 pr_info("Fork %d, child %d\n", child_count, child);
42 process_count = child_count;
43 /* reset child's child count */
49 int harvest_zombies(int pid)
57 pr_info("Waiting on pid %d, children left: %d\n", pid,
60 pid = waitpid(pid, &status, 0);
63 pr_err("Error on wait(): %s\n", strerror(error));
64 child_count--; /* Decrement child count anyway */
68 pr_info("pid %d: exit code %d. Children left: %d\n", pid,
76 * Runs a command cmd with params argv, connects stdin and stdout to
79 * Returns the pid of the executed process
81 int run_piped(const char *cmd, char *const argv[],
82 int *stdinfd, int *stdoutfd, int *stderrfd)
84 int ifd[2], ofd[2], efd[2], error, pid;
86 if (stdinfd && pipe(ifd)) {
88 pr_err("pipe() failed: %s\n", strerror(error));
92 if (stdoutfd && pipe(ofd)) {
94 pr_err("pipe() failed: %s\n", strerror(error));
98 if (stderrfd && pipe(efd)) {
100 pr_err("pipe() failed: %s\n", strerror(error));
105 if (pid) { /* Parent side */
126 dup2(ifd[0], STDIN_FILENO);
131 dup2(ofd[1], STDOUT_FILENO);
136 dup2(efd[1], STDERR_FILENO);
139 /* Now we have redirected standard streams to parent process */
142 pr_err("Failed to execv command %s: %s\n", cmd, strerror(error));
149 * Runs a command cmd with params argv, connects stdin and stdout to
152 * Returns the pid of the executed process
154 int run_piped_stream(const char *cmd, char *const argv[],
155 FILE **stdinf, FILE **stdoutf, FILE **stderrf)
157 int ifd, ofd, efd, pid, error;
173 pid = run_piped(cmd, argv, i, o, e);
176 *stdinf = fdopen(ifd, "r");
177 if (*stdinf == NULL) {
179 pr_err("Error opening file stream for fd %d: %s\n",
180 ifd, strerror(error));
186 *stdoutf = fdopen(ofd, "r");
187 if (*stdoutf == NULL) {
189 pr_err("Error opening file stream for fd %d: %s\n",
190 ofd, strerror(error));
196 *stderrf = fdopen(efd, "r");
197 if (*stderrf == NULL) {
199 pr_err("Error opening file stream for fd %d: %s\n",
200 efd, strerror(error));
209 * Forks a child and executes a command to run on parallel
212 #define max(a,b) (a) < (b) ? (b) : (a)
213 #define BUF_SIZE (128*1024)
214 int run(const char *cmd, char *const argv[])
220 char stdoutstr[32], stderrstr[32], indent[16] = { " " };
222 indent[get_parent_count() + 1] = 0;
224 if ((child = do_fork()))
227 child = run_piped(cmd, argv, NULL, &ofd, &efd);
228 snprintf(stdoutstr, 32, "%sstdout", green_color);
229 snprintf(stderrstr, 32, "%sstderr", red_color);
241 maxfd = max(ofd, efd);
242 error = select(maxfd, &rfds, NULL, NULL, NULL);
244 if (FD_ISSET(ofd, &rfds)) {
246 bytes = read(ofd, rbuf, BUF_SIZE);
250 if (FD_ISSET(efd, &rfds)) {
252 bytes = read(efd, rbuf, BUF_SIZE);
256 pr_err("select() returned unknown fd\n");
262 pr_err("read() failed: %s\n", strerror(error));
272 printf("%s[%5d %s] %s: %s%s\n", indent,
273 child, cmd, typestr, sptr, normal_color);
280 harvest_zombies(child);