diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2004-11-22 10:33:03 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2004-11-22 10:33:03 +0000 |
commit | 5141e68daa20caa8523361d5dff63e9384c30191 (patch) | |
tree | 7521410b050a3f152e5dd902c209ff12477bd455 /Src | |
parent | f1846d402bed119a74409c3b417484661e100e27 (diff) | |
download | zsh-5141e68daa20caa8523361d5dff63e9384c30191.tar.gz zsh-5141e68daa20caa8523361d5dff63e9384c30191.tar.xz zsh-5141e68daa20caa8523361d5dff63e9384c30191.zip |
20572: Allow alternative signal names
Diffstat (limited to 'Src')
-rw-r--r-- | Src/builtin.c | 18 | ||||
-rw-r--r-- | Src/exec.c | 6 | ||||
-rw-r--r-- | Src/jobs.c | 129 | ||||
-rw-r--r-- | Src/signals.c | 15 | ||||
-rw-r--r-- | Src/utils.c | 21 |
5 files changed, 153 insertions, 36 deletions
diff --git a/Src/builtin.c b/Src/builtin.c index bc21fa9e2..3a471760a 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2543,7 +2543,16 @@ bin_functions(char *name, char **argv, Options ops, int func) /* no flags, so just print */ shfunctab->printnode((HashNode) shf, pflags); } else if (on & PM_UNDEFINED) { - int signum, ok = 1; + int signum = -1, ok = 1; + + if (!strncmp(*argv, "TRAP", 4) && + (signum = getsignum(*argv + 4)) != -1) { + /* + * Because of the possibility of alternative names, + * we must remove the trap explicitly. + */ + removetrapnode(signum); + } /* Add a new undefined (autoloaded) function to the * * hash table with the corresponding flags set. */ @@ -2552,8 +2561,7 @@ bin_functions(char *name, char **argv, Options ops, int func) shf->funcdef = mkautofn(shf); shfunctab->addnode(shfunctab, ztrdup(*argv), shf); - if (!strncmp(*argv, "TRAP", 4) && - (signum = getsignum(*argv + 4)) != -1) { + if (signum != -1) { if (settrap(signum, shf->funcdef)) { shfunctab->removenode(shfunctab, *argv); shfunctab->freenode((HashNode)shf); @@ -4898,11 +4906,9 @@ bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) queue_signals(); for (sig = 0; sig < VSIGCOUNT; sig++) { if (sigtrapped[sig] & ZSIG_FUNC) { - char fname[20]; HashNode hn; - sprintf(fname, "TRAP%s", sigs[sig]); - if ((hn = shfunctab->getnode(shfunctab, fname))) + if ((hn = gettrapnode(sig, 0))) shfunctab->printnode(hn, 0); DPUTS(!hn, "BUG: I did not find any trap functions!"); } else if (sigtrapped[sig]) { diff --git a/Src/exec.c b/Src/exec.c index c5fac2fc9..49503db0f 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3345,6 +3345,12 @@ execfuncdef(Estate state, UNUSED(int do_exec)) return 1; } sigtrapped[signum] |= ZSIG_FUNC; + + /* + * Remove the old node explicitly in case it has + * an alternative name + */ + removetrapnode(signum); } shfunctab->addnode(shfunctab, ztrdup(s), shf); } diff --git a/Src/jobs.c b/Src/jobs.c index dc5bc10b6..cb9e5422c 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1819,6 +1819,36 @@ bin_fg(char *name, char **argv, Options ops, int func) return retval; } +#if defined(SIGCHLD) && defined(SIGCLD) +#if SIGCHLD == SIGCLD +#define ALT_SIGS 1 +#endif +#endif +#if defined(SIGPOLL) && defined(SIGIO) +#if SIGPOLL == SIGIO +#define ALT_SIGS 1 +#endif +#endif + +#ifdef ALT_SIGS +const struct { + const char *name; + int num; +} alt_sigs[] = { +#if defined(SIGCHLD) && defined(SIGCLD) +#if SIGCHLD == SIGCLD + { "CLD", SIGCLD }, +#endif +#endif +#if defined(SIGPOLL) && defined(SIGIO) +#if SIGPOLL == SIGIO + { "IO", SIGIO }, +#endif +#endif + { NULL, 0 } +}; +#endif + /* kill: send a signal to a process. The process(es) may be specified * * by job specifier (see above) or pid. A signal, defaulting to * * SIGTERM, may be specified by name or number, preceded by a dash. */ @@ -1847,6 +1877,18 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) for (sig = 1; sig <= SIGCOUNT; sig++) if (!cstrpcmp(sigs + sig, &signame)) break; +#ifdef ALT_SIGS + if (sig > SIGCOUNT) { + int i; + + for (i = 0; alt_sigs[i].name; i++) + if (!cstrpcmp(&alt_sigs[i].name, &signame)) + { + sig = alt_sigs[i].num; + break; + } + } +#endif if (sig > SIGCOUNT) { zwarnnam(nam, "unknown signal: SIG%s", signame, 0); @@ -1908,6 +1950,18 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) break; if (*signame == '0' && !signame[1]) sig = 0; +#ifdef ALT_SIGS + if (sig > SIGCOUNT) { + int i; + + for (i = 0; alt_sigs[i].name; i++) + if (!strcmp(alt_sigs[i].name, signame)) + { + sig = alt_sigs[i].num; + break; + } + } +#endif if (sig > SIGCOUNT) { zwarnnam(nam, "unknown signal: SIG%s", signame, 0); zwarnnam(nam, "type kill -l for a List of signals", NULL, 0); @@ -1964,6 +2018,81 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) return returnval < 126 ? returnval : 1; } +/* Get a signal number from a string */ + +/**/ +mod_export int +getsignum(char *s) +{ + int x, i; + + /* check for a signal specified by number */ + x = atoi(s); + if (idigit(*s) && x >= 0 && x < VSIGCOUNT) + return x; + + /* search for signal by name */ + for (i = 0; i < VSIGCOUNT; i++) + if (!strcmp(s, sigs[i])) + return i; + +#ifdef ALT_SIGS + for (i = 0; alt_sigs[i].name; i++) + { + if (!strcmp(s, alt_sigs[i].name)) + return alt_sigs[i].num; + } +#endif + + /* no matching signal */ + return -1; +} + +/* Get the function node for a trap, taking care about alternative names */ +/**/ +HashNode +gettrapnode(int sig, int ignoredisable) +{ + char fname[20]; + HashNode hn; + HashNode (*getptr)(HashTable ht, char *name); +#ifdef ALT_SIGS + int i; +#endif + if (ignoredisable) + getptr = shfunctab->getnode2; + else + getptr = shfunctab->getnode; + + sprintf(fname, "TRAP%s", sigs[sig]); + if ((hn = getptr(shfunctab, fname))) + return hn; + +#ifdef ALT_SIGS + for (i = 0; alt_sigs[i].name; i++) { + if (alt_sigs[i].num == sig) { + sprintf(fname, "TRAP%s", alt_sigs[i].name); + if ((hn = getptr(shfunctab, fname))) + return hn; + } + } +#endif + + return NULL; +} + +/* Remove a TRAP function under any name for the signal */ + +/**/ +void +removetrapnode(int sig) +{ + HashNode hn = gettrapnode(sig, 1); + if (hn) { + shfunctab->removenode(shfunctab, hn->nam); + shfunctab->freenode(hn); + } +} /* Suspend this shell */ diff --git a/Src/signals.c b/Src/signals.c index fd5d47e71..9959d3c31 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -697,10 +697,8 @@ dosavetrap(int sig, int level) * Get the old function: this assumes we haven't added * the new one yet. */ - char func[20]; Shfunc shf, newshf = NULL; - sprintf(func, "TRAP%s", sigs[sig]); - if ((shf = (Shfunc)shfunctab->getnode2(shfunctab, func))) { + if ((shf = (Shfunc)gettrapnode(sig, 1))) { /* Copy the node for saving */ newshf = (Shfunc) zalloc(sizeof(*newshf)); newshf->nam = ztrdup(shf->nam); @@ -837,16 +835,15 @@ removetrap(int sig) * That causes a little inefficiency, but a good deal more reliability. */ if (trapped & ZSIG_FUNC) { - char func[20]; - HashNode node; + HashNode node = gettrapnode(sig, 1); - sprintf(func, "TRAP%s", sigs[sig]); /* * As in dosavetrap(), don't call removeshfuncnode() because * that calls back into unsettrap(); */ sigfuncs[sig] = NULL; - node = removehashnode(shfunctab, func); + if (node) + removehashnode(shfunctab, node->nam); unqueue_signals(); return node; @@ -1010,10 +1007,10 @@ dotrapargs(int sig, int *sigtr, void *sigfn) runhookdef(BEFORETRAPHOOK, NULL); if (*sigtr & ZSIG_FUNC) { int osc = sfcontext; + HashNode hn = gettrapnode(sig, 0); args = znewlinklist(); - name = (char *) zalloc(5 + strlen(sigs[sig])); - sprintf(name, "TRAP%s", sigs[sig]); + name = ztrdup(hn->nam); zaddlinknode(args, name); sprintf(num, "%d", sig); zaddlinknode(args, num); diff --git a/Src/utils.c b/Src/utils.c index 047aa2644..20eef2ac6 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -3969,27 +3969,6 @@ restoredir(struct dirsav *d) return err; } -/* Get a signal number from a string */ - -/**/ -mod_export int -getsignum(char *s) -{ - int x, i; - - /* check for a signal specified by number */ - x = atoi(s); - if (idigit(*s) && x >= 0 && x < VSIGCOUNT) - return x; - - /* search for signal by name */ - for (i = 0; i < VSIGCOUNT; i++) - if (!strcmp(s, sigs[i])) - return i; - - /* no matching signal */ - return -1; -} /* Check whether the shell is running with privileges in effect. * * This is the case if EITHER the euid is zero, OR (if the system * |