chip@ateng.ateng.com (Chip Salzenberg) (01/23/90)
As distributed, Bash 1.04 includes a SysV emulation of the BSD "union wait". This emulation is slightly broken. It is also unnecessarily complex and non-portable. This patch fixes the bugs and implements the wait() call in a way that should be portable even to BSD. (After all, "union wait" is an optional sugar-coating on the raw V7 semantics of wait().) Index: jobs.h *************** *** 6,73 **** #include <sys/wait.h> #else - - #if defined (i386) || defined (ATT3B) || defined (ATT386) - - union wait { - struct { - unsigned char low; - unsigned char high; - } - bytes; - short word; - }; - - #define WSTOPPED 0177 - #define w_status word - #define w_termsig bytes.low & 0x7f - #define w_stopsig bytes.high - #define w_retcode bytes.high - #define w_coredump w_termsig & ~0x7f - #define WIFEXITED(wstat) ((wstat).bytes.low == 0) - #define WIFSTOPPED(wstat) ((wstat).bytes.low == 0177) - #define WIFTERMINATED(wstat) ((wstat).bytes.high == 0) - - #else /* i386 || ATT3B || ATT386 */ - - #ifdef NO_WAIT_H union wait { ! int w_status; /* used in syscall */ ! ! /* Terminated process status. */ ! struct ! { ! unsigned short ! w_Fill1 : 16, /* high 16 bits unused */ ! w_Retcode : 8, /* exit code if w_termsig==0 */ ! w_Coredump : 1, /* core dump indicator */ ! w_Termsig : 7; /* termination signal */ ! } w_T; ! ! /* Stopped process status. Returned ! only for traced children unless requested ! with the WUNTRACED option bit. */ ! struct ! { ! unsigned short ! w_Fill2 : 16, /* high 16 bits unused */ ! w_Stopsig : 8, /* signal that stopped us */ ! w_Stopval : 8; /* == W_STOPPED if stopped */ ! } w_S; }; - - #define w_termsig w_T.w_Termsig - #define w_coredump w_T.w_Coredump - #define w_retcode w_T.w_Retcode - #define w_stopval w_S.w_Stopval - #define w_stopsig w_S.w_Stopsig - - #define WSTOPPED 0177 - #define WIFSTOPPED(x) (((x) . w_stopval) == WSTOPPED) - #define WIFEXITED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) == 0)) - #define WIFSIGNALED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) != 0)) - - #endif /* HPUX */ - #endif /* i386 || ATT3B || ATT386 */ #endif /* !defined (SYSV) || defined (UNIXPC) */ --- 6,13 ---- #include <sys/wait.h> #else union wait { ! int w_status; }; #endif /* !defined (SYSV) || defined (UNIXPC) */ Index: nojobs.c *************** *** 150,154 **** int pid; { ! int got_pid, return_val, oldmask; union wait status; #ifndef SYSV --- 150,154 ---- int pid; { ! int got_pid, retcode, coredump, termsig, return_val, oldmask; union wait status; #ifndef SYSV *************** *** 162,170 **** #endif ! while ((got_pid = wait (&status)) != pid) { if (got_pid < 0 && errno == ECHILD) { ! status.w_termsig = status.w_retcode = 0; break; } --- 162,170 ---- #endif ! while ((got_pid = wait (&status.w_status)) != pid) { if (got_pid < 0 && errno == ECHILD) { ! status.w_status = 0; break; } *************** *** 181,194 **** /* Default return value. */ ! return_val = status.w_retcode & 0x7f; ! if (status.w_termsig != 0 && status.w_termsig != WSTOPPED) { extern char *sys_siglist[]; ! fprintf (stderr, "%s", sys_siglist[status.w_termsig]); ! if (status.w_coredump) fprintf (stderr, " (core dumped)"); fprintf (stderr, "\n"); ! return_val = status.w_termsig + 128; get_tty_state (); } --- 181,208 ---- /* Default return value. */ ! #ifdef WSTOPPED ! retcode = status.w_retcode; ! coredump = status.w_coredump ! termsig = status.w_termsig; ! #else ! retcode = (status.w_status >> 8) & 0xff; ! coredump = (status.w_status & 0x80) ? 1 : 0; ! termsig = status.w_status & 0x7f; ! #endif ! return_val = retcode & 0x7f; ! ! if (termsig ! #ifdef WSTOPPED ! && termsig != WSTOPPED ! #endif ! ) { extern char *sys_siglist[]; ! fprintf (stderr, "%s", sys_siglist[termsig]); ! if (coredump) fprintf (stderr, " (core dumped)"); fprintf (stderr, "\n"); ! return_val = termsig + 128; get_tty_state (); }