summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/builtin.c18
-rw-r--r--Src/exec.c6
-rw-r--r--Src/jobs.c129
-rw-r--r--Src/signals.c15
-rw-r--r--Src/utils.c21
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 *