Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 May 1997 22:55:26 -0700 (PDT)
From:      dholland@eecs.harvard.edu
To:        freebsd-gnats-submit@FreeBSD.ORG
Subject:   bin/3668: /bin/sh knows too much about wait()
Message-ID:  <199705230555.WAA02625@hub.freebsd.org>
Resent-Message-ID: <199705230600.XAA02744@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         3668
>Category:       bin
>Synopsis:       /bin/sh knows too much about wait()
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 22 23:00:01 PDT 1997
>Last-Modified:
>Originator:     David A. Holland
>Organization:
VINO, Harvard University
>Release:        see below
>Environment:
N/A
>Description:
sh knows too much about the bit fields returned by wait(), instead of
using the WIF... macros in <sys/wait.h>. This means if you change the
bit fields (eg to support >256 signals), sh breaks in strange ways.

This problem was found in netbsd's sh but apparently applies to freebsd
too, so I'm sending the patch along.
>How-To-Repeat:
n/a
>Fix:
If this patch has been garbaged by netscape or other web stuff please
mail me for a fixed copy. :-/

also please note that the patch is in fact against netbsd and I haven't
tried applying it to freebsd's sh. 

Index: jobs.c
===================================================================
RCS file: /home/vino/repo/src/utils/bsd/bin/sh/jobs.c,v
retrieving revision 1.1.1.1
diff -u -3 -r1.1.1.1 jobs.c
--- jobs.c      1997/04/10 18:32:45     1.1.1.1
+++ jobs.c      1997/05/22 22:07:22
@@ -241,7 +241,7 @@
        INTOFF;
        killpg(jp->ps[0].pid, SIGCONT);
        for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
-               if ((ps->status & 0377) == 0177) {
+               if (WIFSTOPPED(ps->status)) {
                        ps->status = -1;
                        jp->state = 0;
                }
@@ -304,19 +304,21 @@
                        if (ps->status == -1) {
                                /* don't print anything */
-                       } else if ((ps->status & 0xFF) == 0) {
-                               fmtstr(s, 64, "Exit %d", ps->status >> 8);
+                       } else if (WIFEXITED(ps->status)) {
+                               fmtstr(s, 64, "Exit %d", 
+                                      WEXITSTATUS(ps->status));
                        } else {
-                               i = ps->status;
 #if JOBS
-                               if ((i & 0xFF) == 0177)
-                                       i >>= 8;
+                               if (WIFSTOPPED(ps->status)) 
+                                       i = WSTOPSIG(ps->status);
+                               else /* WIFSIGNALED(ps->status) */
 #endif
+                                       i = WTERMSIG(ps->status);
                                if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
                                        scopy(sys_siglist[i & 0x7F], s);
                                else
                                        fmtstr(s, 64, "Signal %d", i & 0x7F);
-                               if (i & 0x80)
+                               if (WCOREDUMP(ps->status))
                                        strcat(s, " (core dumped)");
                        }
                        out1str(s);
@@ -372,7 +374,7 @@
        char **argv;
 {
        struct job *job;
-       int status;
+       int status, retval;
        struct job *jp;
 
        if (argc > 1) {
@@ -384,17 +386,19 @@
                if (job != NULL) {
                        if (job->state) {
                                status = job->ps[job->nprocs - 1].status;
-                               if ((status & 0xFF) == 0)
-                                       status = status >> 8 & 0xFF;
+                               if (WIFEXITED(status))
+                                       retval = WEXITSTATUS(status);
 #if JOBS
-                               else if ((status & 0xFF) == 0177)
-                                       status = (status >> 8 & 0x7F) + 128;
+                               else if (WIFSTOPPED(status))
+                                       retval = WSTOPSIG(status) + 128;
 #endif
-                               else
-                                       status = (status & 0x7F) + 128;
+                               else {
+                                       /* XXX */
+                                       retval = WTERMSIG(status) + 128;
+                               }
                                if (! iflag)
                                        freejob(job);
-                               return status;
+                               return retval;
                        }
                } else {
                        for (jp = jobtab ; ; jp++) {
@@ -713,18 +717,18 @@
 #endif
        status = jp->ps[jp->nprocs - 1].status;
        /* convert to 8 bits */
-       if ((status & 0xFF) == 0)
-               st = status >> 8 & 0xFF;
+       if (WIFEXITED(status))
+               st = WEXITSTATUS(status);
 #if JOBS
-       else if ((status & 0xFF) == 0177)
-               st = (status >> 8 & 0x7F) + 128;
+       else if (WIFSTOPPED(status))
+               st = WSTOPSIG(status) + 128;
 #endif
        else
-               st = (status & 0x7F) + 128;
+               st = WTERMSIG(status) + 128;
        if (! JOBS || jp->state == JOBDONE)
                freejob(jp);
        CLEAR_PENDING_INT;
-       if ((status & 0x7F) == SIGINT)
+       if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
                kill(getpid(), SIGINT);
        INTON;
        return st;
@@ -749,6 +753,7 @@
        int done;
        int stopped;
        int core;
+       int sig;
 
        TRACE(("dowait(%d) called\n", block));
        do {
@@ -767,13 +772,13 @@
                                if (sp->pid == -1)
                                        continue;
                                if (sp->pid == pid) {
-                                       TRACE(("Changin status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
+                                       TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
                                        sp->status = status;
                                        thisjob = jp;
                                }
                                if (sp->status == -1)
                                        stopped = 0;
-                               else if ((sp->status & 0377) == 0177)
+                               else if (WIFSTOPPED(sp->status))
                                        done = 0;
                        }
                        if (stopped) {          /* stopped or done */
@@ -791,29 +796,32 @@
        }
        INTON;
        if (! rootshell || ! iflag || (job && thisjob == job)) {
+               core = WCOREDUMP(status);
 #if JOBS
-               if ((status & 0xFF) == 0177)
-                       status >>= 8;
+               if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
+               else
 #endif
-               core = status & 0x80;
-               status &= 0x7F;
-               if (status != 0 && status != SIGINT && status != SIGPIPE) {
+               if (WIFEXITED(status)) sig = 0;
+               else sig = WTERMSIG(status);
+
+               if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
                        if (thisjob != job)
                                outfmt(out2, "%d: ", pid);
 #if JOBS
-                       if (status == SIGTSTP && rootshell && iflag)
+                       if (sig == SIGTSTP && rootshell && iflag)
                                outfmt(out2, "%%%d ", job - jobtab + 1);
 #endif
-                       if (status < NSIG && sys_siglist[status])
-                               out2str(sys_siglist[status]);
+                       if (sig < NSIG && sys_siglist[sig])
+                               out2str(sys_siglist[sig]);
                        else
-                               outfmt(out2, "Signal %d", status);
+                               outfmt(out2, "Signal %d", sig);
                        if (core)
                                out2str(" - core dumped");
                        out2c('\n');
                        flushout(&errout);
                } else {
-                       TRACE(("Not printing status: status=%d\n", status));
+                       TRACE(("Not printing status: status=%d, sig=%d\n", 
+                              status, sig));
                }
        } else {
                TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705230555.WAA02625>