diff options
author | Bryan Drewery <bryan@shatow.net> | 2018-02-04 04:36:47 +0300 |
---|---|---|
committer | Bryan Drewery <bryan@shatow.net> | 2018-02-08 05:53:07 +0300 |
commit | 17a5084cbf5c43b6271f602fcebf1c15b5000696 (patch) | |
tree | 639fe3bcb73dd24ac5dd312cf2bcb7df7f17e170 | |
parent | 700ad285a3abb2b06906bfaeabf32a9720a7df65 (diff) |
Add trap_push/pop builtins
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | Makefile.in | 22 | ||||
-rw-r--r-- | external/sh/trap.c | 4 | ||||
-rw-r--r-- | external/update_sh.sh | 2 | ||||
-rw-r--r-- | src/libexec/poudriere/cachec/cachec.c | 10 | ||||
-rw-r--r-- | src/libexec/poudriere/locked_mkdir/locked_mkdir.c | 6 | ||||
-rw-r--r-- | src/libexec/poudriere/pwait/pwait.c | 2 | ||||
-rw-r--r-- | src/poudriere-sh/builtins-poudriere.def | 2 | ||||
-rw-r--r-- | src/poudriere-sh/helpers.c | 115 | ||||
-rw-r--r-- | src/poudriere-sh/helpers.h | 16 | ||||
-rw-r--r-- | src/poudriere-sh/traps.c | 124 | ||||
-rw-r--r-- | src/share/poudriere/include/util.sh | 4 | ||||
-rw-r--r-- | test/trap_save.sh | 11 |
13 files changed, 293 insertions, 26 deletions
diff --git a/Makefile.am b/Makefile.am index 99559229..e577c616 100644 --- a/Makefile.am +++ b/Makefile.am @@ -216,6 +216,7 @@ sh_SOURCES+= \ src/poudriere-sh/rmdir.c \ src/poudriere-sh/setproctitle.c \ src/poudriere-sh/sleep.c \ + src/poudriere-sh/traps.c \ src/poudriere-sh/touch.c \ src/poudriere-sh/unlink.c sh_CFLAGS+= -I$(top_srcdir)/src/poudriere-sh \ diff --git a/Makefile.in b/Makefile.in index 749efac6..c07b0549 100644 --- a/Makefile.in +++ b/Makefile.in @@ -261,6 +261,7 @@ am_sh_OBJECTS = external/sh_compat/sh-strchrnul.$(OBJEXT) \ src/poudriere-sh/sh-rmdir.$(OBJEXT) \ src/poudriere-sh/sh-setproctitle.$(OBJEXT) \ src/poudriere-sh/sh-sleep.$(OBJEXT) \ + src/poudriere-sh/sh-traps.$(OBJEXT) \ src/poudriere-sh/sh-touch.$(OBJEXT) \ src/poudriere-sh/sh-unlink.$(OBJEXT) \ src/poudriere-sh/sh-builtins.$(OBJEXT) @@ -665,8 +666,8 @@ sh_SOURCES = external/sh_compat/strchrnul.c \ src/poudriere-sh/mkfifo.c src/poudriere-sh/mktemp.c \ src/poudriere-sh/realpath.c src/poudriere-sh/rmdir.c \ src/poudriere-sh/setproctitle.c src/poudriere-sh/sleep.c \ - src/poudriere-sh/touch.c src/poudriere-sh/unlink.c \ - src/poudriere-sh/builtins.c + src/poudriere-sh/traps.c src/poudriere-sh/touch.c \ + src/poudriere-sh/unlink.c src/poudriere-sh/builtins.c libucl_a_SOURCES = external/libucl/src/ucl_emitter.c \ external/libucl/src/ucl_emitter_streamline.c \ external/libucl/src/ucl_emitter_utils.c \ @@ -1232,6 +1233,8 @@ src/poudriere-sh/sh-setproctitle.$(OBJEXT): \ src/poudriere-sh/$(DEPDIR)/$(am__dirstamp) src/poudriere-sh/sh-sleep.$(OBJEXT): src/poudriere-sh/$(am__dirstamp) \ src/poudriere-sh/$(DEPDIR)/$(am__dirstamp) +src/poudriere-sh/sh-traps.$(OBJEXT): src/poudriere-sh/$(am__dirstamp) \ + src/poudriere-sh/$(DEPDIR)/$(am__dirstamp) src/poudriere-sh/sh-touch.$(OBJEXT): src/poudriere-sh/$(am__dirstamp) \ src/poudriere-sh/$(DEPDIR)/$(am__dirstamp) src/poudriere-sh/sh-unlink.$(OBJEXT): \ @@ -1468,6 +1471,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/poudriere-sh/$(DEPDIR)/sh-setproctitle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/poudriere-sh/$(DEPDIR)/sh-sleep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/poudriere-sh/$(DEPDIR)/sh-touch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/poudriere-sh/$(DEPDIR)/sh-traps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/poudriere-sh/$(DEPDIR)/sh-unlink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/poudriered/$(DEPDIR)/poudriered-poudriered.Po@am__quote@ @@ -2453,6 +2457,20 @@ src/poudriere-sh/sh-sleep.obj: src/poudriere-sh/sleep.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -c -o src/poudriere-sh/sh-sleep.obj `if test -f 'src/poudriere-sh/sleep.c'; then $(CYGPATH_W) 'src/poudriere-sh/sleep.c'; else $(CYGPATH_W) '$(srcdir)/src/poudriere-sh/sleep.c'; fi` +src/poudriere-sh/sh-traps.o: src/poudriere-sh/traps.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -MT src/poudriere-sh/sh-traps.o -MD -MP -MF src/poudriere-sh/$(DEPDIR)/sh-traps.Tpo -c -o src/poudriere-sh/sh-traps.o `test -f 'src/poudriere-sh/traps.c' || echo '$(srcdir)/'`src/poudriere-sh/traps.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/poudriere-sh/$(DEPDIR)/sh-traps.Tpo src/poudriere-sh/$(DEPDIR)/sh-traps.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/poudriere-sh/traps.c' object='src/poudriere-sh/sh-traps.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -c -o src/poudriere-sh/sh-traps.o `test -f 'src/poudriere-sh/traps.c' || echo '$(srcdir)/'`src/poudriere-sh/traps.c + +src/poudriere-sh/sh-traps.obj: src/poudriere-sh/traps.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -MT src/poudriere-sh/sh-traps.obj -MD -MP -MF src/poudriere-sh/$(DEPDIR)/sh-traps.Tpo -c -o src/poudriere-sh/sh-traps.obj `if test -f 'src/poudriere-sh/traps.c'; then $(CYGPATH_W) 'src/poudriere-sh/traps.c'; else $(CYGPATH_W) '$(srcdir)/src/poudriere-sh/traps.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/poudriere-sh/$(DEPDIR)/sh-traps.Tpo src/poudriere-sh/$(DEPDIR)/sh-traps.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/poudriere-sh/traps.c' object='src/poudriere-sh/sh-traps.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -c -o src/poudriere-sh/sh-traps.obj `if test -f 'src/poudriere-sh/traps.c'; then $(CYGPATH_W) 'src/poudriere-sh/traps.c'; else $(CYGPATH_W) '$(srcdir)/src/poudriere-sh/traps.c'; fi` + src/poudriere-sh/sh-touch.o: src/poudriere-sh/touch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sh_CFLAGS) $(CFLAGS) -MT src/poudriere-sh/sh-touch.o -MD -MP -MF src/poudriere-sh/$(DEPDIR)/sh-touch.Tpo -c -o src/poudriere-sh/sh-touch.o `test -f 'src/poudriere-sh/touch.c' || echo '$(srcdir)/'`src/poudriere-sh/touch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/poudriere-sh/$(DEPDIR)/sh-touch.Tpo src/poudriere-sh/$(DEPDIR)/sh-touch.Po diff --git a/external/sh/trap.c b/external/sh/trap.c index 8a230241..58cb0177 100644 --- a/external/sh/trap.c +++ b/external/sh/trap.c @@ -74,11 +74,11 @@ __FBSDID("$FreeBSD: head/bin/sh/trap.c 326025 2017-11-20 19:49:47Z pfg $"); #define S_RESET 5 /* temporary - to reset a hard ignored sig */ -static char sigmode[NSIG]; /* current value of signal */ +char sigmode[NSIG]; /* current value of signal */ volatile sig_atomic_t pendingsig; /* indicates some signal received */ volatile sig_atomic_t pendingsig_waitcmd; /* indicates wait builtin should be interrupted */ static int in_dotrap; /* do we execute in a trap handler? */ -static char *volatile trap[NSIG]; /* trap handler commands */ +char *volatile trap[NSIG]; /* trap handler commands */ volatile sig_atomic_t gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ diff --git a/external/update_sh.sh b/external/update_sh.sh index cceb6f46..ab164790 100644 --- a/external/update_sh.sh +++ b/external/update_sh.sh @@ -44,7 +44,7 @@ cd "${ORIG_PWD}" # Fix backwards compat for st_mtim sed -i '' -e 's,[[:<:]]st_mtim[[:>:]],st_mtimespec,g' "${DESTDIR}/test.c" # Allow interaction with traps -sed -i '' -Ee 's,^static (volatile sig_atomic_t gotsig),\1,' \ +sed -i '' -Ee 's,^static (char sigmode|char \*volatile trap|volatile sig_atomic_t gotsig),\1,' \ "${DESTDIR}external/sh/trap.c" git add -A "${DESTDIR}" diff --git a/src/libexec/poudriere/cachec/cachec.c b/src/libexec/poudriere/cachec/cachec.c index 274e0afb..dd32b60f 100644 --- a/src/libexec/poudriere/cachec/cachec.c +++ b/src/libexec/poudriere/cachec/cachec.c @@ -57,7 +57,7 @@ main(int argc, char **argv) size_t outlen; bool set = false; #ifdef SHELL - struct sigaction oact; + struct sigdata oinfo; while ((ch = nextopt("s:")) != '\0') { switch (ch) { @@ -94,12 +94,12 @@ main(int argc, char **argv) #ifdef SHELL INTOFF; - siginfo_push(&oact); + trap_push(SIGINFO, &oinfo); #endif qserver = mq_open(queuepath, O_WRONLY); if (qserver == (mqd_t)-1) { #ifdef SHELL - siginfo_pop(&oact); + trap_pop(SIGINFO, &oinfo); INTON; #endif err(EXIT_FAILURE, "%s", "mq_open"); @@ -114,7 +114,7 @@ main(int argc, char **argv) mq_send(qserver, out, outlen, 0); mq_close(qserver); #ifdef SHELL - siginfo_pop(&oact); + trap_pop(SIGINFO, &oinfo); INTON; #endif return (0); @@ -131,7 +131,7 @@ main(int argc, char **argv) mq_close(qme); mq_unlink(spath); #ifdef SHELL - siginfo_pop(&oact); + trap_pop(SIGINFO, &oinfo); INTON; #endif return (0); diff --git a/src/libexec/poudriere/locked_mkdir/locked_mkdir.c b/src/libexec/poudriere/locked_mkdir/locked_mkdir.c index 898e0d1e..3f2d7dbd 100644 --- a/src/libexec/poudriere/locked_mkdir/locked_mkdir.c +++ b/src/libexec/poudriere/locked_mkdir/locked_mkdir.c @@ -57,7 +57,7 @@ static int lockfd = -1; static volatile sig_atomic_t timed_out; static struct sigaction oact; #ifdef SHELL -static struct sigaction oact_siginfo; +static struct sigdata oinfo; #endif /* @@ -95,7 +95,7 @@ cleanup(void) } #ifdef SHELL sigaction(SIGALRM, &oact, NULL); - siginfo_pop(&oact_siginfo); + trap_pop(SIGINFO, &oinfo); errno = serrno; #endif } @@ -134,7 +134,7 @@ main(int argc, char **argv) #ifdef SHELL INTOFF; - siginfo_push(&oact_siginfo); + trap_push(SIGINFO, &oinfo); #endif act.sa_handler = sig_timeout; sigemptyset(&act.sa_mask); diff --git a/src/libexec/poudriere/pwait/pwait.c b/src/libexec/poudriere/pwait/pwait.c index 04adf4ce..7ef5c4c4 100644 --- a/src/libexec/poudriere/pwait/pwait.c +++ b/src/libexec/poudriere/pwait/pwait.c @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) { #ifdef SHELL - struct sigaction info_oact, alrm_oact; + struct sigdata info_oact, alrm_oact; #endif struct itimerval itv; int kq; diff --git a/src/poudriere-sh/builtins-poudriere.def b/src/poudriere-sh/builtins-poudriere.def index c54a3053..304c6376 100644 --- a/src/poudriere-sh/builtins-poudriere.def +++ b/src/poudriere-sh/builtins-poudriere.def @@ -13,4 +13,6 @@ rmdircmd -n rmdir setproctitlecmd setproctitle sleepcmd -n sleep touchcmd touch +trap_pushcmd -n trap_push +trap_popcmd -n trap_pop unlinkcmd -n unlink diff --git a/src/poudriere-sh/helpers.c b/src/poudriere-sh/helpers.c index 7e8cd922..6b7175a9 100644 --- a/src/poudriere-sh/helpers.c +++ b/src/poudriere-sh/helpers.c @@ -28,29 +28,132 @@ #include <signal.h> #include <string.h> +#include "helpers.h" + +#include "bltin/bltin.h" +#include "options.h" + +extern int rootshell; + +/* From external/sh/trap.c */ +extern char *volatile trap[NSIG]; /* trap handler commands */ +extern char sigmode[NSIG]; /* current value of signal */ +extern char *savestr(const char *); +extern void onsig(int); +extern void ckfree(pointer); +#define S_DFL 1 /* default signal handling (SIG_DFL) */ +#define S_CATCH 2 /* signal is caught */ +#define S_IGN 3 /* signal is ignored (SIG_IGN) */ +#define S_HARD_IGN 4 /* signal is ignored permanently */ +#define S_RESET 5 /* temporary - to reset a hard ignored sig */ + /* * Allow signal to use SA_RESTART. The trapcmd always registers * traps without SA_RESTART, but for the builtins we do want that * behavior on SIGINFO. This is also for restoring signal handlers * that are modified temporarily in the builtin. */ -void -trap_push(int signo, struct sigaction *oact) +static void +_trap_push(int signo, struct sigdata *sd, bool sh) { struct sigaction act; + sig_t sigact = SIG_DFL; + char *action_str = "-", *t; + int action; + + memset(sd, sizeof(*sd), 0); + sd->signo = signo; + sd->sh = sh; + + /* Adapted from setsignal() */ + /* While a trap is stashed we want to use S_DFL (-) by default. */ + action = S_DFL; + switch (signo) { + case SIGINT: + case SIGQUIT: + action = S_CATCH; + break; + case SIGINFO: + /* Ignore to avoid [EINTR]. */ + action = S_DFL; + break; + case SIGALRM: + action = S_IGN; + break; + case SIGTERM: + if (rootshell && iflag) + action = S_IGN; + break; +#if JOBS + case SIGTSTP: + case SIGTTOU: + if (rootshell && mflag) + action = S_IGN; + else + action = S_DFL; + break; +#endif + default: + action = S_DFL; + break; + } + switch (action) { + case S_DFL: sigact = SIG_DFL; action_str=NULL; break; + case S_CATCH: sigact = onsig; action_str=NULL; break; + case S_IGN: sigact = SIG_IGN; action_str=""; break; + } - act.sa_handler = SIG_IGN; + if (sh) { + sd->action_str = trap[signo]; + if (action_str != NULL) + action_str = savestr(action_str); + trap[signo] = action_str; + } + act.sa_handler = sigact; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; - sigaction(signo, &act, oact); + sigaction(signo, &act, &sd->oact); + + if (sh) { + t = &sigmode[signo]; + if (*t == 0) { + if (sd->oact.sa_handler == SIG_IGN) { + if (mflag && (signo == SIGTSTP || + signo == SIGTTIN || signo == SIGTTOU)) { + *t = S_IGN; /* don't hard ignore these */ + } else + *t = S_HARD_IGN; + } else { + *t = S_RESET; /* force to be set */ + } + } + *t = action; + sd->sigmode = sigmode[sd->signo]; + } +} +void +trap_push(int signo, struct sigdata *sd) +{ + _trap_push(signo, sd, 0); +} +void +trap_push_sh(int signo, struct sigdata *sd) +{ + _trap_push(signo, sd, 1); } void -trap_pop(int signo, struct sigaction *oact) +trap_pop(int signo, struct sigdata *sd) { int serrno; serrno = errno; - sigaction(signo, oact, NULL); + sigaction(signo, &sd->oact, NULL); + if (sd->sh) { + if (trap[sd->signo]) + ckfree(trap[sd->signo]); + trap[sd->signo] = sd->action_str; + sigmode[sd->signo] = sd->sigmode; + } errno = serrno; } diff --git a/src/poudriere-sh/helpers.h b/src/poudriere-sh/helpers.h index 69cb6eae..ba936c5b 100644 --- a/src/poudriere-sh/helpers.h +++ b/src/poudriere-sh/helpers.h @@ -25,8 +25,16 @@ */ #include <signal.h> +#include <stdbool.h> -void trap_push(int signo, struct sigaction *oact); -void trap_pop(int signo, struct sigaction *oact); -#define siginfo_push(oact) trap_push(SIGINFO, oact) -#define siginfo_pop(oact) trap_pop(SIGINFO, oact) +struct sigdata { + struct sigaction oact; + char *action_str; + char sigmode; + int signo; + bool sh; +}; + +void trap_push(int signo, struct sigdata *sd); +void trap_push_sh(int signo, struct sigdata *sd); +void trap_pop(int signo, struct sigdata *sd); diff --git a/src/poudriere-sh/traps.c b/src/poudriere-sh/traps.c new file mode 100644 index 00000000..2d75836d --- /dev/null +++ b/src/poudriere-sh/traps.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2018 Bryan Drewery <bdrewery@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sysexits.h> + +#ifndef SHELL +#error Only supported as a builtin +#endif + +#include "bltin/bltin.h" +#include <errno.h> +#include "helpers.h" +#include "var.h" +#define err(exitstatus, fmt, ...) error(fmt ": %s", __VA_ARGS__, strerror(errno)) + +extern int rootpid; + +#define MAX_SIGNALS 32 +static struct sigdata *signals[MAX_SIGNALS] = {0}; +static int nextidx = 0; + +static int +signame_to_signum(const char *sig) +{ + int n; + + if (strncasecmp(sig, "SIG", 3) == 0) + sig += 3; + for (n = 1; n < sys_nsig; n++) { + if (!strcasecmp(sys_signame[n], sig)) + return (n); + } + return (-1); +} + +int +trap_pushcmd(int argc, char **argv) +{ + struct sigdata *sd; + char buf[32]; + int signo; + + if (argc != 3) + errx(EXIT_USAGE, "%s", "Usage: trap_push <signal> <var_return>"); + + if ((signo = signame_to_signum(argv[1])) == -1) + errx(EX_DATAERR, "Invalid signal %s", argv[1]); + + if (signals[nextidx] != NULL) + errx(EX_SOFTWARE, "%s", "Signal stack exceeded"); + + INTOFF; + sd = calloc(1, sizeof(*sd)); + trap_push_sh(signo, sd); + + snprintf(buf, sizeof(buf), "%d", nextidx); + + signals[nextidx] = sd; + if (nextidx + 1 == MAX_SIGNALS) + nextidx = 0; + else + ++nextidx; + INTON; + setvar(argv[2], buf, 0); + + return (0); +} + +int +trap_popcmd(int argc, char **argv) +{ + struct sigdata *sd; + char *end; + int signo, idx; + + if (argc != 3) + errx(EXIT_USAGE, "%s", "Usage: trap_popcmd <signal> <saved_trap>"); + + if ((signo = signame_to_signum(argv[1])) == -1) + errx(EX_DATAERR, "Invalid signal %s", argv[1]); + + errno = 0; + idx = strtod(argv[2], &end); + if (end == argv[2] || errno == ERANGE || idx < 0 || idx >= MAX_SIGNALS) + errx(EX_DATAERR, "%s", "Invalid saved_trap"); + sd = signals[idx]; + if (sd == NULL || sd->signo != signo) + errx(EX_DATAERR, "%s", "Invalid saved_trap"); + + INTOFF; + trap_pop(sd->signo, sd); + free(signals[idx]); + signals[idx] = NULL; + INTON; + + return (0); + +} diff --git a/src/share/poudriere/include/util.sh b/src/share/poudriere/include/util.sh index 41a3fcf7..0eb7c215 100644 --- a/src/share/poudriere/include/util.sh +++ b/src/share/poudriere/include/util.sh @@ -160,6 +160,7 @@ relpath() { echo "${_relpath}" } +if [ "$(type trap_push 2>/dev/null)" != "trap_push is a shell builtin" ]; then trap_push() { local -; set +x [ $# -eq 2 ] || eargs trap_push signal var_return @@ -193,11 +194,12 @@ trap_pop() { local _trap="$2" if [ -n "${_trap}" ]; then - eval trap -- ${_trap} ${signal} || : + eval trap -- "${_trap}" ${signal} || : else return 1 fi } +fi # Start a "critical section", disable INT/TERM while in here and delay until # critical_end is called. diff --git a/test/trap_save.sh b/test/trap_save.sh index 461cddcf..6a4b18d5 100644 --- a/test/trap_save.sh +++ b/test/trap_save.sh @@ -3,6 +3,11 @@ . common.sh . ${SCRIPTPREFIX}/include/util.sh +builtin=0 +if [ "$(type trap_push 2>/dev/null)" = "trap_push is a shell builtin" ]; then + builtin=1 +fi + assert_traps() { local expected_file="$1" local extra="$2" @@ -87,6 +92,7 @@ EXPECTED_0=$(mktemp -ut trap_save) cp "${ORIGINAL}" "${EXPECTED_0}" trap_push INFO oact_info assert 0 $? "trap_push INFO" +[ ${builtin} -eq 0 ] && assert "-" "${oact_info}" "INFO had no trap so should be -" assert_traps "${EXPECTED_0}" "saved 0 traps should match" @@ -97,6 +103,7 @@ EXPECTED_1=$(mktemp -ut trap_save) awk '$NF != "INT"' "${ORIGINAL}" > "${EXPECTED_1}" trap_push INT oact_int assert 0 $? "trap_push INT" +[ ${builtin} -eq 0 ] && assert "${orig_intrap}" "${oact_int}" "INT trap should match" assert_traps "${EXPECTED_1}" "saved 1 traps should match" @@ -110,6 +117,7 @@ if [ ${sh_quotes_assignments} -eq 1 ]; then trap_push USR1 oact_usr1 assert 0 $? "trap_push USR1" assert 0 ${evalled_usr1} "trap_push USR1 should not have evalled it" +[ ${builtin} -eq 0 ] && assert $'$\'var="gotusr1"; evalled_usr1=1; [ -z $dokill ] && `kill -9 $$`; setvar "${var}" \\\'1\\\'\'' "${oact_usr1}" "USR1 trap should match" fi assert_traps "${EXPECTED_2}" "saved 2 traps should match" @@ -121,6 +129,7 @@ EXPECTED_3=$(mktemp -ut trap_save) awk '$NF != "INT" && $NF != "USR1" && $NF != "TERM"' "${ORIGINAL}" > "${EXPECTED_3}" trap_push TERM oact_term assert 0 $? "trap_push TERM" +[ ${builtin} -eq 0 ] && assert "''" "${oact_term}" "TERM trap should match" assert_traps "${EXPECTED_3}" "saved 3 traps should match" @@ -150,7 +159,7 @@ assert_traps "${CRITICAL}" "critical traps should match" echo "Restore 0 - bad INFO" cp "${CRITICAL}" "${EXPECTED_0}" trap_pop INFO "" -assert 1 $? "trap_pop INFO blank" +assert_not 0 $? "trap_pop INFO blank" trap assert_traps "${EXPECTED_0}" "restore 0 traps should match" |