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)
31 pr_err("fork() failed: %m\n");
37 pr_info("Fork %d, child %d\n", child_count, child);
41 process_count = child_count;
42 /* reset child's child count */
48 int harvest_zombies(int pid)
56 pr_info("Waiting on pid %d, children left: %d\n", pid,
59 pid = waitpid(pid, &status, 0);
61 pr_err("Error on wait(): %m\n");
62 child_count--; /* Decrement child count anyway */
66 pr_info("pid %d: exit code %d. Children left: %d\n", pid,
74 * Runs a command cmd with params argv, connects stdin and stdout to
77 * Returns the pid of the executed process
79 int run_piped(const char *cmd, char *const argv[],
80 int *stdinfd, int *stdoutfd, int *stderrfd)
82 int ifd[2], ofd[2], efd[2], pid;
84 pr_info("Running command %s\n", cmd);
86 if (stdinfd && pipe(ifd)) {
87 pr_err("pipe() failed: %m\n");
91 if (stdoutfd && pipe(ofd)) {
92 pr_err("pipe() failed: %m\n");
96 if (stderrfd && pipe(efd)) {
97 pr_err("pipe() failed: %m\n");
102 if (pid) { /* Parent side */
123 dup2(ifd[0], STDIN_FILENO);
128 dup2(ofd[1], STDOUT_FILENO);
133 dup2(efd[1], STDERR_FILENO);
136 /* Now we have redirected standard streams to parent process */
138 pr_err("Failed to execv command %s: %m\n", cmd);
145 * Runs a command cmd with params argv, connects stdin and stdout to
148 * Returns the pid of the executed process
150 int run_piped_stream(const char *cmd, char *const argv[],
151 FILE **stdinf, FILE **stdoutf, FILE **stderrf)
153 int ifd, ofd, efd, pid;
169 pid = run_piped(cmd, argv, i, o, e);
172 *stdinf = fdopen(ifd, "r");
173 if (*stdinf == NULL) {
174 pr_err("Error opening file stream for fd %d: %m\n",
181 *stdoutf = fdopen(ofd, "r");
182 if (*stdoutf == NULL) {
183 pr_err("Error opening file stream for fd %d: %m\n",
190 *stderrf = fdopen(efd, "r");
191 if (*stderrf == NULL) {
192 pr_err("Error opening file stream for fd %d: %m\n",
202 * Forks a child and executes a command to run on parallel
205 #define max(a,b) (a) < (b) ? (b) : (a)
206 #define BUF_SIZE (128*1024)
207 int run(const char *cmd, char *const argv[])
214 char stdoutstr[32], stderrstr[32], indent[16] = { " " };
216 indent[get_parent_count() + 1] = 0;
218 if ((child = do_fork()))
221 child = run_piped(cmd, argv, NULL, &ofd, &efd);
222 snprintf(stdoutstr, 32, "%sstdout", green_color);
223 snprintf(stderrstr, 32, "%sstderr", red_color);
235 maxfd = max(ofd, efd);
236 error = select(maxfd, &rfds, NULL, NULL, NULL);
239 printf("Error with select: %m\n");
243 if (FD_ISSET(ofd, &rfds)) {
245 bytes = read(ofd, rbuf, BUF_SIZE);
249 if (FD_ISSET(efd, &rfds)) {
251 bytes = read(efd, rbuf, BUF_SIZE);
255 pr_err("select() returned unknown fd\n");
260 pr_err("read() failed: %m\n");
265 * Workaround: When a process had die and it has only
266 * written to stderr, select() doesn't indicate that
267 * there might be something to read in stderr fd. To
268 * work around this issue, we try to read stderr just
269 * in case in order to ensure everything gets read.
272 bytes = read(efd, rbuf, BUF_SIZE);
281 printf("%s[%5d %s] %s: %s%s\n", indent,
282 child, cmd, typestr, sptr, normal_color);
292 harvest_zombies(child);