diff options
author | jilles <jilles@FreeBSD.org> | 2010-12-05 22:37:01 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2010-12-05 22:37:01 +0000 |
commit | 91e61ea9fc5a14b27d49a05b90e2732126f1a86c (patch) | |
tree | 942fe6307fc75d604dc9090824c2f42dde8ccda9 /bin | |
parent | 8186346ebb40a05ee911488b3b48056f2d9e69b0 (diff) | |
download | FreeBSD-src-91e61ea9fc5a14b27d49a05b90e2732126f1a86c.zip FreeBSD-src-91e61ea9fc5a14b27d49a05b90e2732126f1a86c.tar.gz |
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").
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/jobs.c | 149 |
1 files changed, 83 insertions, 66 deletions
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 994c064..60f9795 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -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 mode) 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 mode) 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; } |