Author: jilles
Date: Sun Dec  5 22:37:01 2010
New Revision: 216217
URL: http://svn.freebsd.org/changeset/base/216217

Log:
  sh: Improve jobs output of pipelines.
  
  If describing the status of a pipeline, write all elements of the pipeline
  and show the status of the last process (which would also end up in $?).
  Only write one report per job, not one for every process that exits.
  
  To keep some earlier behaviour, if any process started by the shell in a
  foreground job terminates because of a signal, write a message about the
  signal (at most one message per job, however).
  
  Also, do not write messages about signals in the wait builtin in
  non-interactive shells. Only true foreground jobs now write such messages
  (for example, "Terminated").

Modified:
  head/bin/sh/jobs.c

Modified: head/bin/sh/jobs.c
==============================================================================
--- head/bin/sh/jobs.c  Sun Dec  5 22:24:34 2010        (r216216)
+++ head/bin/sh/jobs.c  Sun Dec  5 22:37:01 2010        (r216217)
@@ -100,7 +100,8 @@ static void setcurjob(struct job *);
 static void deljob(struct job *);
 static struct job *getcurjob(struct job *);
 #endif
-static void showjob(struct job *, pid_t, int);
+static void printjobcmd(struct job *);
+static void showjob(struct job *, int);
 
 
 /*
@@ -205,8 +206,7 @@ fgcmd(int argc __unused, char **argv)
        jp = getjob(argv[1]);
        if (jp->jobctl == 0)
                error("job not created under job control");
-       out1str(jp->ps[0].cmd);
-       out1c('\n');
+       printjobcmd(jp);
        flushout(&output);
        pgrp = jp->ps[0].pid;
        tcsetpgrp(ttyfd, pgrp);
@@ -235,8 +235,7 @@ bgcmd(int argc, char **argv)
                jp->foreground = 0;
                fmtstr(s, 64, "[%td] ", jp - jobtab + 1);
                out1str(s);
-               out1str(jp->ps[0].cmd);
-               out1c('\n');
+               printjobcmd(jp);
        } while (--argc > 1);
        return 0;
 }
@@ -296,15 +295,30 @@ jobscmd(int argc, char *argv[])
                showjobs(0, mode);
        else
                while ((id = *argv++) != NULL)
-                       showjob(getjob(id), 0, mode);
+                       showjob(getjob(id), mode);
 
        return (0);
 }
 
 static void
-showjob(struct job *jp, pid_t pid, int mode)
+printjobcmd(struct job *jp)
+{
+       struct procstat *ps;
+       int i;
+
+       for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
+               out1str(ps->cmd);
+               if (i > 0)
+                       out1str(" | ");
+       }
+       out1c('\n');
+}
+
+static void
+showjob(struct job *jp, int mode)
 {
        char s[64];
+       char statestr[64];
        struct procstat *ps;
        struct job *j;
        int col, curr, i, jobno, prev, procno;
@@ -320,14 +334,44 @@ showjob(struct job *jp, pid_t pid, int m
                        prev = j - jobtab + 1;
        }
 #endif
+       ps = jp->ps + jp->nprocs - 1;
+       if (jp->state == 0) {
+               strcpy(statestr, "Running");
+#if JOBS
+       } else if (jp->state == JOBSTOPPED) {
+               while (!WIFSTOPPED(ps->status) && ps > jp->ps)
+                       ps--;
+               if (WIFSTOPPED(ps->status))
+                       i = WSTOPSIG(ps->status);
+               else
+                       i = -1;
+               if (i > 0 && i < sys_nsig && sys_siglist[i])
+                       strcpy(statestr, sys_siglist[i]);
+               else
+                       strcpy(statestr, "Suspended");
+#endif
+       } else if (WIFEXITED(ps->status)) {
+               if (WEXITSTATUS(ps->status) == 0)
+                       strcpy(statestr, "Done");
+               else
+                       fmtstr(statestr, 64, "Done (%d)",
+                           WEXITSTATUS(ps->status));
+       } else {
+               i = WTERMSIG(ps->status);
+               if (i > 0 && i < sys_nsig && sys_siglist[i])
+                       strcpy(statestr, sys_siglist[i]);
+               else
+                       fmtstr(statestr, 64, "Signal %d", i);
+               if (WCOREDUMP(ps->status))
+                       strcat(statestr, " (core dumped)");
+       }
+
        for (ps = jp->ps ; ; ps++) {    /* for each process */
                if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
                        out1fmt("%d\n", (int)ps->pid);
                        goto skip;
                }
