Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/freebsd/poudriere.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Drewery <bryan@shatow.net>2018-02-04 04:36:47 +0300
committerBryan Drewery <bryan@shatow.net>2018-02-08 05:53:07 +0300
commit17a5084cbf5c43b6271f602fcebf1c15b5000696 (patch)
tree639fe3bcb73dd24ac5dd312cf2bcb7df7f17e170
parent700ad285a3abb2b06906bfaeabf32a9720a7df65 (diff)
Add trap_push/pop builtins
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.in22
-rw-r--r--external/sh/trap.c4
-rw-r--r--external/update_sh.sh2
-rw-r--r--src/libexec/poudriere/cachec/cachec.c10
-rw-r--r--src/libexec/poudriere/locked_mkdir/locked_mkdir.c6
-rw-r--r--src/libexec/poudriere/pwait/pwait.c2
-rw-r--r--src/poudriere-sh/builtins-poudriere.def2
-rw-r--r--src/poudriere-sh/helpers.c115
-rw-r--r--src/poudriere-sh/helpers.h16
-rw-r--r--src/poudriere-sh/traps.c124
-rw-r--r--src/share/poudriere/include/util.sh4
-rw-r--r--test/trap_save.sh11
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"