Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Cleanup traps a bit - attempt to handle weird uses in...



details:   https://anonhg.NetBSD.org/src/rev/a04efe92e326
branches:  trunk
changeset: 446379:a04efe92e326
user:      kre <kre%NetBSD.org@localhost>
date:      Mon Dec 03 06:43:19 2018 +0000

description:
Cleanup traps a bit - attempt to handle weird uses in traps, such
as traps that issue break/continue/return to cause the loop/function
executing when the trap occurred to break/continue/return, and
generating the correct exit code from the shell including when a
signal is caught, but the trap handler for it exits.

All that from FreeBSD.

Also make
        T=$(trap)
work as it is supposed to (also trap -p).

For now this is handled by the same technique as $(jobs) - rather
than clearing the traps in subshells, just mark them invalid, and
then whenever they're invalid, clear them before executing anything
other than the special blessed "trap" command.   Eventually we will
handle these using non-subshell command substitution instead (not
creating a subshell environ when the commands in a command-sub alter
nothing in the environment).

diffstat:

 bin/sh/eval.c |   27 ++++-
 bin/sh/eval.h |    9 +-
 bin/sh/main.c |    9 +-
 bin/sh/sh.1   |   22 +---
 bin/sh/trap.c |  282 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 bin/sh/trap.h |    9 +-
 6 files changed, 274 insertions(+), 84 deletions(-)

diffs (truncated from 710 to 300 lines):

diff -r ca870dea5a77 -r a04efe92e326 bin/sh/eval.c
--- a/bin/sh/eval.c     Mon Dec 03 06:42:25 2018 +0000
+++ b/bin/sh/eval.c     Mon Dec 03 06:43:19 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $   */
+/*     $NetBSD: eval.c,v 1.168 2018/12/03 06:43:19 kre Exp $   */
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)eval.c     8.9 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $");
+__RCSID("$NetBSD: eval.c,v 1.168 2018/12/03 06:43:19 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -87,8 +87,10 @@
 #endif
 
 
-STATIC enum skipstate evalskip;        /* != SKIPNONE if we are skipping commands */
-STATIC int skipcount;          /* number of levels to skip */
+STATIC struct skipsave s_k_i_p;
+#define        evalskip        (s_k_i_p.state)
+#define        skipcount       (s_k_i_p.count)
+
 STATIC int loopnest;           /* current loop nesting level */
 STATIC int funcnest;           /* depth of function calls */
 STATIC int builtin_flags;      /* evalcommand flags for builtins */
@@ -278,6 +280,8 @@
                next = NULL;
                CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n",
                    getpid(), n, NODETYPENAME(n->type), n->type, flags));
+               if (n->type != NCMD && traps_invalid)
+                       free_traps();
                switch (n->type) {
                case NSEMI:
                        evaltree(n->nbinary.ch1, sflags);
@@ -1026,6 +1030,9 @@
                        cmdentry.cmdtype = CMDBUILTIN;
        }
 
+       if (traps_invalid && cmdentry.cmdtype != CMDSPLBLTIN)
+               free_traps();
+
        /* Fork off a child process if necessary. */
        if (cmd->ncmd.backgnd || (have_traps() && (flags & EV_EXIT) != 0)
         || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
@@ -1376,6 +1383,18 @@
 }
 
 void
+save_skipstate(struct skipsave *p)
+{
+       *p = s_k_i_p;
+}
+
+void
+restore_skipstate(const struct skipsave *p)
+{
+       s_k_i_p = *p;
+}
+
+void
 stop_skipping(void)
 {
        evalskip = SKIPNONE;
diff -r ca870dea5a77 -r a04efe92e326 bin/sh/eval.h
--- a/bin/sh/eval.h     Mon Dec 03 06:42:25 2018 +0000
+++ b/bin/sh/eval.h     Mon Dec 03 06:43:19 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: eval.h,v 1.21 2018/08/19 11:16:13 kre Exp $    */
+/*     $NetBSD: eval.h,v 1.22 2018/12/03 06:43:19 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -66,7 +66,14 @@
       SKIPFILE         /* return in a dot command */
 };
 
+struct skipsave {
+       enum skipstate state;   /* skipping or not */
+       int count;              /* when break or continue, how many */
+};
+
 enum skipstate current_skipstate(void);
+void save_skipstate(struct skipsave *);
+void restore_skipstate(const struct skipsave *);
 void stop_skipping(void);      /* reset internal skipping state to SKIPNONE */
 
 /*
diff -r ca870dea5a77 -r a04efe92e326 bin/sh/main.c
--- a/bin/sh/main.c     Mon Dec 03 06:42:25 2018 +0000
+++ b/bin/sh/main.c     Mon Dec 03 06:43:19 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.77 2018/12/03 02:38:30 kre Exp $    */
+/*     $NetBSD: main.c,v 1.78 2018/12/03 06:43:19 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c     8.7 (Berkeley) 7/19/95";
 #else
-__RCSID("$NetBSD: main.c,v 1.77 2018/12/03 02:38:30 kre Exp $");
+__RCSID("$NetBSD: main.c,v 1.78 2018/12/03 06:43:19 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -378,7 +378,8 @@
        if (stoppedjobs())
                return 0;
        if (argc > 1)
-               exitstatus = number(argv[1]);
-       exitshell(exitstatus);
+               exitshell(number(argv[1]));
+       else
+               exitshell_savedstatus();
        /* NOTREACHED */
 }
diff -r ca870dea5a77 -r a04efe92e326 bin/sh/sh.1
--- a/bin/sh/sh.1       Mon Dec 03 06:42:25 2018 +0000
+++ b/bin/sh/sh.1       Mon Dec 03 06:43:19 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.209 2018/11/23 20:40:06 kre Exp $
+.\"    $NetBSD: sh.1,v 1.210 2018/12/03 06:43:19 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -3307,6 +3307,11 @@
 flag, trap prints the same information for the signals specified,
 or if none are given, for all signals, including those where the
 action is the default.
