overhaul the signal handling:

• support NSIG_MAX from http://austingroupbugs.net/view.php?id=741
  and make a TODO for later to use sysconf(_SC_NSIG) at runtime
• bounds-check signals (e.g. no smaller than 1, but smaller than NSIG)
• align trap errorlevel with other shells
• make trap match what’s in POSIX and fixup the manpage
• refactor some code related to signals
• hide from kill builtin both EXIT and ERR pseudo-signals
This commit is contained in:
tg 2015-04-29 20:44:37 +00:00
parent 4e313e705d
commit 93ccb42114
6 changed files with 219 additions and 162 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.677 2015/04/29 20:39:00 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.678 2015/04/29 20:44:31 tg Exp $'
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015 # 2011, 2012, 2013, 2014, 2015
@ -2248,20 +2248,22 @@ if test 0 = $HAVE_SYS_SIGNAME; then
sigseenone=: sigseenone=:
sigseentwo=: sigseentwo=:
echo '#include <signal.h> echo '#include <signal.h>
#ifndef NSIG #if defined(NSIG_MAX)
#if defined(_NSIG) #define cfg_NSIG NSIG_MAX
#define NSIG _NSIG #elif defined(NSIG)
#define cfg_NSIG NSIG
#elif defined(_NSIG)
#define cfg_NSIG _NSIG
#elif defined(SIGMAX) #elif defined(SIGMAX)
#define NSIG (SIGMAX+1) #define cfg_NSIG (SIGMAX + 1)
#elif defined(_SIGMAX) #elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1) #define cfg_NSIG (_SIGMAX + 1)
#else #else
/* XXX better error out, see sh.h */ /*XXX better error out, see sh.h */
#define NSIG 64 #define cfg_NSIG 64
#endif
#endif #endif
int int
mksh_cfg= NSIG mksh_cfg= cfg_NSIG
;' >conftest.c ;' >conftest.c
# GNU sed 2.03 segfaults when optimising this to sed -n # GNU sed 2.03 segfaults when optimising this to sed -n
NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \ NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
@ -2310,7 +2312,7 @@ mksh_cfg= NSIG
sed 's/^ *mksh_cfg *=[ ]*\([0-9][0-9x]*\).*$/:\1 '$name/ sed 's/^ *mksh_cfg *=[ ]*\([0-9][0-9x]*\).*$/:\1 '$name/
done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
test $printf = echo || nr=`printf %d "$nr" 2>/dev/null` test $printf = echo || nr=`printf %d "$nr" 2>/dev/null`
test $nr -gt 0 && test $nr -le $NSIG || continue test $nr -gt 0 && test $nr -lt $NSIG || continue
case $sigseentwo in case $sigseentwo in
*:$nr:*) ;; *:$nr:*) ;;
*) echo " { \"$name\", $nr }," *) echo " { \"$name\", $nr },"

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.692 2015/04/29 20:13:47 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.693 2015/04/29 20:44:32 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R51 2015/04/19 @(#)MIRBSD KSH R51 2015/04/29
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R51 2015/04/19 @(#)LEGACY KSH R51 2015/04/29
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -4837,7 +4837,7 @@ expected-stdout:
PROG: trap: bad signal 'UNKNOWNSIGNAL' PROG: trap: bad signal 'UNKNOWNSIGNAL'
PROG: trap: bad signal '999999' PROG: trap: bad signal '999999'
PROG: trap: bad signal 'FNORD' PROG: trap: bad signal 'FNORD'
= 3 = 1
trap 2 executed trap 2 executed
--- ---
name: read-IFS-1 name: read-IFS-1

63
funcs.c
View File

@ -38,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.270 2015/04/29 20:07:32 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.271 2015/04/29 20:44:34 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -1331,7 +1331,7 @@ c_kill(const char **wp)
/* assume old style options if -digits or -UPPERCASE */ /* assume old style options if -digits or -UPPERCASE */
if ((p = wp[1]) && *p == '-' && (ksh_isdigit(p[1]) || if ((p = wp[1]) && *p == '-' && (ksh_isdigit(p[1]) ||
ksh_isupper(p[1]))) { ksh_isupper(p[1]))) {
if (!(t = gettrap(p + 1, false))) { if (!(t = gettrap(p + 1, false, false))) {
bi_errorf("bad signal '%s'", p + 1); bi_errorf("bad signal '%s'", p + 1);
return (1); return (1);
} }
@ -1345,7 +1345,8 @@ c_kill(const char **wp)
lflag = true; lflag = true;
break; break;
case 's': case 's':
if (!(t = gettrap(builtin_opt.optarg, true))) { if (!(t = gettrap(builtin_opt.optarg,
true, false))) {
bi_errorf("bad signal '%s'", bi_errorf("bad signal '%s'",
builtin_opt.optarg); builtin_opt.optarg);
return (1); return (1);
@ -1371,24 +1372,25 @@ c_kill(const char **wp)
for (; wp[i]; i++) { for (; wp[i]; i++) {
if (!bi_getn(wp[i], &n)) if (!bi_getn(wp[i], &n))
return (1); return (1);
#if (NSIG < 128) #if (ksh_NSIG < 128)
if (n > 128 && n < 128 + NSIG) if (n > 128 && n < 128 + ksh_NSIG)
n -= 128; n -= 128;
#endif #endif
if (n > 0 && n < NSIG) if (n > 0 && n < ksh_NSIG)
shprintf("%s\n", sigtraps[n].name); shprintf("%s\n", sigtraps[n].name);
else else
shprintf("%d\n", n); shprintf("%d\n", n);
} }
} else { } else {
ssize_t w, mess_cols, mess_octs; ssize_t w, mess_cols = 0, mess_octs = 0;
int j; int j = ksh_NSIG;
struct kill_info ki; struct kill_info ki = { 0, 0 };
for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10) do {
ki.num_width++; ki.num_width++;
ki.name_width = mess_cols = mess_octs = 0; } while ((j /= 10));
for (j = 0; j < NSIG; j++) {
for (j = 1; j < ksh_NSIG; j++) {
w = strlen(sigtraps[j].name); w = strlen(sigtraps[j].name);
if (w > ki.name_width) if (w > ki.name_width)
ki.name_width = w; ki.name_width = w;
@ -1400,7 +1402,7 @@ c_kill(const char **wp)
mess_cols = w; mess_cols = w;
} }
print_columns(shl_stdout, (unsigned int)(NSIG - 1), print_columns(shl_stdout, (unsigned int)(ksh_NSIG - 1),
kill_fmt_entry, (void *)&ki, kill_fmt_entry, (void *)&ki,
ki.num_width + 1 + ki.name_width + 1 + mess_octs, ki.num_width + 1 + ki.name_width + 1 + mess_octs,
ki.num_width + 1 + ki.name_width + 1 + mess_cols, ki.num_width + 1 + ki.name_width + 1 + mess_cols,
@ -2286,41 +2288,44 @@ c_eval(const char **wp)
int int
c_trap(const char **wp) c_trap(const char **wp)
{ {
int i; Trap *p = sigtraps;
int i = ksh_NSIG + 1;
const char *s; const char *s;
Trap *p;
if (ksh_getopt(wp, &builtin_opt, null) == '?') if (ksh_getopt(wp, &builtin_opt, null) == '?')
return (1); return (1);
wp += builtin_opt.optind; wp += builtin_opt.optind;
if (*wp == NULL) { if (*wp == NULL) {
for (p = sigtraps, i = NSIG + 1; --i >= 0; p++) do {
if (p->trap != NULL) { if (p->trap) {
shf_puts("trap -- ", shl_stdout); shf_puts("trap -- ", shl_stdout);
print_value_quoted(shl_stdout, p->trap); print_value_quoted(shl_stdout, p->trap);
shprintf(" %s\n", p->name); shprintf(" %s\n", p->name);
} }
++p;
} while (--i);
return (0); return (0);
} }
/* if (getn(*wp, &i)) {
* Use case sensitive lookup for first arg so the /* first argument is a signal number, reset them all */
* command 'exit' isn't confused with the pseudo-signal
* 'EXIT'.
*/
/* get command */
s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL;
if (s != NULL && ksh_isdash(s))
s = NULL; s = NULL;
} else {
/* first argument must be a command, then */
s = *wp++;
/* reset traps? */
if (ksh_isdash(s))
s = NULL;
}
/* set/clear traps */ /* set/clear the traps */
i = 0; i = 0;
while (*wp != NULL) while (*wp)
if ((p = gettrap(*wp++, true)) == NULL) { if (!(p = gettrap(*wp++, true, true))) {
warningf(true, "%s: %s '%s'", builtin_argv0, warningf(true, "%s: %s '%s'", builtin_argv0,
"bad signal", wp[-1]); "bad signal", wp[-1]);
++i; i = 1;
} else } else
settrap(p, s); settrap(p, s);
return (i); return (i);

157
histrap.c
View File

@ -27,9 +27,9 @@
#include <sys/file.h> #include <sys/file.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.142 2015/04/29 19:11:57 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.143 2015/04/29 20:44:35 tg Exp $");
Trap sigtraps[NSIG + 1]; Trap sigtraps[ksh_NSIG + 1];
static struct sigaction Sigact_ign; static struct sigaction Sigact_ign;
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
@ -980,55 +980,53 @@ inittraps(void)
trap_exstat = -1; trap_exstat = -1;
/* Populate sigtraps based on sys_signame and sys_siglist. */ /* Populate sigtraps based on sys_signame and sys_siglist. */
/*XXX this is idiotic, use a multi-key/value hashtable! */ for (i = 1; i < ksh_NSIG; i++) {
for (i = 0; i <= NSIG; i++) {
sigtraps[i].signal = i; sigtraps[i].signal = i;
if (i == ksh_SIGERR) {
sigtraps[i].name = "ERR";
sigtraps[i].mess = "Error handler";
} else {
#if HAVE_SYS_SIGNAME #if HAVE_SYS_SIGNAME
cs = sys_signame[i]; cs = sys_signame[i];
#else #else
const struct mksh_sigpair *pair = mksh_sigpairs; const struct mksh_sigpair *pair = mksh_sigpairs;
while ((pair->nr != i) && (pair->name != NULL)) while ((pair->nr != i) && (pair->name != NULL))
++pair; ++pair;
cs = pair->name; cs = pair->name;
#endif #endif
if ((cs == NULL) || if ((cs == NULL) ||
(cs[0] == '\0')) (cs[0] == '\0'))
sigtraps[i].name = shf_smprintf("%d", i); sigtraps[i].name = shf_smprintf("%d", i);
else { else {
char *s; char *s;
/* this is not optimal, what about SIGSIG1? */ /* this is not optimal, what about SIGSIG1? */
if ((cs[0] & 0xDF) == 'S' && if (ksh_eq(cs[0], 'S', 's') &&
(cs[1] & 0xDF) == 'I' && ksh_eq(cs[1], 'I', 'i') &&
(cs[2] & 0xDF) == 'G' && ksh_eq(cs[2], 'G', 'g') &&
cs[3] != '\0') { cs[3] != '\0') {
/* skip leading "SIG" */ /* skip leading "SIG" */
cs += 3; cs += 3;
}
strdupx(s, cs, APERM);
sigtraps[i].name = s;
while ((*s = ksh_toupper(*s)))
++s;
} }
#if HAVE_SYS_SIGLIST strdupx(s, cs, APERM);
sigtraps[i].mess = sys_siglist[i]; sigtraps[i].name = s;
#elif HAVE_STRSIGNAL while ((*s = ksh_toupper(*s)))
sigtraps[i].mess = strsignal(i); ++s;
#else
sigtraps[i].mess = NULL;
#endif
if ((sigtraps[i].mess == NULL) ||
(sigtraps[i].mess[0] == '\0'))
sigtraps[i].mess = shf_smprintf("%s %d",
"Signal", i);
} }
#if HAVE_SYS_SIGLIST
sigtraps[i].mess = sys_siglist[i];
#elif HAVE_STRSIGNAL
sigtraps[i].mess = strsignal(i);
#else
sigtraps[i].mess = NULL;
#endif
if ((sigtraps[i].mess == NULL) ||
(sigtraps[i].mess[0] == '\0'))
sigtraps[i].mess = shf_smprintf("%s %d",
"Signal", i);
} }
/* our name for signal 0 */ sigtraps[ksh_SIGEXIT].signal = ksh_SIGEXIT;
sigtraps[ksh_SIGEXIT].name = "EXIT"; sigtraps[ksh_SIGEXIT].name = "EXIT";
sigtraps[ksh_SIGEXIT].mess = "Exit trap";
sigtraps[ksh_SIGERR].signal = ksh_SIGERR;
sigtraps[ksh_SIGERR].name = "ERR";
sigtraps[ksh_SIGERR].mess = "Error handler";
(void)sigemptyset(&Sigact_ign.sa_mask); (void)sigemptyset(&Sigact_ign.sa_mask);
Sigact_ign.sa_flags = 0; /* interruptible */ Sigact_ign.sa_flags = 0; /* interruptible */
@ -1076,21 +1074,24 @@ alarm_catcher(int sig MKSH_A_UNUSED)
} }
Trap * Trap *
gettrap(const char *cs, bool igncase) gettrap(const char *cs, bool igncase, bool allsigs)
{ {
int i; int i;
Trap *p; Trap *p;
char *as; char *as;
if (ksh_isdigit(*cs)) { /* signal number (1..ksh_NSIG) or 0? */
return ((getn(cs, &i) && 0 <= i && i < NSIG) ?
if (ksh_isdigit(*cs))
return ((getn(cs, &i) && 0 <= i && i < ksh_NSIG) ?
(&sigtraps[i]) : NULL); (&sigtraps[i]) : NULL);
}
/* do a lookup by name then */
/* this breaks SIGSIG1, but we do that above anyway */ /* this breaks SIGSIG1, but we do that above anyway */
if ((cs[0] & 0xDF) == 'S' && if (ksh_eq(cs[0], 'S', 's') &&
(cs[1] & 0xDF) == 'I' && ksh_eq(cs[1], 'I', 'i') &&
(cs[2] & 0xDF) == 'G' && ksh_eq(cs[2], 'G', 'g') &&
cs[3] != '\0') { cs[3] != '\0') {
/* skip leading "SIG" */ /* skip leading "SIG" */
cs += 3; cs += 3;
@ -1105,14 +1106,24 @@ gettrap(const char *cs, bool igncase)
} else } else
as = NULL; as = NULL;
/* this is idiotic, we really want a hashtable here */
p = sigtraps; p = sigtraps;
for (i = 0; i <= NSIG; i++) { i = ksh_NSIG + 1;
do {
if (!strcmp(p->name, cs)) if (!strcmp(p->name, cs))
goto found; goto found;
++p; ++p;
} } while (--i);
p = NULL; goto notfound;
found: found:
if (!allsigs) {
if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) {
notfound:
p = NULL;
}
}
afree(as, ATEMP); afree(as, ATEMP);
return (p); return (p);
} }
@ -1156,14 +1167,16 @@ intrcheck(void)
int int
fatal_trap_check(void) fatal_trap_check(void)
{ {
int i; Trap *p = sigtraps;
Trap *p; int i = ksh_NSIG + 1;
/* todo: should check if signal is fatal, not the TF_DFL_INTR flag */ /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */
for (p = sigtraps, i = NSIG+1; --i >= 0; p++) do {
if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL))) if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL)))
/* return value is used as an exit code */ /* return value is used as an exit code */
return (128 + p->signal); return (128 + p->signal);
++p;
} while (--i);
return (0); return (0);
} }
@ -1175,13 +1188,15 @@ fatal_trap_check(void)
int int
trap_pending(void) trap_pending(void)
{ {
int i; Trap *p = sigtraps;
Trap *p; int i = ksh_NSIG + 1;
for (p = sigtraps, i = NSIG+1; --i >= 0; p++) do {
if (p->set && ((p->trap && p->trap[0]) || if (p->set && ((p->trap && p->trap[0]) ||
((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap))) ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap)))
return (p->signal); return (p->signal);
++p;
} while (--i);
return (0); return (0);
} }
@ -1192,8 +1207,8 @@ trap_pending(void)
void void
runtraps(int flag) runtraps(int flag)
{ {
int i; Trap *p = sigtraps;
Trap *p; int i = ksh_NSIG + 1;
if (ksh_tmout_state == TMOUT_LEAVING) { if (ksh_tmout_state == TMOUT_LEAVING) {
ksh_tmout_state = TMOUT_EXECUTING; ksh_tmout_state = TMOUT_EXECUTING;
@ -1212,10 +1227,12 @@ runtraps(int flag)
if (flag & TF_FATAL) if (flag & TF_FATAL)
fatal_trap = 0; fatal_trap = 0;
++trap_nested; ++trap_nested;
for (p = sigtraps, i = NSIG+1; --i >= 0; p++) do {
if (p->set && (!flag || if (p->set && (!flag ||
((p->flags & flag) && p->trap == NULL))) ((p->flags & flag) && p->trap == NULL)))
runtrap(p, false); runtrap(p, false);
++p;
} while (--i);
if (!--trap_nested) if (!--trap_nested)
runtrap(NULL, true); runtrap(NULL, true);
} }
@ -1284,30 +1301,34 @@ runtrap(Trap *p, bool is_last)
void void
cleartraps(void) cleartraps(void)
{ {
int i; Trap *p = sigtraps;
Trap *p; int i = ksh_NSIG + 1;
trap = 0; trap = 0;
intrsig = 0; intrsig = 0;
fatal_trap = 0; fatal_trap = 0;
for (i = NSIG+1, p = sigtraps; --i >= 0; p++) {
do {
p->set = 0; p->set = 0;
if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0]))
settrap(p, NULL); settrap(p, NULL);
} ++p;
} while (--i);
} }
/* restore signals just before an exec(2) */ /* restore signals just before an exec(2) */
void void
restoresigs(void) restoresigs(void)
{ {
int i; Trap *p = sigtraps;
Trap *p; int i = ksh_NSIG + 1;
for (i = NSIG+1, p = sigtraps; --i >= 0; p++) do {
if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL)) if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL))
setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL, setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL,
SS_RESTORE_CURR|SS_FORCE); SS_RESTORE_CURR|SS_FORCE);
++p;
} while (--i);
} }
void void

