diff options
Diffstat (limited to 'Src/jobs.c')
-rw-r--r-- | Src/jobs.c | 91 |
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 |