+These variants of the trap command may be executed in a sub-shell
+.Pq "such as in a command substitution" ,
+provided they appear as the sole, or first, command in that sub-shell,
+in which case the state of traps from the parent of that
+sub-shell is reported.
 .Pp
 Examples:
 .Pp
@@ -4371,21 +4376,6 @@
 to ensure that the filename is still valid after the input line has been
 processed.
 .Pp
-The
-.Ic trap
-command cannot usefully be used, yet, within a command substitution,
-to obtain the current trap values,
-as all command substitutions are currently executed within a
-sub-shell environment,
-and in sub-shells all non-ignored, non-default, traps are reset.
-As a workaround, it is possible to redirect output from
-.Dq trap
-or
-.Dq trap -p
-to a file, and then read the file later using the
-.Dq \&.
-command.
-.Pp
 Job control of compound statements (loops, etc) is a complete mess.
 .Pp
 Many, many, more.
diff -r ca870dea5a77 -r a04efe92e326 bin/sh/trap.c
--- a/bin/sh/trap.c     Mon Dec 03 06:42:25 2018 +0000
+++ b/bin/sh/trap.c     Mon Dec 03 06:43:19 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: trap.c,v 1.46 2018/10/28 18:26:52 kre Exp $    */
+/*     $NetBSD: trap.c,v 1.47 2018/12/03 06:43:19 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)trap.c     8.5 (Berkeley) 6/5/95";
 #else
-__RCSID("$NetBSD: trap.c,v 1.46 2018/10/28 18:26:52 kre Exp $");
+__RCSID("$NetBSD: trap.c,v 1.47 2018/12/03 06:43:19 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -45,6 +45,9 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <errno.h>
+
+#include <sys/resource.h>
 
 #include "shell.h"
 #include "main.h"
@@ -76,10 +79,17 @@
 #define S_RESET 5              /* temporary - to reset a hard ignored sig */
 
 
-char *trap[NSIG];              /* trap handler commands */
 MKINIT char sigmode[NSIG];     /* current value of signal */
-static volatile char gotsig[NSIG];/* indicates specified signal received */
-volatile int pendingsigs;      /* indicates some signal received */
+static volatile sig_atomic_t gotsig[NSIG];/* indicates specified signal received */
+volatile sig_atomic_t pendingsigs;     /* indicates some signal received */
+
+int traps_invalid;             /* in a subshell, but trap[] not yet cleared */
+static char * volatile trap[NSIG];     /* trap handler commands */
+static int in_dotrap;
+static int last_trapsig;
+
+static int exiting;            /* exitshell() has been done */
+static int exiting_status;     /* the status to use for exit() */
 
 static int getsigaction(int, sig_t *);
 STATIC const char *trap_signame(int);
@@ -161,12 +171,15 @@
 
        ap = argv + 1;
 
+       CTRACE(DBG_TRAP, ("trapcmd: "));
        if (argc == 2 && strcmp(*ap, "-l") == 0) {
+               CTRACE(DBG_TRAP, ("-l\n"));
                out1str("EXIT");
                printsignals(out1, 4);
                return 0;
        }
        if (argc == 2 && strcmp(*ap, "-") == 0) {
+               CTRACE(DBG_TRAP, ("-\n"));
                for (signo = 0; signo < NSIG; signo++) {
                        if (trap[signo] == NULL)
                                continue;
@@ -177,9 +190,11 @@
                                setsignal(signo, 0);
                        INTON;
                }
+               traps_invalid = 0;
                return 0;
        }
        if (argc >= 2 && strcmp(*ap, "-p") == 0) {
+               CTRACE(DBG_TRAP, ("-p "));
                printonly = 1;
                ap++;
                argc--;
@@ -193,6 +208,7 @@
        if (argc <= 1) {
                int count;
 
+               CTRACE(DBG_TRAP, ("*all*\n"));
                if (printonly) {
                        for (count = 0, signo = 0 ; signo < NSIG ; signo++)
                                if (trap[signo] == NULL) {
@@ -239,9 +255,13 @@
 
                return 0;
        }
+       CTRACE(DBG_TRAP, ("\n"));
 
        action = NULL;
 
+       if (!printonly && traps_invalid)
+               free_traps();
+
        if (!printonly && !is_number(*ap)) {
                if ((*ap)[0] == '-' && (*ap)[1] == '\0')
                        ap++;                   /* reset to default */
@@ -285,6 +305,11 @@
                if (action)
                        action = savestr(action);
 
+               VTRACE(DBG_TRAP, ("trap for %d from %s%s%s to %s%s%s\n", signo,
+                       trap[signo] ? "'" : "", trap[signo] ? trap[signo] : "-",
+                       trap[signo] ? "'" : "", action ?  "'" : "",
+                       action ? action : "-", action ?  "'" : ""));
+
                if (trap[signo])
                        ckfree(trap[signo]);
 
@@ -304,24 +329,40 @@
  * Takes one arg vfork, to tell it to not be destructive of
  * the parents variables.
  */
-
 void
 clear_traps(int vforked)
 {
-       char **tp;
+       char * volatile *tp;
 
-       for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+       VTRACE(DBG_TRAP, ("clear_traps(%d)\n", vforked));
+       if (!vforked)
+               traps_invalid = 1;
+
+       for (tp = &trap[1] ; tp < &trap[NSIG] ; tp++) {
                if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
                        INTOFF;
-                       if (!vforked) {
-                               ckfree(*tp);
-                               *tp = NULL;
-                       }
-                       if (tp != &trap[0])



Home | Main Index | Thread Index | Old Index