-               if (mode != SHOWJOBS_VERBOSE && ps != jp->ps && pid == 0)
-                       goto skip;
-               if (pid != 0 && pid != ps->pid)
+               if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
                        goto skip;
                if (jobno == curr && ps == jp->ps)
                        c = '+';
@@ -346,39 +390,19 @@ showjob(struct job *jp, pid_t pid, int m
                        out1str(s);
                        col += strlen(s);
                }
-               s[0] = '\0';
-               if (ps != jp->ps) {
-                       *s = '\0';
-               } else if (ps->status == -1) {
-                       strcpy(s, "Running");
-               } else if (WIFEXITED(ps->status)) {
-                       if (WEXITSTATUS(ps->status) == 0)
-                               strcpy(s, "Done");
-                       else
-                               fmtstr(s, 64, "Done (%d)",
-                                   WEXITSTATUS(ps->status));
-               } else {
-#if JOBS
-                       if (WIFSTOPPED(ps->status))
-                               i = WSTOPSIG(ps->status);
-                       else
-#endif
-                               i = WTERMSIG(ps->status);
-                       if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
-                               scopy(sys_siglist[i & 0x7F], s);
-                       else
-                               fmtstr(s, 64, "Signal %d", i & 0x7F);
-                       if (WCOREDUMP(ps->status))
-                               strcat(s, " (core dumped)");
+               if (ps == jp->ps) {
+                       out1str(statestr);
+                       col += strlen(statestr);
                }
-               out1str(s);
-               col += strlen(s);
                do {
                        out1c(' ');
                        col++;
                } while (col < 30);
-               out1str(ps->cmd);
-               out1c('\n');
+               if (mode == SHOWJOBS_VERBOSE) {
+                       out1str(ps->cmd);
+                       out1c('\n');
+               } else
+                       printjobcmd(jp);
 skip:          if (--procno <= 0)
                        break;
        }
@@ -410,7 +434,7 @@ showjobs(int change, int mode)
                }
                if (change && ! jp->changed)
                        continue;
-               showjob(jp, 0, mode);
+               showjob(jp, mode);
                jp->changed = 0;
                /* Hack: discard jobs for which $! has not been referenced
                 * in interactive mode when they terminate.
@@ -958,7 +982,7 @@ dowait(int block, struct job *job)
        int done;
        int stopped;
        int sig;
-       int i;
+       int coredump;
 
        in_dowait++;
        TRACE(("dowait(%d) called\n", block));
@@ -1017,36 +1041,29 @@ dowait(int block, struct job *job)
                }
        }
        INTON;
-       if (! rootshell || ! iflag || (job && thisjob == job)) {
-#if JOBS
-               if (WIFSTOPPED(status))
-                       sig = WSTOPSIG(status);
-               else
-#endif
-               {
-                       if (WIFEXITED(status))
-                               sig = 0;
+       if (!thisjob || thisjob->state == 0)
+               ;
+       else if ((!rootshell || !iflag || thisjob == job) &&
+           thisjob->foreground && thisjob->state != JOBSTOPPED) {
+               sig = 0;
+               coredump = 0;
+               for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
+                       if (WIFSIGNALED(sp->status)) {
+                               sig = WTERMSIG(sp->status);
+                               coredump = WCOREDUMP(sp->status);
+                       }
+               if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
+                       if (sig < sys_nsig && sys_siglist[sig])
+                               out1str(sys_siglist[sig]);
                        else
-                               sig = WTERMSIG(status);
-               }
-               if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
-                       if (!mflag ||
-                           (thisjob->foreground && !WIFSTOPPED(status))) {
-                               i = WTERMSIG(status);
-                               if ((i & 0x7F) < sys_nsig && sys_siglist[i & 
0x7F])
-                                       out1str(sys_siglist[i & 0x7F]);
-                               else
-                                       out1fmt("Signal %d", i & 0x7F);
-                               if (WCOREDUMP(status))
-                                       out1str(" (core dumped)");
-                               out1c('\n');
-                       } else
-                               showjob(thisjob, pid, SHOWJOBS_DEFAULT);
+                               out1fmt("Signal %d", sig);
+                       if (coredump)
+                               out1str(" (core dumped)");
+                       out1c('\n');
                }
        } else {
                TRACE(("Not printing status, rootshell=%d, job=%p\n", 
rootshell, job));
-               if (thisjob)
-                       thisjob->changed = 1;
+               thisjob->changed = 1;
        }
        return pid;
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to