summaryrefslogtreecommitdiff
path: root/Src/jobs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/jobs.c')
-rw-r--r--Src/jobs.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/Src/jobs.c b/Src/jobs.c
index e7438251e..af0a1233d 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -98,10 +98,12 @@ mod_export int jobtabsize;
mod_export int maxjob;
/* If we have entered a subshell, the original shell's job table. */
-static struct job *oldjobtab;
+/**/
+mod_export struct job *oldjobtab;
/* The size of that. */
-static int oldmaxjob;
+/**/
+mod_export int oldmaxjob;
/* shell timings */
@@ -283,7 +285,8 @@ handle_sub(int job, int fg)
if ((cp = ((WIFEXITED(jn->procs->status) ||
WIFSIGNALED(jn->procs->status)) &&
- killpg(jn->gleader, 0) == -1))) {
+ (killpg(jn->gleader, 0) == -1 &&
+ errno == ESRCH)))) {
Process p;
for (p = jn->procs; p->next; p = p->next);
jn->gleader = p->pid;
@@ -441,7 +444,7 @@ update_job(Job jn)
Process pn;
int job;
int val = 0, status = 0;
- int somestopped = 0, inforeground = 0;
+ int somestopped = 0, inforeground = 0, signalled = 0;
for (pn = jn->auxprocs; pn; pn = pn->next) {
#ifdef WIFCONTINUED
@@ -463,12 +466,15 @@ update_job(Job jn)
return; /* so no need to update job table entry */
if (WIFSTOPPED(pn->status)) /* some processes are stopped */
somestopped = 1; /* so job is not done, but entry needs updating */
- if (!pn->next) /* last job in pipeline determines exit status */
+ if (!pn->next) {
+ /* last job in pipeline determines exit status */
val = (WIFSIGNALED(pn->status) ?
0200 | WTERMSIG(pn->status) :
(WIFSTOPPED(pn->status) ?
0200 | WEXITSTATUS(pn->status) :
WEXITSTATUS(pn->status)));
+ signalled = WIFSIGNALED(pn->status);
+ }
if (pn->pid == jn->gleader) /* if this process is process group leader */
status = pn->status;
}
@@ -541,9 +547,13 @@ update_job(Job jn)
/* is this job in the foreground of an interactive shell? */
if (mypgrp != pgrp && inforeground &&
- (jn->gleader == pgrp || (pgrp > 1 && kill(-pgrp, 0) == -1))) {
+ (jn->gleader == pgrp ||
+ (pgrp > 1 &&
+ (kill(-pgrp, 0) == -1 && errno == ESRCH)))) {
if (list_pipe) {
- if (somestopped || (pgrp > 1 && kill(-pgrp, 0) == -1)) {
+ if (somestopped || (pgrp > 1 &&
+ kill(-pgrp, 0) == -1 &&
+ errno == ESRCH)) {
attachtty(mypgrp);
/* check window size and adjust if necessary */
adjustwinsize(0);
@@ -559,7 +569,7 @@ update_job(Job jn)
}
/* If we have `foo|while true; (( x++ )); done', and hit
* ^C, we have to stop the loop, too. */
- if ((val & 0200) && inforeground == 1 &&
+ if (signalled && inforeground == 1 &&
((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) {
if (!errbrk_saved) {
errbrk_saved = 1;
@@ -576,7 +586,7 @@ update_job(Job jn)
adjustwinsize(0);
}
}
- } else if (list_pipe && (val & 0200) && inforeground == 1 &&
+ } else if (list_pipe && signalled && inforeground == 1 &&
((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) {
if (!errbrk_saved) {
errbrk_saved = 1;
@@ -1708,8 +1718,15 @@ clearjobtab(int monitor)
/* Don't report any job we're part of */
if (thisjob != -1 && thisjob < oldmaxjob)
memset(oldjobtab+thisjob, 0, sizeof(struct job));
+
+ /* oldmaxjob is now the size of the table, but outside
+ * this function, it's used as a job number, which must
+ * be the largest index available in the table.
+ */
+ --oldmaxjob;
}
+
memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */
maxjob = 0;
@@ -1723,6 +1740,18 @@ clearjobtab(int monitor)
thisjob = initjob();
}
+/* In a subshell, decide we want our own job table after all. */
+
+/**/
+mod_export void
+clearoldjobtab(void)
+{
+ if (oldjobtab)
+ free(oldjobtab);
+ oldjobtab = NULL;
+ oldmaxjob = 0;
+}
+
static int initnewjob(int i)
{
jobtab[i].stat = STAT_INUSE;
@@ -1854,13 +1883,14 @@ scanjobs(void)
/* This simple function indicates whether or not s may represent *
* a number. It returns true iff s consists purely of digits and *
- * minuses. Note that minus may appear more than once, and the empty *
- * string will produce a `true' response. */
+ * minuses. Note that minus may appear more than once. */
/**/
static int
isanum(char *s)
{
+ if (*s == '\0')
+ return 0;
while (*s == '-' || idigit(*s))
s++;
return *s == '\0';
@@ -1885,6 +1915,26 @@ setcurjob(void)
}
}
+/* Find the job table for reporting jobs */
+
+/**/
+mod_export void
+selectjobtab(Job *jtabp, int *jmaxp)
+{
+ if (oldjobtab)
+ {
+ /* In subshell --- use saved job table to report */
+ *jtabp = oldjobtab;
+ *jmaxp = oldmaxjob;
+ }
+ else
+ {
+ /* Use main job table */
+ *jtabp = jobtab;
+ *jmaxp = maxjob;
+ }
+}
+
/* Convert a job specifier ("%%", "%1", "%foo", "%?bar?", etc.) *
* to a job number. */
@@ -1895,13 +1945,7 @@ getjob(const char *s, const char *prog)
int jobnum, returnval, mymaxjob;
Job myjobtab;
- if (oldjobtab) {
- myjobtab = oldjobtab;
- mymaxjob = oldmaxjob;
- } else {
- myjobtab= jobtab;
- mymaxjob = maxjob;
- }
+ selectjobtab(&myjobtab, &mymaxjob);
/* if there is no %, treat as a name */
if (*s != '%')
@@ -2261,6 +2305,13 @@ bin_fg(char *name, char **argv, Options ops, int func)
memcpy(hackzero, *argv, len);
memset(hackzero + len, 0, hackspace - len);
#endif
+
+#ifdef HAVE_PRCTL
+ /* try to change /proc/$$/comm which will *
+ * be used when checking with "ps -e" */
+#include <sys/prctl.h>
+ prctl(PR_SET_NAME, *argv);
+#endif
unqueue_signals();
return 0;
}
@@ -2417,6 +2468,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
case BIN_BG:
case BIN_WAIT:
if (func == BIN_BG) {
+ clearoldjobtab();
jobtab[job].stat |= STAT_NOSTTY;
jobtab[job].stat &= ~STAT_CURSH;
}
@@ -2469,7 +2521,8 @@ bin_fg(char *name, char **argv, Options ops, int func)
if ((jobtab[job].stat & STAT_SUPERJOB) &&
((!jobtab[job].procs->next ||
(jobtab[job].stat & STAT_SUBLEADER) ||
- killpg(jobtab[job].gleader, 0) == -1)) &&
+ (killpg(jobtab[job].gleader, 0) == -1 &&
+ errno == ESRCH))) &&
jobtab[jobtab[job].other].gleader)
attachtty(jobtab[jobtab[job].other].gleader);
else