From owner-svn-src-all@FreeBSD.ORG Sun Dec 5 22:37:01 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DF8CE106566B; Sun, 5 Dec 2010 22:37:01 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CE3D48FC18; Sun, 5 Dec 2010 22:37:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oB5Mb1sE011315; Sun, 5 Dec 2010 22:37:01 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oB5Mb18x011313; Sun, 5 Dec 2010 22:37:01 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201012052237.oB5Mb18x011313@svn.freebsd.org> From: Jilles Tjoelker Date: Sun, 5 Dec 2010 22:37:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216217 - head/bin/sh X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Dec 2010 22:37:02 -0000 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; }