summaryrefslogtreecommitdiffstats
path: root/bin/sh/jobs.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh/jobs.c')
-rw-r--r--bin/sh/jobs.c197
1 files changed, 122 insertions, 75 deletions
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 8722f67..de813c2 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,19 +295,33 @@ 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;
- pid_t ppid;
char c;
procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
@@ -321,16 +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) {
- ppid = (mode == SHOWJOBS_PIDS) ? ps->pid :
- getpgid(ps->pid);
- out1fmt("%d\n", (int)ppid);
+ 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 = '+';
@@ -349,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;
}
@@ -413,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.
@@ -769,7 +790,7 @@ forkshell(struct job *jp, union node *n, int mode)
TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
mode));
INTOFF;
- if (mode == FORK_BG)
+ if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
checkzombies();
flushall();
pid = fork();
@@ -961,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));
@@ -983,7 +1004,7 @@ dowait(int block, struct job *job)
INTOFF;
thisjob = NULL;
for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
- if (jp->used) {
+ if (jp->used && jp->nprocs > 0) {
done = 1;
stopped = 1;
for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
@@ -1020,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;
}
@@ -1300,13 +1314,46 @@ cmdputs(const char *s)
if (--cmdnleft > 0)
*q++ = '{';
subtype = *p++;
+ if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0)
+ *q++ = '#';
} else if (c == '=' && subtype != 0) {
- *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
+ *q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL];
+ if (*q)
+ q++;
+ else
+ cmdnleft++;
+ if (((subtype & VSTYPE) == VSTRIMLEFTMAX ||
+ (subtype & VSTYPE) == VSTRIMRIGHTMAX) &&
+ --cmdnleft > 0)
+ *q = q[-1], q++;
subtype = 0;
} else if (c == CTLENDVAR) {
*q++ = '}';
- } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
- cmdnleft++; /* ignore it */
+ } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) {
+ cmdnleft -= 5;
+ if (cmdnleft > 0) {
+ *q++ = '$';
+ *q++ = '(';
+ *q++ = '.';
+ *q++ = '.';
+ *q++ = '.';
+ *q++ = ')';
+ }
+ } else if (c == CTLARI) {
+ cmdnleft -= 2;
+ if (cmdnleft > 0) {
+ *q++ = '$';
+ *q++ = '(';
+ *q++ = '(';
+ }
+ p++;
+ } else if (c == CTLENDARI) {
+ if (--cmdnleft > 0) {
+ *q++ = ')';
+ *q++ = ')';
+ }
+ } else if (c == CTLQUOTEMARK || c == CTLQUOTEEND)
+ cmdnleft++; /* ignore */
else
*q++ = c;
if (--cmdnleft <= 0) {
OpenPOWER on IntegriCloud