From d8872c43b48eae5501998a4e5a84337017d8fbe6 Mon Sep 17 00:00:00 2001
From: Rob Landley <rob@landley.net>
Date: Sat, 31 May 2014 12:33:24 -0500
Subject: Introduce xfork() and make commands use it, and make some
 WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.

---
 lib/lib.h                 | 1 +
 lib/xwrap.c               | 9 +++++++++
 toys/other/netcat.c       | 4 ++--
 toys/other/timeout.c      | 7 +++----
 toys/pending/bootchartd.c | 4 ++--
 toys/pending/dhcp.c       | 4 +---
 toys/pending/find.c       | 2 +-
 toys/pending/inotifyd.c   | 5 ++---
 toys/pending/nbd_client.c | 2 +-
 toys/pending/openvt.c     | 5 ++---
 toys/pending/tcpsvd.c     | 8 ++++----
 toys/pending/useradd.c    | 8 ++++----
 toys/posix/time.c         | 2 +-
 toys/posix/xargs.c        | 4 ++--
 14 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/lib/lib.h b/lib/lib.h
index 09af2837..3ca631b6 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -91,6 +91,7 @@ void xprintf(char *format, ...);
 void xputs(char *s);
 void xputc(char c);
 void xflush(void);
+pid_t xfork(void);
 void xexec_optargs(int skip);
 void xexec(char **argv);
 void xaccess(char *path, int flags);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 69682f65..3e146fb7 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -113,6 +113,15 @@ void xflush(void)
   if (fflush(stdout) || ferror(stdout)) perror_exit("write");;
 }
 
+pid_t xfork(void)
+{
+  pid_t pid = fork();
+
+  if (pid < 0) perror_exit("fork");
+
+  return pid;
+}
+
 // Call xexec with a chunk of optargs, starting at skip. (You can't just
 // call xexec() directly because toy_init() frees optargs.)
 void xexec_optargs(int skip)
diff --git a/toys/other/netcat.c b/toys/other/netcat.c
index d002b047..3c6f630b 100644
--- a/toys/other/netcat.c
+++ b/toys/other/netcat.c
@@ -140,7 +140,7 @@ void netcat_main(void)
       // Do we need to return immediately because -l has arguments?
 
       if ((toys.optflags & FLAG_l) && toys.optc) {
-        if (fork()) goto cleanup;
+        if (xfork()) goto cleanup;
         close(0);
         close(1);
         close(2);
@@ -149,7 +149,7 @@ void netcat_main(void)
       for (;;) {
         pid_t child = 0;
 
-        // For -l, call accept from the _new_ thread.
+        // For -l, call accept from the _new_ process.
 
         pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address, &len);
         if (pollfds[0].fd<0) perror_exit("accept");
diff --git a/toys/other/timeout.c b/toys/other/timeout.c
index 4b8a87df..f8acabf5 100644
--- a/toys/other/timeout.c
+++ b/toys/other/timeout.c
@@ -60,15 +60,14 @@ void timeout_main(void)
   if (TT.s_signal && -1 == (TT.nextsig = sig_to_num(TT.s_signal)))
     error_exit("bad -s: '%s'", TT.s_signal);
 
-  if (!(TT.pid = fork())) xexec_optargs(1);
+  if (!(TT.pid = xfork())) xexec_optargs(1);
   else {
     int status;
 
     signal(SIGALRM, handler);
     setitimer(ITIMER_REAL, &TT.itv, (void *)&toybuf);
     while (-1 == waitpid(TT.pid, &status, 0) && errno == EINTR);
-    if (WIFEXITED(status)) toys.exitval = WEXITSTATUS(status);
-    else if (WIFSIGNALED(status)) toys.exitval = WTERMSIG(status);
-    else toys.exitval = 1;
+    toys.exitval = WIFEXITED(status)
+      ? WEXITSTATUS(status) : WTERMSIG(status) + 127;
   }
 }
