summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-12-05 22:37:01 +0000
committerjilles <jilles@FreeBSD.org>2010-12-05 22:37:01 +0000
commit91e61ea9fc5a14b27d49a05b90e2732126f1a86c (patch)
tree942fe6307fc75d604dc9090824c2f42dde8ccda9 /bin
parent8186346ebb40a05ee911488b3b48056f2d9e69b0 (diff)
downloadFreeBSD-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.c149
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;
}
OpenPOWER on IntegriCloud