70
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.365 2015/04/29 20:13:26 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.366 2015/04/29 20:44:36 tg Exp $
.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $ .\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -4631,54 +4631,60 @@ The format of the output is:
0m0.00s 0m0.00s 0m0.00s 0m0.00s
.Ed .Ed
.Pp .Pp
.It Ic trap Ar n Op Ar signal ...
If the first operand is a decimal unsigned integer, this resets all
specified signals to the default action, i.e. is the same as calling
.Ic trap
with a minus sign
.Pq Sq \-
as
.Ar handler ,
followed by the arguments
.Pq Ar n Op Ar signal ... ,
all of which are treated as signals.
.Pp
.It Ic trap Op Ar handler signal ... .It Ic trap Op Ar handler signal ...
Sets a trap handler that is to be executed when any of the specified signals are Sets a trap handler that is to be executed when any of the specified
received. .Ar signal Ns s
are received.
.Ar handler .Ar handler
is either a is either an empty string, indicating the signals are to be ignored,
.Dv NULL a minus sign
string, indicating the signals are to be ignored, a minus sign
.Pq Sq \- , .Pq Sq \- ,
indicating that the default action is to be taken for the signals (see indicating that the default action is to be taken for the signals
.Xr signal 3 ) , .Pq see Xr signal 3 ,
or a string containing shell commands to be evaluated and executed at the first or a string containing shell commands to be executed at the first opportunity
opportunity (i.e. when the current command completes, or before printing the (i.e. when the current command completes, or before printing the next
next
.Ev PS1 .Ev PS1
prompt) after receipt of one of the signals. prompt) after receipt of one of the signals.
.Ar signal .Ar signal
is the name of a signal (e.g.\& is the name of a signal
.Dv PIPE .Pq e.g.\& Dv PIPE or Dv ALRM
or
.Dv ALRM )
or the number of the signal (see the or the number of the signal (see the
.Ic kill \-l .Ic kill Fl l
command above). command above).
.Pp .Pp
There are two special signals: There are two special signals:
.Dv EXIT .Dv EXIT
(also known as 0) which is executed when the shell is about to exit, and .Pq also known as 0 ,
which is executed when the shell is about to exit, and
.Dv ERR , .Dv ERR ,
which is executed after an error occurs (an error is something that would cause which is executed after an error occurs; an error is something
the shell to exit if the that would cause the shell to exit if the
.Fl e .Ic set Fl e
or or
.Ic errexit .Ic set Fl o Ic errexit
option were set \*(en see the option were set.
.Ic set
command above).
.Dv EXIT .Dv EXIT
handlers are executed in the environment of the last executed command. handlers are executed in the environment of the last executed command.
Note
that for non-interactive shells, the trap handler cannot be changed for signals
that were ignored when the shell started.
.Pp .Pp
With no arguments, Note that, for non-interactive shells, the trap handler cannot be changed
for signals that were ignored when the shell started.
.Pp
With no arguments, the current state of the traps that have been set since
the shell started is shown as a series of
.Ic trap .Ic trap
lists, as a series of commands.
.Ic trap
commands, the current state of the traps that have been set since the shell
started.
Note that the output of Note that the output of
.Ic trap .Ic trap
cannot be usefully piped to another process (an artifact of the fact that cannot be usefully piped to another process (an artifact of the fact that

59
sh.h
View File

@ -169,9 +169,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.728 2015/04/29 20:07:34 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.729 2015/04/29 20:44:37 tg Exp $");
#endif #endif
#define MKSH_VERSION "R51 2015/04/19" #define MKSH_VERSION "R51 2015/04/29"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -329,24 +329,47 @@ struct rusage {
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
#endif #endif
#ifndef NSIG
#if defined(_NSIG) /* determine ksh_NSIG: first, use the traditional definitions */
#define NSIG _NSIG #undef ksh_NSIG
#if defined(NSIG)
#define ksh_NSIG NSIG
#elif defined(_NSIG)
#define ksh_NSIG _NSIG
#elif defined(SIGMAX) #elif defined(SIGMAX)
#define NSIG (SIGMAX+1) #define ksh_NSIG (SIGMAX + 1)
#elif defined(_SIGMAX) #elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1) #define ksh_NSIG (_SIGMAX + 1)
#elif defined(NSIG_MAX)
#define ksh_NSIG NSIG_MAX
#else #else
# error Please have your platform define NSIG. # error Please have your platform define NSIG.
#define NSIG 64
#endif #endif
#endif /* range-check them */
#if (ksh_NSIG < 1)
/* get rid of this (and awk/printf(1) in Build.sh) later */
#if (NSIG < 1)
# error Your NSIG value is not positive. # error Your NSIG value is not positive.
#unset NSIG #undef ksh_NSIG
#define NSIG 64 #endif
/* second, see if the new POSIX definition is available */
#ifdef NSIG_MAX
#if (NSIG_MAX < 2)
/* and usable */
# error Your NSIG_MAX value is too small.
#undef NSIG_MAX
#elif (ksh_NSIG > NSIG_MAX)
/* and realistic */
# error Your NSIG value is larger than your NSIG_MAX value.
#undef NSIG_MAX
#else
/* since its usable, prefer it */
#undef ksh_NSIG
#define ksh_NSIG NSIG_MAX
#endif
/* if NSIG_MAX is now still defined, use sysconf(_SC_NSIG) at runtime */
#endif
/* third, for cpp without the error directive, default */
#ifndef ksh_NSIG
#define ksh_NSIG 64
#endif #endif
@ -878,13 +901,13 @@ typedef struct trap {
#define SS_USER BIT(4) /* user is doing the set (ie, trap command) */ #define SS_USER BIT(4) /* user is doing the set (ie, trap command) */
#define SS_SHTRAP BIT(5) /* trap for internal use (ALRM, CHLD, WINCH) */ #define SS_SHTRAP BIT(5) /* trap for internal use (ALRM, CHLD, WINCH) */
#define ksh_SIGEXIT 0 /* for trap EXIT */ #define ksh_SIGEXIT 0 /* for trap EXIT */
#define ksh_SIGERR NSIG /* for trap ERR */ #define ksh_SIGERR ksh_NSIG /* for trap ERR */
EXTERN volatile sig_atomic_t trap; /* traps pending? */ EXTERN volatile sig_atomic_t trap; /* traps pending? */
EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */ EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */
EXTERN volatile sig_atomic_t fatal_trap; /* received a fatal signal */ EXTERN volatile sig_atomic_t fatal_trap; /* received a fatal signal */
extern Trap sigtraps[NSIG+1]; extern Trap sigtraps[ksh_NSIG + 1];
/* got_winch = 1 when we need to re-adjust the window size */ /* got_winch = 1 when we need to re-adjust the window size */
#ifdef SIGWINCH #ifdef SIGWINCH
@ -1745,7 +1768,7 @@ int findhist(int, int, const char *, bool) MKSH_A_PURE;
char **hist_get_newest(bool); char **hist_get_newest(bool);
void inittraps(void); void inittraps(void);
void alarm_init(void); void alarm_init(void);
Trap *gettrap(const char *, bool); Trap *gettrap(const char *, bool, bool);
void trapsig(int); void trapsig(int);
void intrcheck(void); void intrcheck(void);
int fatal_trap_check(void); int fatal_trap_check(void);