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").
This commit is contained in:
Jilles Tjoelker 2010-12-05 22:37:01 +00:00
parent dc5e1d528e
commit 1bb49f9524
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216217

View File

@ -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;
}