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
|
#!/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 },"
|
||||||
|
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 -*-
|
# -*- 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
63
funcs.c
@ -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
157
histrap.c
@ -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
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 $
|
.\" $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
59
sh.h
@ -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 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
|
#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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user