summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/builtins.yo13
-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
7 files changed, 172 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 13d4c5731..9b69e96ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-22 Peter Stephenson <pws@csr.com>
+
+ * 20572: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c,
+ Src/jobs.c, Src/signals.c, Src/utils.c: Allow -CLD and -IO
+ as alternatives to -CHLD and -POLL where they are the same signal.
+
2004-11-20 Doug Kearns <djkea2@mugca.its.monash.edu.au>
* 20571: Completion/Unix/Command/_java: update javac completion for
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 51802f1d6..a1e9df79a 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -626,6 +626,14 @@ var(sig) that is a name, the corresponding signal number is
listed. For each var(sig) that is a signal number or a number
representing the exit status of a process which was terminated or
stopped by a signal the name of the signal is printed.
+
+On some systems, alternative signal names are allowed for a few signals.
+Typical examples are tt(SIGCHLD) and tt(SIGCLD) or tt(SIGPOLL) and
+tt(SIGIO), assuming they correspond to the same signal number. tt(kill
+-l) will only list the preferred form, however tt(kill -l) var(alt) will
+show if the alternative form corresponds to a signal number. For example,
+under Linux tt(kill -l IO) and tt(kill -l POLL) both output 29, hence
+tt(kill -IO) and tt(kill -POLL) have the same effect.
)
findex(let)
item(tt(let) var(arg) ...)(
@@ -1179,6 +1187,11 @@ will print the line number of a command executed after it has run, while
example(TRAPDEBUG() { print $LINENO; })
will always print the number zero.
+
+Alternative signal names are allowed as described under tt(kill) above.
+Defining a trap under either name causes any trap under an alternative
+name to be removed. However, it is recommended that for consistency
+users stick exclusively to one name or another.
)
findex(true)
cindex(doing nothing, successfully)
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 *