diff options
Diffstat (limited to 'Src/jobs.c')
-rw-r--r-- | Src/jobs.c | 206 |
1 files changed, 178 insertions, 28 deletions
diff --git a/Src/jobs.c b/Src/jobs.c index 4863962b9..07facc60b 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -427,11 +427,17 @@ storepipestats(Job jn, int inforeground, int fixlastval) } if (fixlastval) { - if (jn->stat & STAT_CURSH) { - if (!lastval && isset(PIPEFAIL)) - lastval = pipefail; - } else if (isset(PIPEFAIL)) - lastval = pipefail; + if (jn->stat & STAT_CURSH) { + if (!lastval && isset(PIPEFAIL)) { + if (inforeground) + this_noerrexit = 0; + lastval = pipefail; + } + } else if (isset(PIPEFAIL)) { + if (inforeground) + this_noerrexit = 0; + lastval = pipefail; + } } } @@ -654,6 +660,25 @@ update_job(Job jn) } } +/**/ +void +update_bg_job(Job jn, pid_t pid, int status) +{ + /* + * Accumulate a list of older jobs. We only do this for + * background jobs, which is something in the job table + * that's not marked as in the current shell or as shell builtin + * and is not equal to the current foreground job. + */ + if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) && + jn - jobtab != thisjob) { + if (WIFEXITED(status)) + addbgstatus(pid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + addbgstatus(pid, 0200 | WTERMSIG(status)); + } +} + /* set the previous job to something reasonable */ /**/ @@ -888,8 +913,13 @@ printtime(struct timeval *real, child_times_t *ti, char *desc) break; #endif #ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS +#ifdef RU_MAXRSS_IS_IN_BYTES +# define MAXRSS_IN_KB(x) ((x)/1024) +#else +# define MAXRSS_IN_KB(x) (x) +#endif case 'M': - fprintf(stderr, "%ld", ti->ru_maxrss / 1024); + fprintf(stderr, "%ld", MAXRSS_IN_KB(ti->ru_maxrss)); break; #endif #ifdef HAVE_STRUCT_RUSAGE_RU_MAJFLT @@ -1027,7 +1057,7 @@ should_report_time(Job j) return 1; #else { - clktck = get_clktck(); + long clktck = get_clktck(); if ((j->procs->ti.ut + j->procs->ti.st) / clktck >= reporttime) return 1; } @@ -1036,13 +1066,28 @@ should_report_time(Job j) #ifdef HAVE_GETRUSAGE if (reportmemory >= 0 && - j->procs->ti.ru_maxrss / 1024 > reportmemory) + MAXRSS_IN_KB(j->procs->ti.ru_maxrss) > reportmemory) return 1; #endif return 0; } +/**/ +char * +sigmsg(int sig) +{ + static char *unknown = "unknown signal"; +#if defined(SIGRTMIN) && defined(SIGRTMAX) + static char rtmsg[] = "real-time event XXX"; + if (sig >= SIGRTMIN && sig <= SIGRTMAX) { + sprintf(rtmsg + sizeof(rtmsg) - 4, "%u", sig - SIGRTMIN + 1); + return rtmsg; + } +#endif + return sig <= SIGCOUNT ? sig_msg[sig] : unknown; +} + /* !(lng & 3) means jobs * * (lng & 1) means jobs -l * * (lng & 2) means jobs -p @@ -1372,8 +1417,10 @@ cleanfilelists(void) DPUTS(shell_exiting >= 0, "BUG: cleanfilelists() before exit"); - for (i = 1; i <= maxjob; i++) + for (i = 1; i <= maxjob; i++) { deletefilelist(jobtab[i].filelist, 0); + jobtab[i].filelist = 0; + } } /**/ @@ -1531,8 +1578,10 @@ havefiles(void) int i; for (i = 1; i <= maxjob; i++) - if (jobtab[i].stat && jobtab[i].filelist) + if (jobtab[i].stat && jobtab[i].filelist && + peekfirst(jobtab[i].filelist)) { return 1; + } return 0; } @@ -2660,11 +2709,37 @@ static const struct { int bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) { - int sig = SIGTERM; + int status, sig = SIGTERM; int returnval = 0; +#ifdef HAVE_SIGQUEUE + union sigval sigqueue_info; +#endif + int use_sigqueue = 0, got_sig = 0; + + while (*argv && **argv == '-') { + if (!use_sigqueue && (*argv)[1] == 'q' && (*argv)[2] == '\0') { + char *endp; + + if (!*++argv) { + zwarnnam(nam, "-q: argument expected"); + return 1; + } +#ifdef HAVE_SIGQUEUE + sigqueue_info.sival_int = +#endif + zstrtol(*argv, &endp, 10); + if (*endp) { + zwarnnam(nam, "invalid number: %s", *argv); + return 1; + } + use_sigqueue = 1; + argv++; + continue; + } + if (got_sig) + break; /* check for, and interpret, a signal specifier */ - if (*argv && **argv == '-') { if (idigit((*argv)[1])) { char *endp; /* signal specified by number */ @@ -2680,23 +2755,29 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) if ((*argv)[1] == 'l' && (*argv)[2] == '\0') { if (argv[1]) { while (*++argv) { - sig = zstrtol(*argv, &signame, 10); + status = zstrtol(*argv, &signame, 10); if (signame == *argv) { + signame = casemodify(signame, CASMOD_UPPER); if (!strncmp(signame, "SIG", 3)) signame += 3; for (sig = 1; sig <= SIGCOUNT; sig++) - if (!strcasecmp(sigs[sig], signame)) + if (!strcmp(sigs[sig], signame)) break; if (sig > SIGCOUNT) { int i; for (i = 0; alt_sigs[i].name; i++) - if (!strcasecmp(alt_sigs[i].name, signame)) + if (!strcmp(alt_sigs[i].name, signame)) { sig = alt_sigs[i].num; break; } } +#if defined(SIGRTMIN) && defined(SIGRTMAX) + if (sig > SIGCOUNT && (sig = rtsigno(signame))) { + printf("%d\n", sig); + } else +#endif if (sig > SIGCOUNT) { zwarnnam(nam, "unknown signal: SIG%s", signame); @@ -2709,14 +2790,15 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) signame); returnval++; } else { - if (WIFSIGNALED(sig)) - sig = WTERMSIG(sig); - else if (WIFSTOPPED(sig)) - sig = WSTOPSIG(sig); + sig = status & ~0200; if (1 <= sig && sig <= SIGCOUNT) printf("%s\n", sigs[sig]); +#if defined(SIGRTMIN) && defined(SIGRTMAX) + else if ((signame = rtsigname(sig, 0))) + printf("%s\n", signame); +#endif else - printf("%d\n", sig); + printf("%d\n", status); } } } @@ -2725,10 +2807,45 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) printf("%s", sigs[1]); for (sig = 2; sig <= SIGCOUNT; sig++) printf(" %s", sigs[sig]); +#if defined(SIGRTMIN) && defined(SIGRTMAX) + for (sig = SIGRTMIN; sig <= SIGRTMAX; sig++) + printf(" %s", rtsigname(sig, 0)); +#endif putchar('\n'); return 0; } + /* with argument "-L" list signals with their numbers in a table */ + if ((*argv)[1] == 'L' && (*argv)[2] == '\0') { +#if defined(SIGRTMIN) && defined(SIGRTMAX) + const int width = SIGRTMAX >= 100 ? 3 : 2; +#else + const int width = SIGCOUNT >= 100 ? 3 : 2; +#endif + const int cols = zterm_columns >= 30 ? + (zterm_columns < 90 ? zterm_columns / 15 : 6) : 1; + + for (sig = 1; sig < SIGCOUNT +#if defined(SIGRTMIN) && defined(SIGRTMAX) + + 1 +#endif + ; sig++) + { + printf("%*d %-10s%c", width, sig, sigs[sig], + sig % cols ? ' ' : '\n'); + } +#if defined(SIGRTMIN) && defined(SIGRTMAX) + for (sig = SIGRTMIN; sig < SIGRTMAX; sig++) { + printf("%*d %-10s%c", width, sig, rtsigname(sig, 0), + (sig - SIGRTMIN + SIGCOUNT + 1) % cols ? ' ' : '\n'); + } + printf("%*d RTMAX\n", width, sig); +#else + printf("%*d %s\n", width, sig, sigs[sig]); +#endif + return 0; + } + if ((*argv)[1] == 'n' && (*argv)[2] == '\0') { char *endp; @@ -2773,14 +2890,19 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) break; } } - if (sig > SIGCOUNT) { + if (sig > SIGCOUNT +#if defined(SIGRTMIN) && defined(SIGRTMAX) + && !(sig = rtsigno(signame)) +#endif + ) { zwarnnam(nam, "unknown signal: SIG%s", signame); - zwarnnam(nam, "type kill -l for a list of signals"); + zwarnnam(nam, "type kill -L for a list of signals"); return 1; } } } argv++; + got_sig = 1; } /* Discard the standard "-" and "--" option breaks */ @@ -2829,7 +2951,12 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) returnval++; } else { int pid = atoi(*argv); - if (kill(pid, sig) == -1) { + if ( +#ifdef HAVE_SIGQUEUE + use_sigqueue ? sigqueue(pid, sig, sigqueue_info) : +#endif + kill(pid, sig) == -1) + { zwarnnam("kill", "kill %s failed: %e", *argv, errno); returnval++; } @@ -2850,18 +2977,19 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) return returnval < 126 ? returnval : 1; } -/* Get a signal number from a string */ + +/* Get index into table of traps from a string describing a signal */ /**/ mod_export int -getsignum(const char *s) +getsigidx(const char *s) { int x, i; /* check for a signal specified by number */ x = atoi(s); - if (idigit(*s) && x >= 0 && x < VSIGCOUNT) - return x; + if (idigit(*s) && x >= 0) + return SIGIDX(x); /* search for signal by name */ if (!strncmp(s, "SIG", 3)) @@ -2877,11 +3005,16 @@ getsignum(const char *s) return alt_sigs[i].num; } +#if defined(SIGRTMIN) && defined(SIGRTMAX) + if ((x = rtsigno(s))) + return SIGIDX(x); +#endif + /* no matching signal */ return -1; } -/* Get the name for a signal. */ +/* Get the name for a signal given the index into the traps table. */ /**/ mod_export const char * @@ -2895,6 +3028,11 @@ getsigname(int sig) return alt_sigs[i].name; } else +#if defined(SIGRTMIN) && defined(SIGRTMAX) + if (sig >= VSIGCOUNT) + return rtsigname(SIGNUM(sig), 0); + else +#endif return sigs[sig]; /* shouldn't reach here */ @@ -2919,10 +3057,22 @@ gettrapnode(int sig, int ignoredisable) else getptr = shfunctab->getnode; +#if defined(SIGRTMIN) && defined(SIGRTMAX) + if (sig >= VSIGCOUNT) + sprintf(fname, "TRAP%s", rtsigname(SIGNUM(sig), 0)); + else +#endif sprintf(fname, "TRAP%s", sigs[sig]); if ((hn = getptr(shfunctab, fname))) return hn; +#if defined(SIGRTMIN) && defined(SIGRTMAX) + if (sig >= VSIGCOUNT) { + sprintf(fname, "TRAP%s", rtsigname(SIGNUM(sig), 1)); + return getptr(shfunctab, fname); + } +#endif + for (i = 0; alt_sigs[i].name; i++) { if (alt_sigs[i].num == sig) { sprintf(fname, "TRAP%s", alt_sigs[i].name); |