/* orginal written by E. Mattes */ #include #include #include #include #ifdef __EMX__ #include #include #else #include #endif static int v = 1; static void usage(void) { puts("Usage: fork [-r#] [-svw]"); puts("Options:"); puts(" -r# Set number of recursion levels"); puts(" -s Set SIGCLD handler"); puts(" -v Be verbose"); puts(" -w Wait for children"); exit(1); } static void handler(int sig) { switch (sig) { case SIGCLD: printf("process %d get SIGCLD\n", getpid()); break; default: printf("Signal %d\n", sig); break; } fflush(stdout); signal(SIGCLD, SIG_ACK); } int main(int argc, char *argv[]) { int c, i, n, p, t, v0, rep, opt_s, opt_w, verb; char buf[32], *fork_name; rep = 0; opt_s = 0; opt_w = 0; verb = 1; for (i = 0; i < argc; i++) if (*(argv[i]) != '-') continue; else switch (*(argv[i] + 1)) { case 'r': rep = atoi(argv[i] + 2); break; case 's': opt_s = 1; break; case 'v': verb = 2; break; case 'w': opt_w = 1; break; default: usage(); } if (rep > 6) { printf("*** That's too dangerous ***\n"); return (1); } if (opt_s) signal(SIGCLD, handler); v0 = v; printf("Here's fork%d (pid=%d, ppid=%d)\n", v0, getpid(), getppid()); fork_name = strdup("fork"); /* test heap */ n = 0; do { ++v; i = fork(); if (verb >= 1) printf("fork() call returns: %d\n", i); if (i < 0) { sprintf(buf, "fork%d: fork", v0); perror(buf); return (1); } else if (i == 0) { v0 = v; n = 0; printf("New child: Here's forked %s%d (pid=%d, ppid=%d)\n", fork_name, v0, getpid(), getppid()); } else { ++n; if (verb >= 1) printf("father: fork%d: forked fork has pid %d\n", v0, i); } } while (v <= rep); if (opt_w && n > 0) { if (verb >= 2) printf("fork%d: waiting for %d child%s\n", v0, n, (n == 1 ? "" : "ren")); while (n > 0) { p = wait(&t); if (verb >= 1) printf("wait() call returns: pid %d stat %d\n", i, t); if (p == -1) { sprintf(buf, "fork%d: wait", v0); perror(buf); return (1); } else { --n; if ((t & 0xff) == 0) printf("fork%d: process %d terminated normally, rc=%d\n", v0, p, t >> 8); else if ((t & 0xff) == 127) printf("fork%d: process %d stopped by signal %d\n", v0, p, t >> 8); else printf("fork%d: process %d terminated by signal %d\n", v0, p, t & 0xff); } } } if (verb >= 2) printf("fork%d: end with ret code %d\n", v0, 10 + getpid()); return (10 + getpid()); }