diff --git a/toys/pending/bootchartd.c b/toys/pending/bootchartd.c
index 6839b2ca..cbed4ac0 100644
--- a/toys/pending/bootchartd.c
+++ b/toys/pending/bootchartd.c
@@ -281,7 +281,7 @@ void bootchartd_main()
     parse_config_file("/etc/bootchartd.conf");
 
   memset(toybuf, 0, sizeof(toybuf));
-  if (!(lgr_pid = fork())) {
+  if (!(lgr_pid = xfork())) {
     char *tmp_dir = create_tmp_dir();
 
     sigatexit(generic_signal);
@@ -306,7 +306,7 @@ void bootchartd_main()
   if (bchartd_opt == 1 && toys.optargs[1]) { 
     pid_t prog_pid;
 
-    if (!(prog_pid = fork())) xexec_optargs(1);
+    if (!(prog_pid = xfork())) xexec_optargs(1);
     waitpid(prog_pid, NULL, 0);
     kill(lgr_pid, SIGUSR1);
   }
diff --git a/toys/pending/dhcp.c b/toys/pending/dhcp.c
index 2b432cb3..636746da 100644
--- a/toys/pending/dhcp.c
+++ b/toys/pending/dhcp.c
@@ -318,10 +318,8 @@ static int dhcp_daemon(void)
 {
   int fd = open("/dev/null", O_RDWR);
   if (fd < 0) fd = xcreate("/", O_RDONLY, 0666);
-  pid_t pid = fork();
 
-  if (pid < 0) perror_exit("DAEMON: failed to fork");
-  if (pid) exit(EXIT_SUCCESS);
+  if (xfork()) exit(0);
 
   setsid();
   dup2(fd, 0);
diff --git a/toys/pending/find.c b/toys/pending/find.c
index 58e554b8..1600f5f8 100644
--- a/toys/pending/find.c
+++ b/toys/pending/find.c
@@ -94,7 +94,7 @@ static int do_exec(struct filter_node *filter, struct dirtree *node)
     arg_array[filter->data.e.arg_path_index] = path;
   }
 
-  if (!(pid = fork())) xexec(arg_array);
+  if (!(pid = xfork())) xexec(arg_array);
   free(path);
   waitpid(pid, &status, 0);
 
diff --git a/toys/pending/inotifyd.c b/toys/pending/inotifyd.c
index 98de2546..657fcb5f 100644
--- a/toys/pending/inotifyd.c
+++ b/toys/pending/inotifyd.c
@@ -55,11 +55,10 @@ static void sig_handler(int sig)
 static int exec_wait(char **args)
 {
   int status = 0;
-  pid_t pid = fork();
+  pid_t pid = xfork();
 
   if (!pid) xexec(args);
-  else if (pid > 0) waitpid(pid, &status, 0);
-  else perror_exit("fork");
+  else waitpid(pid, &status, 0);
   return WEXITSTATUS(status);
 }
 
diff --git a/toys/pending/nbd_client.c b/toys/pending/nbd_client.c
index 9164a114..9a5b2f74 100644
--- a/toys/pending/nbd_client.c
+++ b/toys/pending/nbd_client.c
@@ -100,7 +100,7 @@ void nbd_client_main(void)
     if (toys.optflags & FLAG_s) mlockall(MCL_CURRENT|MCL_FUTURE);
 
     // Open the device to force reread of the partition table.
-    if ((toys.optflags & FLAG_n) || !fork()) {
+    if ((toys.optflags & FLAG_n) || !xfork()) {
       char *s = strrchr(device, '/');
       int i;
 
diff --git a/toys/pending/openvt.c b/toys/pending/openvt.c
index f136b1b7..be3070e2 100644
--- a/toys/pending/openvt.c
+++ b/toys/pending/openvt.c
@@ -110,9 +110,8 @@ void openvt_main(void)
   while (vt_fd > 2)
     close(vt_fd--);
 
-  pid = vfork();
-  if (pid < 0)  perror_exit("Fork failed");
-  else if (!pid) {
+  pid = xfork();
+  if (!pid) {
     setsid();
     ioctl(vt_fd, TIOCSCTTY, 0);
     xexec(toys.optargs);
diff --git a/toys/pending/tcpsvd.c b/toys/pending/tcpsvd.c
index 031d7238..d7e1f6c1 100644
--- a/toys/pending/tcpsvd.c
+++ b/toys/pending/tcpsvd.c
@@ -14,7 +14,7 @@ config TCPSVD
   default n
   help
     usage: tcpsvd [-hEv] [-c N] [-C N[:MSG]] [-b N] [-u User] [-l Name] IP Port Prog
-    udpsvd [-hEv] [-c N] [-u User] [-l Name] IP Port Prog
+    usage: udpsvd [-hEv] [-c N] [-u User] [-l Name] IP Port Prog
     
     Create TCP/UDP socket, bind to IP:PORT and listen for incoming connection. 
     Run PROG for each connection.
@@ -350,7 +350,7 @@ void tcpsvd_main(void)
       h[hash].head->count++;
     }
 
-    if (!(pid = fork())) {
+    if (!(pid = xfork())) {
       char *serv = NULL, *clie = NULL;
       char *client = sock_to_address((struct sockaddr*)buf, NI_NUMERICHOST | NI_NUMERICSERV);
       if (toys.optflags & FLAG_h) { //lookup name
@@ -393,11 +393,11 @@ void tcpsvd_main(void)
       dup2(newfd, 0);
       dup2(newfd, 1);
       xexec_optargs(2); //skip IP PORT
-    } else if(pid > 0) {
+    } else {
       insert(&pids, pid, addr);
       xclose(newfd); //close and reopen for next client.
       if (TT.udp) fd = create_bind_sock(toys.optargs[0],
           (struct sockaddr*)&haddr);
-    } else error_msg(" fork failed");
+    }
   } //while(1)
 }
diff --git a/toys/pending/useradd.c b/toys/pending/useradd.c
index 450e021a..99e2530f 100644
--- a/toys/pending/useradd.c
+++ b/toys/pending/useradd.c
@@ -58,12 +58,12 @@ static char* get_shell(void)
 static int exec_wait(char **args)
 {
   int status = 0;
-  pid_t pid = fork();
+  pid_t pid = xfork();
 
   if (!pid) xexec(args);
-  else if (pid > 0) waitpid(pid, &status, 0);
-  else perror_exit("fork failed");
-  return WEXITSTATUS(status);
+  else if waitpid(pid, &status, 0);
+
+  return WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127;
 }
 
 /* create_copy_skel(), This function will create the home directory of the
diff --git a/toys/posix/time.c b/toys/posix/time.c
index 2648cd1c..01592052 100644
--- a/toys/posix/time.c
+++ b/toys/posix/time.c
@@ -27,7 +27,7 @@ void time_main(void)
   struct timeval tv, tv2;
 
   gettimeofday(&tv, NULL);
-  if (!(pid = fork())) xexec_optargs(0);
+  if (!(pid = xfork())) xexec_optargs(0);
   else {
     int stat;
     struct rusage ru;
diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c
index b024789f..cde71f61 100644
--- a/toys/posix/xargs.c
+++ b/toys/posix/xargs.c
@@ -166,14 +166,14 @@ void xargs_main(void)
     for (dtemp = dlist; dtemp; dtemp = dtemp->next)
       handle_entries(dtemp->data, out+entries);
 
-    pid_t pid=fork();
+    pid_t pid=xfork();
     if (!pid) {
       xclose(0);
       open("/dev/null", O_RDONLY);
       xexec(out);
     }
     waitpid(pid, &status, 0);
-    status = WEXITSTATUS(status);
+    status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127;
 
     // Abritrary number of execs, can't just leak memory each time...
     while (dlist) {
-- 
cgit v1.2.3