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:
parent
4e313e705d
commit
93ccb42114
24
Build.sh
24
Build.sh
@ -1,5 +1,5 @@
|
||||
#!/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,
|
||||
# 2011, 2012, 2013, 2014, 2015
|
||||
@ -2248,20 +2248,22 @@ if test 0 = $HAVE_SYS_SIGNAME; then
|
||||
sigseenone=:
|
||||
sigseentwo=:
|
||||
echo '#include <signal.h>
|
||||
#ifndef NSIG
|
||||
#if defined(_NSIG)
|
||||
#define NSIG _NSIG
|
||||
#if defined(NSIG_MAX)
|
||||
#define cfg_NSIG NSIG_MAX
|
||||
#elif defined(NSIG)
|
||||
#define cfg_NSIG NSIG
|
||||
#elif defined(_NSIG)
|
||||
#define cfg_NSIG _NSIG
|
||||
#elif defined(SIGMAX)
|
||||
#define NSIG (SIGMAX+1)
|
||||
#define cfg_NSIG (SIGMAX + 1)
|
||||
#elif defined(_SIGMAX)
|
||||
#define NSIG (_SIGMAX+1)
|
||||
#define cfg_NSIG (_SIGMAX + 1)
|
||||
#else
|
||||
/* XXX better error out, see sh.h */
|
||||
#define NSIG 64
|
||||
#endif
|
||||
/*XXX better error out, see sh.h */
|
||||
#define cfg_NSIG 64
|
||||
#endif
|
||||
int
|
||||
mksh_cfg= NSIG
|
||||
mksh_cfg= cfg_NSIG
|
||||
;' >conftest.c
|
||||
# GNU sed 2.03 segfaults when optimising this to sed -n
|
||||
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/
|
||||
done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
|
||||
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
|
||||
*:$nr:*) ;;
|
||||
*) echo " { \"$name\", $nr },"
|
||||
|
8
check.t
8
check.t
@ -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 -*-
|
||||
#-
|
||||
# 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
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R51 2015/04/19
|
||||
@(#)MIRBSD KSH R51 2015/04/29
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -39,7 +39,7 @@ name: KSH_VERSION
|
||||
category: shell:legacy-no
|
||||
---
|
||||
expected-stdout:
|
||||
@(#)LEGACY KSH R51 2015/04/19
|
||||
@(#)LEGACY KSH R51 2015/04/29
|
||||
description:
|
||||
Check version of legacy shell.
|
||||
stdin:
|
||||
@ -4837,7 +4837,7 @@ expected-stdout:
|
||||
PROG: trap: bad signal 'UNKNOWNSIGNAL'
|
||||
PROG: trap: bad signal '999999'
|
||||
PROG: trap: bad signal 'FNORD'
|
||||
= 3
|
||||
= 1
|
||||
trap 2 executed
|
||||
---
|
||||
name: read-IFS-1
|
||||
|
63
funcs.c
63
funcs.c
@ -38,7 +38,7 @@
|
||||
#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
|
||||
/*
|
||||
@ -1331,7 +1331,7 @@ c_kill(const char **wp)
|
||||
/* assume old style options if -digits or -UPPERCASE */
|
||||
if ((p = wp[1]) && *p == '-' && (ksh_isdigit(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);
|
||||
return (1);
|
||||
}
|
||||
@ -1345,7 +1345,8 @@ c_kill(const char **wp)
|
||||
lflag = true;
|
||||
break;
|
||||
case 's':
|
||||
if (!(t = gettrap(builtin_opt.optarg, true))) {
|
||||
if (!(t = gettrap(builtin_opt.optarg,
|
||||
true, false))) {
|
||||
bi_errorf("bad signal '%s'",
|
||||
builtin_opt.optarg);
|
||||
return (1);
|
||||
@ -1371,24 +1372,25 @@ c_kill(const char **wp)
|
||||
for (; wp[i]; i++) {
|
||||
if (!bi_getn(wp[i], &n))
|
||||
return (1);
|
||||
#if (NSIG < 128)
|
||||
if (n > 128 && n < 128 + NSIG)
|
||||
#if (ksh_NSIG < 128)
|
||||
if (n > 128 && n < 128 + ksh_NSIG)
|
||||
n -= 128;
|
||||
#endif
|
||||
if (n > 0 && n < NSIG)
|
||||
if (n > 0 && n < ksh_NSIG)
|
||||
shprintf("%s\n", sigtraps[n].name);
|
||||
else
|
||||
shprintf("%d\n", n);
|
||||
}
|
||||
} else {
|
||||
ssize_t w, mess_cols, mess_octs;
|
||||
int j;
|
||||
struct kill_info ki;
|
||||
ssize_t w, mess_cols = 0, mess_octs = 0;
|
||||
int j = ksh_NSIG;
|
||||
struct kill_info ki = { 0, 0 };
|
||||
|
||||
for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10)
|
||||
do {
|
||||
ki.num_width++;
|
||||
ki.name_width = mess_cols = mess_octs = 0;
|
||||
for (j = 0; j < NSIG; j++) {
|
||||
} while ((j /= 10));
|
||||
|
||||
for (j = 1; j < ksh_NSIG; j++) {
|
||||
w = strlen(sigtraps[j].name);
|
||||
if (w > ki.name_width)
|
||||
ki.name_width = w;
|
||||
@ -1400,7 +1402,7 @@ c_kill(const char **wp)
|
||||
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,
|
||||
ki.num_width + 1 + ki.name_width + 1 + mess_octs,
|
||||
ki.num_width + 1 + ki.name_width + 1 + mess_cols,
|
||||
@ -2286,41 +2288,44 @@ c_eval(const char **wp)
|
||||
int
|
||||
c_trap(const char **wp)
|
||||
{
|
||||
int i;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
const char *s;
|
||||
Trap *p;
|
||||
|
||||
if (ksh_getopt(wp, &builtin_opt, null) == '?')
|
||||
return (1);
|
||||
wp += builtin_opt.optind;
|
||||
|
||||
if (*wp == NULL) {
|
||||
for (p = sigtraps, i = NSIG + 1; --i >= 0; p++)
|
||||
if (p->trap != NULL) {
|
||||
do {
|
||||
if (p->trap) {
|
||||
shf_puts("trap -- ", shl_stdout);
|
||||
print_value_quoted(shl_stdout, p->trap);
|
||||
shprintf(" %s\n", p->name);
|
||||
}
|
||||
++p;
|
||||
} while (--i);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use case sensitive lookup for first arg so the
|
||||
* 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))
|
||||
if (getn(*wp, &i)) {
|
||||
/* first argument is a signal number, reset them all */
|
||||
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;
|
||||
while (*wp != NULL)
|
||||
if ((p = gettrap(*wp++, true)) == NULL) {
|
||||
while (*wp)
|
||||
if (!(p = gettrap(*wp++, true, true))) {
|
||||
warningf(true, "%s: %s '%s'", builtin_argv0,
|
||||
"bad signal", wp[-1]);
|
||||
++i;
|
||||
i = 1;
|
||||
} else
|
||||
settrap(p, s);
|
||||
return (i);
|
||||
|
157
histrap.c
157
histrap.c
@ -27,9 +27,9 @@
|
||||
#include <sys/file.h>
|
||||
#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;
|
||||
|
||||
#if HAVE_PERSISTENT_HISTORY
|
||||
@ -980,55 +980,53 @@ inittraps(void)
|
||||
trap_exstat = -1;
|
||||
|
||||
/* Populate sigtraps based on sys_signame and sys_siglist. */
|
||||
/*XXX this is idiotic, use a multi-key/value hashtable! */
|
||||
for (i = 0; i <= NSIG; i++) {
|
||||
for (i = 1; i < ksh_NSIG; i++) {
|
||||
sigtraps[i].signal = i;
|
||||
if (i == ksh_SIGERR) {
|
||||
sigtraps[i].name = "ERR";
|
||||
sigtraps[i].mess = "Error handler";
|
||||
} else {
|
||||
#if HAVE_SYS_SIGNAME
|
||||
cs = sys_signame[i];
|
||||
cs = sys_signame[i];
|
||||
#else
|
||||
const struct mksh_sigpair *pair = mksh_sigpairs;
|
||||
while ((pair->nr != i) && (pair->name != NULL))
|
||||
++pair;
|
||||
cs = pair->name;
|
||||
const struct mksh_sigpair *pair = mksh_sigpairs;
|
||||
while ((pair->nr != i) && (pair->name != NULL))
|
||||
++pair;
|
||||
cs = pair->name;
|
||||
#endif
|
||||
if ((cs == NULL) ||
|
||||
(cs[0] == '\0'))
|
||||
sigtraps[i].name = shf_smprintf("%d", i);
|
||||
else {
|
||||
char *s;
|
||||
if ((cs == NULL) ||
|
||||
(cs[0] == '\0'))
|
||||
sigtraps[i].name = shf_smprintf("%d", i);
|
||||
else {
|
||||
char *s;
|
||||
|
||||
/* this is not optimal, what about SIGSIG1? */
|
||||
if ((cs[0] & 0xDF) == 'S' &&
|
||||
(cs[1] & 0xDF) == 'I' &&
|
||||
(cs[2] & 0xDF) == 'G' &&
|
||||
cs[3] != '\0') {
|
||||
/* skip leading "SIG" */
|
||||
cs += 3;
|
||||
}
|
||||
strdupx(s, cs, APERM);
|
||||
sigtraps[i].name = s;
|
||||
while ((*s = ksh_toupper(*s)))
|
||||
++s;
|
||||
/* this is not optimal, what about SIGSIG1? */
|
||||
if (ksh_eq(cs[0], 'S', 's') &&
|
||||
ksh_eq(cs[1], 'I', 'i') &&
|
||||
ksh_eq(cs[2], 'G', 'g') &&
|
||||
cs[3] != '\0') {
|
||||
/* skip leading "SIG" */
|
||||
cs += 3;
|
||||
}
|
||||
#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);
|
||||
strdupx(s, cs, APERM);
|
||||
sigtraps[i].name = s;
|
||||
while ((*s = ksh_toupper(*s)))
|
||||
++s;
|
||||
}
|
||||
#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].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);
|
||||
Sigact_ign.sa_flags = 0; /* interruptible */
|
||||
@ -1076,21 +1074,24 @@ alarm_catcher(int sig MKSH_A_UNUSED)
|
||||
}
|
||||
|
||||
Trap *
|
||||
gettrap(const char *cs, bool igncase)
|
||||
gettrap(const char *cs, bool igncase, bool allsigs)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
char *as;
|
||||
|
||||
if (ksh_isdigit(*cs)) {
|
||||
return ((getn(cs, &i) && 0 <= i && i < NSIG) ?
|
||||
/* signal number (1..ksh_NSIG) or 0? */
|
||||
|
||||
if (ksh_isdigit(*cs))
|
||||
return ((getn(cs, &i) && 0 <= i && i < ksh_NSIG) ?
|
||||
(&sigtraps[i]) : NULL);
|
||||
}
|
||||
|
||||
/* do a lookup by name then */
|
||||
|
||||
/* this breaks SIGSIG1, but we do that above anyway */
|
||||
if ((cs[0] & 0xDF) == 'S' &&
|
||||
(cs[1] & 0xDF) == 'I' &&
|
||||
(cs[2] & 0xDF) == 'G' &&
|
||||
if (ksh_eq(cs[0], 'S', 's') &&
|
||||
ksh_eq(cs[1], 'I', 'i') &&
|
||||
ksh_eq(cs[2], 'G', 'g') &&
|
||||
cs[3] != '\0') {
|
||||
/* skip leading "SIG" */
|
||||
cs += 3;
|
||||
@ -1105,14 +1106,24 @@ gettrap(const char *cs, bool igncase)
|
||||
} else
|
||||
as = NULL;
|
||||
|
||||
/* this is idiotic, we really want a hashtable here */
|
||||
|
||||
p = sigtraps;
|
||||
for (i = 0; i <= NSIG; i++) {
|
||||
i = ksh_NSIG + 1;
|
||||
do {
|
||||
if (!strcmp(p->name, cs))
|
||||
goto found;
|
||||
++p;
|
||||
}
|
||||
p = NULL;
|
||||
} while (--i);
|
||||
goto notfound;
|
||||
|
||||
found:
|
||||
if (!allsigs) {
|
||||
if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) {
|
||||
notfound:
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
afree(as, ATEMP);
|
||||
return (p);
|
||||
}
|
||||
@ -1156,14 +1167,16 @@ intrcheck(void)
|
||||
int
|
||||
fatal_trap_check(void)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
|
||||
/* 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)))
|
||||
/* return value is used as an exit code */
|
||||
return (128 + p->signal);
|
||||
++p;
|
||||
} while (--i);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1175,13 +1188,15 @@ fatal_trap_check(void)
|
||||
int
|
||||
trap_pending(void)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
|
||||
for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
|
||||
do {
|
||||
if (p->set && ((p->trap && p->trap[0]) ||
|
||||
((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap)))
|
||||
return (p->signal);
|
||||
++p;
|
||||
} while (--i);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1192,8 +1207,8 @@ trap_pending(void)
|
||||
void
|
||||
runtraps(int flag)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
|
||||
if (ksh_tmout_state == TMOUT_LEAVING) {
|
||||
ksh_tmout_state = TMOUT_EXECUTING;
|
||||
@ -1212,10 +1227,12 @@ runtraps(int flag)
|
||||
if (flag & TF_FATAL)
|
||||
fatal_trap = 0;
|
||||
++trap_nested;
|
||||
for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
|
||||
do {
|
||||
if (p->set && (!flag ||
|
||||
((p->flags & flag) && p->trap == NULL)))
|
||||
runtrap(p, false);
|
||||
++p;
|
||||
} while (--i);
|
||||
if (!--trap_nested)
|
||||
runtrap(NULL, true);
|
||||
}
|
||||
@ -1284,30 +1301,34 @@ runtrap(Trap *p, bool is_last)
|
||||
void
|
||||
cleartraps(void)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
|
||||
trap = 0;
|
||||
intrsig = 0;
|
||||
fatal_trap = 0;
|
||||
for (i = NSIG+1, p = sigtraps; --i >= 0; p++) {
|
||||
|
||||
do {
|
||||
p->set = 0;
|
||||
if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0]))
|
||||
settrap(p, NULL);
|
||||
}
|
||||
++p;
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
/* restore signals just before an exec(2) */
|
||||
void
|
||||
restoresigs(void)
|
||||
{
|
||||
int i;
|
||||
Trap *p;
|
||||
Trap *p = sigtraps;
|
||||
int i = ksh_NSIG + 1;
|
||||
|
||||
for (i = NSIG+1, p = sigtraps; --i >= 0; p++)
|
||||
do {
|
||||
if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL))
|
||||
setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL,
|
||||
SS_RESTORE_CURR|SS_FORCE);
|
||||
++p;
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
void
|
||||
|
70
mksh.1
70
mksh.1
@ -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 $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
@ -4631,54 +4631,60 @@ The format of the output is:
|
||||
0m0.00s 0m0.00s
|
||||
.Ed
|
||||
.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 ...
|
||||
Sets a trap handler that is to be executed when any of the specified signals are
|
||||
received.
|
||||
Sets a trap handler that is to be executed when any of the specified
|
||||
.Ar signal Ns s
|
||||
are received.
|
||||
.Ar handler
|
||||
is either a
|
||||
.Dv NULL
|
||||
string, indicating the signals are to be ignored, a minus sign
|
||||
is either an empty string, indicating the signals are to be ignored,
|
||||
a minus sign
|
||||
.Pq Sq \- ,
|
||||
indicating that the default action is to be taken for the signals (see
|
||||
.Xr signal 3 ) ,
|
||||
or a string containing shell commands to be evaluated and executed at the first
|
||||
opportunity (i.e. when the current command completes, or before printing the
|
||||
next
|
||||
indicating that the default action is to be taken for the signals
|
||||
.Pq see Xr signal 3 ,
|
||||
or a string containing shell commands to be executed at the first opportunity
|
||||
(i.e. when the current command completes, or before printing the next
|
||||
.Ev PS1
|
||||
prompt) after receipt of one of the signals.
|
||||
.Ar signal
|
||||
is the name of a signal (e.g.\&
|
||||
.Dv PIPE
|
||||
or
|
||||
.Dv ALRM )
|
||||
is the name of a signal
|
||||
.Pq e.g.\& Dv PIPE or Dv ALRM
|
||||
or the number of the signal (see the
|
||||
.Ic kill \-l
|
||||
.Ic kill Fl l
|
||||
command above).
|
||||
.Pp
|
||||
There are two special signals:
|
||||
.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 ,
|
||||
which is executed after an error occurs (an error is something that would cause
|
||||
the shell to exit if the
|
||||
.Fl e
|
||||
which is executed after an error occurs; an error is something
|
||||
that would cause the shell to exit if the
|
||||
.Ic set Fl e
|
||||
or
|
||||
.Ic errexit
|
||||
option were set \*(en see the
|
||||
.Ic set
|
||||
command above).
|
||||
.Ic set Fl o Ic errexit
|
||||
option were set.
|
||||
.Dv EXIT
|
||||
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
|
||||
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
|
||||
lists, as a series of
|
||||
.Ic trap
|
||||
commands, the current state of the traps that have been set since the shell
|
||||
started.
|
||||
commands.
|
||||
Note that the output of
|
||||
.Ic trap
|
||||
cannot be usefully piped to another process (an artifact of the fact that
|
||||
|
59
sh.h
59
sh.h
@ -169,9 +169,9 @@
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define MKSH_VERSION "R51 2015/04/19"
|
||||
#define MKSH_VERSION "R51 2015/04/29"
|
||||
|
||||
/* arithmetic types: C implementation */
|
||||
#if !HAVE_CAN_INTTYPES
|
||||
@ -329,24 +329,47 @@ struct rusage {
|
||||
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||
#endif
|
||||
|
||||
#ifndef NSIG
|
||||
#if defined(_NSIG)
|
||||
#define NSIG _NSIG
|
||||
|
||||
/* determine ksh_NSIG: first, use the traditional definitions */
|
||||
#undef ksh_NSIG
|
||||
#if defined(NSIG)
|
||||
#define ksh_NSIG NSIG
|
||||
#elif defined(_NSIG)
|
||||
#define ksh_NSIG _NSIG
|
||||
#elif defined(SIGMAX)
|
||||
#define NSIG (SIGMAX+1)
|
||||
#define ksh_NSIG (SIGMAX + 1)
|
||||
#elif defined(_SIGMAX)
|
||||
#define NSIG (_SIGMAX+1)
|
||||
#define ksh_NSIG (_SIGMAX + 1)
|
||||
#elif defined(NSIG_MAX)
|
||||
#define ksh_NSIG NSIG_MAX
|
||||
#else
|
||||
# error Please have your platform define NSIG.
|
||||
#define NSIG 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* get rid of this (and awk/printf(1) in Build.sh) later */
|
||||
#if (NSIG < 1)
|
||||
/* range-check them */
|
||||
#if (ksh_NSIG < 1)
|
||||
# error Your NSIG value is not positive.
|
||||
#unset NSIG
|
||||
#define NSIG 64
|
||||
#undef ksh_NSIG
|
||||
#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 it’s 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
|
||||
|
||||
|
||||
@ -878,13 +901,13 @@ typedef struct trap {
|
||||
#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 ksh_SIGEXIT 0 /* for trap EXIT */
|
||||
#define ksh_SIGERR NSIG /* for trap ERR */
|
||||
#define ksh_SIGEXIT 0 /* for trap EXIT */
|
||||
#define ksh_SIGERR ksh_NSIG /* for trap ERR */
|
||||
|
||||
EXTERN volatile sig_atomic_t trap; /* traps pending? */
|
||||
EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */
|
||||
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 */
|
||||
#ifdef SIGWINCH
|
||||
@ -1745,7 +1768,7 @@ int findhist(int, int, const char *, bool) MKSH_A_PURE;
|
||||
char **hist_get_newest(bool);
|
||||
void inittraps(void);
|
||||
void alarm_init(void);
|
||||
Trap *gettrap(const char *, bool);
|
||||
Trap *gettrap(const char *, bool, bool);
|
||||
void trapsig(int);
|
||||
void intrcheck(void);
|
||||
int fatal_trap_check(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user