sh - Sync to FreeBSD d038ee76 part 1/2
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 7 Jun 2015 01:41:36 +0000 (18:41 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 7 Jun 2015 02:57:14 +0000 (19:57 -0700)
* Sync to FreeBSD d038ee76 25 Apr 2015.

65 files changed:
bin/sh/Makefile
bin/sh/TOUR
bin/sh/alias.c
bin/sh/alias.h
bin/sh/arith.h
bin/sh/arith_yacc.c
bin/sh/arith_yacc.h
bin/sh/arith_yylex.c
bin/sh/bltin/bltin.h
bin/sh/bltin/echo.c
bin/sh/builtins.def
bin/sh/cd.c
bin/sh/cd.h
bin/sh/error.c
bin/sh/error.h
bin/sh/eval.c
bin/sh/eval.h
bin/sh/exec.c
bin/sh/exec.h
bin/sh/expand.c
bin/sh/expand.h
bin/sh/funcs/cmv
bin/sh/funcs/dirs
bin/sh/funcs/login
bin/sh/funcs/newgrp
bin/sh/funcs/popd
bin/sh/funcs/pushd
bin/sh/funcs/suspend
bin/sh/histedit.c
bin/sh/input.c
bin/sh/input.h
bin/sh/jobs.c
bin/sh/jobs.h
bin/sh/mail.c
bin/sh/mail.h
bin/sh/main.c
bin/sh/main.h
bin/sh/memalloc.c
bin/sh/memalloc.h
bin/sh/miscbltin.c
bin/sh/mkbuiltins
bin/sh/mknodes.c
bin/sh/mksyntax.c
bin/sh/mktokens
bin/sh/myhistedit.h
bin/sh/mystring.c
bin/sh/mystring.h
bin/sh/nodes.c.pat
bin/sh/nodetypes
bin/sh/options.c
bin/sh/options.h
bin/sh/output.c
bin/sh/output.h
bin/sh/parser.c
bin/sh/parser.h
bin/sh/redir.c
bin/sh/redir.h
bin/sh/sh.1
bin/sh/shell.h
bin/sh/show.c
bin/sh/show.h
bin/sh/trap.c
bin/sh/trap.h
bin/sh/var.c
bin/sh/var.h

index 597039d..5d4ce9f 100644 (file)
@@ -1,5 +1,5 @@
-#      @(#)Makefile    8.4 (Berkeley) 5/5/95
-# $FreeBSD: head/bin/sh/Makefile 235927 2012-05-24 19:48:15Z marcel $
+# Makefile for /bin/sh
+#
 
 PROG=  sh
 INSTALLFLAGS= -S
index 6d180ed..e9bbe9b 100644 (file)
@@ -1,5 +1,5 @@
 #      @(#)TOUR        8.1 (Berkeley) 5/31/93
-# $FreeBSD: head/bin/sh/TOUR 253650 2013-07-25 15:08:41Z jilles $
+# $FreeBSD$
 
 NOTE -- This is the original TOUR paper distributed with ash and
 does not represent the current state of the shell.  It is provided anyway
index 7f8d78f..21f3f44 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)alias.c 8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/alias.c 242766 2012-11-08 13:33:48Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)alias.c    8.3 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <stdlib.h>
 #include "shell.h"
 #include "output.h"
@@ -63,18 +68,7 @@ setalias(const char *name, const char *val)
                if (equal(name, ap->name)) {
                        INTOFF;
                        ckfree(ap->val);
-                       /* See HACK below. */
-#ifdef notyet
                        ap->val = savestr(val);
-#else
-                       {
-                       size_t len = strlen(val);
-                       ap->val = ckmalloc(len + 2);
-                       memcpy(ap->val, val, len);
-                       ap->val[len] = ' ';
-                       ap->val[len+1] = '\0';
-                       }
-#endif
                        INTON;
                        return;
                }
@@ -83,34 +77,7 @@ setalias(const char *name, const char *val)
        INTOFF;
        ap = ckmalloc(sizeof (struct alias));
        ap->name = savestr(name);
-       /*
-        * XXX - HACK: in order that the parser will not finish reading the
-        * alias value off the input before processing the next alias, we
-        * dummy up an extra space at the end of the alias.  This is a crock
-        * and should be re-thought.  The idea (if you feel inclined to help)
-        * is to avoid alias recursions.  The mechanism used is: when
-        * expanding an alias, the value of the alias is pushed back on the
-        * input as a string and a pointer to the alias is stored with the
-        * string.  The alias is marked as being in use.  When the input
-        * routine finishes reading the string, it marks the alias not
-        * in use.  The problem is synchronization with the parser.  Since
-        * it reads ahead, the alias is marked not in use before the
-        * resulting token(s) is next checked for further alias sub.  The
-        * H A C K is that we add a little fluff after the alias value
-        * so that the string will not be exhausted.  This is a good
-        * idea ------- ***NOT***
-        */
-#ifdef notyet
        ap->val = savestr(val);
-#else /* hack */
-       {
-       size_t len = strlen(val);
-       ap->val = ckmalloc(len + 2);
-       memcpy(ap->val, val, len);
-       ap->val[len] = ' ';     /* fluff */
-       ap->val[len+1] = '\0';
-       }
-#endif
        ap->flag = 0;
        ap->next = *app;
        *app = ap;
@@ -202,14 +169,8 @@ comparealiases(const void *p1, const void *p2)
 static void
 printalias(const struct alias *a)
 {
-       char *p;
-
        out1fmt("%s=", a->name);
-       /* Don't print the space added above. */
-       p = a->val + strlen(a->val) - 1;
-       *p = '\0';
        out1qstr(a->val);
-       *p = ' ';
        out1c('\n');
 }
 
@@ -219,6 +180,7 @@ printaliases(void)
        int i, j;
        struct alias **sorted, *ap;
 
+       INTOFF;
        sorted = ckmalloc(aliases * sizeof(*sorted));
        j = 0;
        for (i = 0; i < ATABSIZE; i++)
@@ -226,23 +188,29 @@ printaliases(void)
                        if (*ap->name != '\0')
                                sorted[j++] = ap;
        qsort(sorted, aliases, sizeof(*sorted), comparealiases);
-       for (i = 0; i < aliases; i++)
+       for (i = 0; i < aliases; i++) {
                printalias(sorted[i]);
+               if (int_pending())
+                       break;
+       }
        ckfree(sorted);
+       INTON;
 }
 
 int
-aliascmd(int argc, char **argv)
+aliascmd(int argc __unused, char **argv __unused)
 {
        char *n, *v;
        int ret = 0;
        struct alias *ap;
 
-       if (argc == 1) {
+       nextopt("");
+
+       if (*argptr == NULL) {
                printaliases();
                return (0);
        }
-       while ((n = *++argv) != NULL) {
+       while ((n = *argptr++) != NULL) {
                if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
                        if ((ap = lookupalias(n, 0)) == NULL) {
                                warning("%s: not found", n);
index 434d6ce..546e91a 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)alias.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/alias.h 223060 2011-06-13 21:03:27Z jilles $
+ * $FreeBSD$
  */
 
 #define ALIASINUSE     1
index ca98289..30fc1cb 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  *
  *     @(#)arith.h     1.1 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/arith.h 223060 2011-06-13 21:03:27Z jilles $
+ * $FreeBSD$
  */
 
 #include "shell.h"
 
-#define        DIGITS(var)     (int)(3 + (2 + CHAR_BIT * sizeof((var))) / 3)
+#define DIGITS(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
 
 arith_t        arith(const char *);
 void   arith_lex_reset(void);
index 695ad37..5000c6b 100644 (file)
  * 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.
- *
- * $FreeBSD: head/bin/sh/arith_yacc.c 230530 2012-01-25 08:42:19Z charnier $
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <limits.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -41,7 +42,6 @@
 #include <stdio.h>
 #include "arith.h"
 #include "arith_yacc.h"
-#include "builtins.h"
 #include "expand.h"
 #include "shell.h"
 #include "error.h"
@@ -84,15 +84,15 @@ static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
 
 #define ARITH_MAX_PREC 8
 
-static __dead2 void
-yyerror(const char *s)
+int letcmd(int, char **);
+
+static __dead2 void yyerror(const char *s)
 {
        error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
        /* NOTREACHED */
 }
 
-static arith_t
-arith_lookupvarint(char *varname)
+static arith_t arith_lookupvarint(char *varname)
 {
        const char *str;
        char *p;
@@ -110,20 +110,17 @@ arith_lookupvarint(char *varname)
        return result;
 }
 
-static inline int
-arith_prec(int op)
+static inline int arith_prec(int op)
 {
        return prec[op - ARITH_BINOP_MIN];
 }
 
-static inline int
-higher_prec(int op1, int op2)
+static inline int higher_prec(int op1, int op2)
 {
        return arith_prec(op1) < arith_prec(op2);
 }
 
-static arith_t
-do_binop(int op, arith_t a, arith_t b)
+static arith_t do_binop(int op, arith_t a, arith_t b)
 {
 
        switch (op) {
@@ -142,9 +139,9 @@ do_binop(int op, arith_t a, arith_t b)
        case ARITH_SUB:
                return (uintmax_t)a - (uintmax_t)b;
        case ARITH_LSHIFT:
-               return a << b;
+               return (uintmax_t)a << (b & (sizeof(uintmax_t) * CHAR_BIT - 1));
        case ARITH_RSHIFT:
-               return a >> b;
+               return a >> (b & (sizeof(uintmax_t) * CHAR_BIT - 1));
        case ARITH_LT:
                return a < b;
        case ARITH_LE:
@@ -168,8 +165,7 @@ do_binop(int op, arith_t a, arith_t b)
 
 static arith_t assignment(int var, int noeval);
 
-static arith_t
-primary(int token, union yystype *val, int op, int noeval)
+static arith_t primary(int token, union yystype *val, int op, int noeval)
 {
        arith_t result;
 
@@ -206,8 +202,7 @@ again:
        }
 }
 
-static arith_t
-binop2(arith_t a, int op, int precedence, int noeval)
+static arith_t binop2(arith_t a, int op, int precedence, int noeval)
 {
        for (;;) {
                union yystype val;
@@ -237,8 +232,7 @@ binop2(arith_t a, int op, int precedence, int noeval)
        }
 }
 
-static arith_t
-binop(int token, union yystype *val, int op, int noeval)
+static arith_t binop(int token, union yystype *val, int op, int noeval)
 {
        arith_t a = primary(token, val, op, noeval);
 
@@ -249,8 +243,7 @@ binop(int token, union yystype *val, int op, int noeval)
        return binop2(a, op, ARITH_MAX_PREC, noeval);
 }
 
-static arith_t
-and(int token, union yystype *val, int op, int noeval)
+static arith_t and(int token, union yystype *val, int op, int noeval)
 {
        arith_t a = binop(token, val, op, noeval);
        arith_t b;
@@ -267,8 +260,7 @@ and(int token, union yystype *val, int op, int noeval)
        return a && b;
 }
 
-static arith_t
-or(int token, union yystype *val, int op, int noeval)
+static arith_t or(int token, union yystype *val, int op, int noeval)
 {
        arith_t a = and(token, val, op, noeval);
        arith_t b;
@@ -285,8 +277,7 @@ or(int token, union yystype *val, int op, int noeval)
        return a || b;
 }
 
-static arith_t
-cond(int token, union yystype *val, int op, int noeval)
+static arith_t cond(int token, union yystype *val, int op, int noeval)
 {
        arith_t a = or(token, val, op, noeval);
        arith_t b;
@@ -308,8 +299,7 @@ cond(int token, union yystype *val, int op, int noeval)
        return a ? b : c;
 }
 
-static arith_t
-assignment(int var, int noeval)
+static arith_t assignment(int var, int noeval)
 {
        union yystype val = yylval;
        int op = yylex();
@@ -333,8 +323,7 @@ assignment(int var, int noeval)
        return result;
 }
 
-arith_t
-arith(const char *s)
+arith_t arith(const char *s)
 {
        struct stackmark smark;
        arith_t result;
@@ -390,4 +379,3 @@ letcmd(int argc, char **argv)
        out1fmt(ARITH_FORMAT_STR "\n", i);
        return !i;
 }
-
index 5ea7f97..ca92e6f 100644 (file)
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/bin/sh/arith_yacc.h 218466 2011-02-08 23:18:06Z jilles $
+ * $FreeBSD$
  */
 
 #define ARITH_ASS 1
@@ -81,6 +81,8 @@
 #define ARITH_QMARK 37
 #define ARITH_COLON 38
 
+extern const char *arith_buf;
+
 union yystype {
        arith_t val;
        char *name;
index 232d360..f7eaf3e 100644 (file)
  * 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.
- *
- * $FreeBSD: head/bin/sh/arith_yylex.c 230530 2012-01-25 08:42:19Z charnier $
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
@@ -49,8 +50,6 @@
 #error Arithmetic tokens are out of order.
 #endif
 
-extern const char *arith_buf;
-
 int
 yylex(void)
 {
@@ -217,9 +216,13 @@ checkeqcur:
                        value += ARITH_REM - '%';
                        goto checkeq;
                case '+':
+                       if (buf[1] == '+')
+                               return ARITH_BAD;
                        value += ARITH_ADD - '+';
                        goto checkeq;
                case '-':
+                       if (buf[1] == '-')
+                               return ARITH_BAD;
                        value += ARITH_SUB - '-';
                        goto checkeq;
                case '~':
index b0ea6b3..a530ab7 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)bltin.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/bltin/bltin.h 223060 2011-06-13 21:03:27Z jilles $
+ * $FreeBSD$
  */
 
 /*
@@ -46,6 +42,7 @@
 #include "../shell.h"
 #include "../mystring.h"
 #ifdef SHELL
+#include "../error.h"
 #include "../output.h"
 #include "builtins.h"
 #define FILE struct output
@@ -66,6 +63,7 @@
 #define warnx warning
 #define warn(fmt, ...) warning(fmt ": %s", __VA_ARGS__, strerror(errno))
 #define errx(exitstatus, ...) error(__VA_ARGS__)
+
 #else
 #undef NULL
 #include <stdio.h>
@@ -75,6 +73,7 @@
 
 #include <unistd.h>
 
-pid_t getjobpgrp(char *);
+pointer stalloc(int);
+int killjob(const char *, int);
 
 extern char *commandname;
index c109be8..457a4c7 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  *
  *     @(#)echo.c      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/bltin/echo.c 127958 2004-04-06 20:06:54Z markm $
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * Echo command.
  */
index fbbf5c6..1cbeea9 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)builtins.def        8.4 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/builtins.def 222386 2011-05-27 20:53:07Z jilles $
+# $FreeBSD$
 
 #
 # This file lists all the builtin commands.  The first column is the name
@@ -66,6 +62,7 @@ execcmd               -s exec
 exitcmd                -s exit
 letcmd         let
 exportcmd      -s export -s readonly
+#exprcmd               expr
 falsecmd       false
 fgcmd -j       fg
 getoptscmd     getopts
index 2fee21e..88f03f5 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)cd.c    8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/cd.c 240541 2012-09-15 21:56:30Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cd.c       8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdlib.h>
@@ -117,7 +122,7 @@ cdcmd(int argc __unused, char **argv __unused)
            (dest[0] == '.' && (dest[1] == '/' || dest[1] == '\0')) ||
            (dest[0] == '.' && dest[1] == '.' && (dest[2] == '/' || dest[2] == '\0')) ||
            (path = bltinlookup("CDPATH", 1)) == NULL)
-               path = nullstr;
+               path = "";
        while ((p = padvance(&path, dest)) != NULL) {
                if (stat(p, &statb) < 0) {
                        if (errno != ENOENT)
@@ -184,8 +189,7 @@ cdlogical(char *dest)
         *  next time we get the value of the current directory.
         */
        badstat = 0;
-       cdcomppath = stalloc(strlen(dest) + 1);
-       scopy(dest, cdcomppath);
+       cdcomppath = stsavestr(dest);
        STARTSTACKSTR(p);
        if (*dest == '/') {
                STPUTC('/', p);
@@ -278,8 +282,7 @@ findcwd(char *dir)
         */
        if (dir == NULL || curdir == NULL)
                return getpwd2();
-       cdcomppath = stalloc(strlen(dir) + 1);
-       scopy(dir, cdcomppath);
+       cdcomppath = stsavestr(dir);
        STARTSTACKSTR(new);
        if (*dir != '/') {
                STPUTS(curdir, new);
index 3eaf3f5..91fbc2b 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -30,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/bin/sh/cd.h 223060 2011-06-13 21:03:27Z jilles $
+ * $FreeBSD$
  */
 
 void    pwd_init(int);
index c9d5053..6057226 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)error.c 8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/error.c 216622 2010-12-21 20:47:06Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)error.c    8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * Errors and exceptions.
  */
 
 #include "shell.h"
+#include "eval.h"
 #include "main.h"
 #include "options.h"
 #include "output.h"
 #include "error.h"
-#include "eval.h"  /* defines commandname */
 #include "nodes.h" /* show.h needs nodes.h */
 #include "show.h"
 #include "trap.h"
@@ -85,13 +90,14 @@ exraise(int e)
 
 
 /*
- * Called from trap.c when a SIGINT is received.  (If the user specifies
- * that SIGINT is to be trapped or ignored using the trap builtin, then
- * this routine is not called.)  Suppressint is nonzero when interrupts
- * are held using the INTOFF macro.  If SIGINTs are not suppressed and
- * the shell is not a root shell, then we want to be terminated if we
- * get here, as if we were terminated directly by a SIGINT.  Arrange for
- * this here.
+ * Called from trap.c when a SIGINT is received and not suppressed, or when
+ * an interrupt is pending and interrupts are re-enabled using INTON.
+ * (If the user specifies that SIGINT is to be trapped or ignored using the
+ * trap builtin, then this routine is not called.)  Suppressint is nonzero
+ * when interrupts are held using the INTOFF macro.  If SIGINTs are not
+ * suppressed and the shell is not a root shell, then we want to be
+ * terminated if we get here, as if we were terminated directly by a SIGINT.
+ * Arrange for this here.
  */
 
 void
@@ -99,16 +105,6 @@ onint(void)
 {
        sigset_t sigs;
 
-       /*
-        * The !in_dotrap here is safe.  The only way we can arrive here
-        * with in_dotrap set is that a trap handler set SIGINT to SIG_DFL
-        * and killed itself.
-        */
-
-       if (suppressint && !in_dotrap) {
-               intpending++;
-               return;
-       }
        intpending = 0;
        sigemptyset(&sigs);
        sigprocmask(SIG_SETMASK, &sigs, NULL);
@@ -125,6 +121,7 @@ onint(void)
        else {
                signal(SIGINT, SIG_DFL);
                kill(getpid(), SIGINT);
+               _exit(128 + SIGINT);
        }
 }
 
@@ -134,6 +131,8 @@ vwarning(const char *msg, va_list ap)
 {
        if (commandname)
                outfmt(out2, "%s: ", commandname);
+       else if (arg0)
+               outfmt(out2, "%s: ", arg0);
        doformat(out2, msg, ap);
        out2fmt_flush("\n");
 }
index 63d2033..a60b1fa 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)error.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/error.h 220978 2011-04-23 22:28:56Z jilles $
+ * $FreeBSD$
  */
 
 /*
@@ -79,11 +75,12 @@ extern volatile sig_atomic_t intpending;
 #define is_int_on() suppressint
 #define SETINTON(s) suppressint = (s)
 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
+#define SET_PENDING_INT intpending = 1
 #define CLEAR_PENDING_INT intpending = 0
 #define int_pending() intpending
 
 void exraise(int) __dead2;
-void onint(void);
+void onint(void) __dead2;
 void warning(const char *, ...) __printflike(1, 2);
 void error(const char *, ...) __printf0like(1, 2) __dead2;
 void exerror(int, const char *, ...) __printf0like(2, 3) __dead2;
index 8f9a017..a4823cc 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)eval.c  8.9 (Berkeley) 6/8/95
- * $FreeBSD: head/bin/sh/eval.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h> /* For WIFSIGNALED(status) */
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)eval.c     8.9 (Berkeley) 6/8/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <errno.h>
 #include <paths.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/resource.h>
+#include <sys/wait.h> /* For WIFSIGNALED(status) */
+#include <errno.h>
 
 /*
  * Evaluate a command.
@@ -78,7 +81,7 @@ int funcnest;                 /* depth of function calls */
 static int builtin_flags;      /* evalcommand flags for builtins */
 
 
-const char *commandname;
+char *commandname;
 struct strlist *cmdenviron;
 int exitstatus;                        /* exit status of last command */
 int oexitstatus;               /* saved exit status */
@@ -106,7 +109,6 @@ reseteval(void)
 {
        evalskip = 0;
        loopnest = 0;
-       funcnest = 0;
 }
 
 
@@ -147,7 +149,7 @@ evalcmd(int argc, char **argv)
  */
 
 void
-evalstring(char *s, int flags)
+evalstring(const char *s, int flags)
 {
        union node *n;
        struct stackmark smark;
@@ -166,6 +168,8 @@ evalstring(char *s, int flags)
                        else
                                evaltree(n, flags);
                        any = 1;
+                       if (evalskip)
+                               break;
                }
                popstackmark(&smark);
                setstackmark(&smark);
@@ -283,7 +287,7 @@ evaltree(union node *n, int flags)
                        do_etest = !(flags & EV_TESTED);
                        break;
                case NCMD:
-                       evalcommand(n, flags, NULL);
+                       evalcommand(n, flags, (struct backcmd *)NULL);
                        do_etest = !(flags & EV_TESTED);
                        break;
                default:
@@ -314,15 +318,16 @@ evalloop(union node *n, int flags)
        loopnest++;
        status = 0;
        for (;;) {
+               if (!evalskip)
                evaltree(n->nbinary.ch1, EV_TESTED);
                if (evalskip) {
-skipping:        if (evalskip == SKIPCONT && --skipcount <= 0) {
+                       if (evalskip == SKIPCONT && --skipcount <= 0) {
                                evalskip = 0;
                                continue;
                        }
                        if (evalskip == SKIPBREAK && --skipcount <= 0)
                                evalskip = 0;
-                       if (evalskip == SKIPFUNC || evalskip == SKIPFILE)
+                       if (evalskip == SKIPRETURN)
                                status = exitstatus;
                        break;
                }
@@ -335,8 +340,6 @@ skipping:     if (evalskip == SKIPCONT && --skipcount <= 0) {
                }
                evaltree(n->nbinary.ch2, flags);
                status = exitstatus;
-               if (evalskip)
-                       goto skipping;
        }
        loopnest--;
        exitstatus = status;
@@ -438,7 +441,7 @@ evalsubshell(union node *n, int flags)
                evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
        } else if (!backgnd) {
                INTOFF;
-               exitstatus = waitforjob(jp, NULL);
+               exitstatus = waitforjob(jp, (int *)NULL);
                INTON;
        } else
                exitstatus = 0;
@@ -495,7 +498,7 @@ exphere(union node *redir, struct arglist *fn)
        struct localvar *savelocalvars;
        int need_longjmp = 0;
 
-       redir->nhere.expdoc = nullstr;
+       redir->nhere.expdoc = "";
        savelocalvars = localvars;
        localvars = NULL;
        forcelocal++;
@@ -536,13 +539,13 @@ expredir(union node *n)
                case NFROMTO:
                case NAPPEND:
                case NCLOBBER:
-                       expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+                       expandarg(redir->nfile.fname, &fn, EXP_TILDE);
                        redir->nfile.expfname = fn.list->text;
                        break;
                case NFROMFD:
                case NTOFD:
                        if (redir->ndup.vname) {
-                               expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
+                               expandarg(redir->ndup.vname, &fn, EXP_TILDE);
                                fixredir(redir, fn.list->text, 1);
                        }
                        break;
@@ -613,7 +616,7 @@ evalpipe(union node *n)
        INTON;
        if (n->npipe.backgnd == 0) {
                INTOFF;
-               exitstatus = waitforjob(jp, NULL);
+               exitstatus = waitforjob(jp, (int *)NULL);
                TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
                INTON;
        } else
@@ -646,15 +649,15 @@ evalbackcmd(union node *n, struct backcmd *result)
        struct jmploc *savehandler;
        struct localvar *savelocalvars;
 
-       setstackmark(&smark);
        result->fd = -1;
        result->buf = NULL;
        result->nleft = 0;
        result->jp = NULL;
        if (n == NULL) {
                exitstatus = 0;
-               goto out;
+               return;
        }
+       setstackmark(&smark);
        exitstatus = oexitstatus;
        if (is_valid_fast_cmdsubst(n)) {
                savelocalvars = localvars;
@@ -696,7 +699,6 @@ evalbackcmd(union node *n, struct backcmd *result)
                result->fd = pip[0];
                result->jp = jp;
        }
-out:
        popstackmark(&smark);
        TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
                result->fd, result->buf, result->nleft, result->jp));
@@ -748,6 +750,37 @@ isdeclarationcmd(struct narg *arg)
                (have_command || !isfunc("local"))));
 }
 
+static void
+xtracecommand(struct arglist *varlist, struct arglist *arglist)
+{
+       struct strlist *sp;
+       char sep = 0;
+       const char *p, *ps4;
+
+       ps4 = expandstr(ps4val());
+       out2str(ps4 != NULL ? ps4 : ps4val());
+       for (sp = varlist->list ; sp ; sp = sp->next) {
+               if (sep != 0)
+                       out2c(' ');
+               p = strchr(sp->text, '=');
+               if (p != NULL) {
+                       p++;
+                       outbin(sp->text, p - sp->text, out2);
+                       out2qstr(p);
+               } else
+                       out2qstr(sp->text);
+               sep = ' ';
+       }
+       for (sp = arglist->list ; sp ; sp = sp->next) {
+               if (sep != 0)
+                       out2c(' ');
+               out2qstr(sp->text);
+               sep = ' ';
+       }
+       out2c('\n');
+       flushout(&errout);
+}
+
 /*
  * Check if a builtin can safely be executed in the same process,
  * even though it should be in a subshell (command substitution).
@@ -780,31 +813,30 @@ safe_builtin(int idx, int argc, char **argv)
  */
 
 static void
-evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
+evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 {
        union node *argp;
        struct arglist arglist;
        struct arglist varlist;
-       volatile int flags = flgs;
-       char **volatile argv;
-       volatile int argc;
+       char **argv;
+       int argc;
        char **envp;
        int varflag;
        struct strlist *sp;
        int mode;
        int pip[2];
        struct cmdentry cmdentry;
-       struct job *volatile jp;
+       struct job *jp;
        struct jmploc jmploc;
        struct jmploc *savehandler;
-       const char *savecmdname;
+       char *savecmdname;
        struct shparam saveparam;
        struct localvar *savelocalvars;
        struct parsefile *savetopfile;
        volatile int e;
-       char *volatile lastarg;
+       char *lastarg;
        int realstatus;
-       volatile int do_clearcmdentry;
+       int do_clearcmdentry;
        const char *path = pathval();
 
        /* First expand the arguments. */
@@ -846,40 +878,8 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
        argv -= argc;
 
        /* Print the command if xflag is set. */
-       if (xflag) {
-               char sep = 0;
-               const char *p, *ps4;
-               ps4 = expandstr(ps4val());
-               out2str(ps4 != NULL ? ps4 : ps4val());
-               for (sp = varlist.list ; sp ; sp = sp->next) {
-                       if (sep != 0)
-                               out2c(' ');
-                       p = strchr(sp->text, '=');
-                       if (p != NULL) {
-                               p++;
-                               outbin(sp->text, p - sp->text, out2);
-                               out2qstr(p);
-                       } else
-                               out2qstr(sp->text);
-                       sep = ' ';
-               }
-               for (sp = arglist.list ; sp ; sp = sp->next) {
-                       if (sep != 0)
-                               out2c(' ');
-                       /* Disambiguate command looking like assignment. */
-                       if (sp == arglist.list &&
-                                       strchr(sp->text, '=') != NULL &&
-                                       strchr(sp->text, '\'') == NULL) {
-                               out2c('\'');
-                               out2str(sp->text);
-                               out2c('\'');
-                       } else
-                               out2qstr(sp->text);
-                       sep = ' ';
-               }
-               out2c('\n');
-               flushout(&errout);
-       }
+       if (xflag)
+               xtracecommand(&varlist, &arglist);
 
        /* Now locate the command. */
        if (argc == 0) {
@@ -1031,6 +1031,7 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
                shellparam.reset = 1;
                shellparam.nparam = argc - 1;
                shellparam.p = argv + 1;
+               shellparam.optp = NULL;
                shellparam.optnext = NULL;
                INTOFF;
                savelocalvars = localvars;
@@ -1067,7 +1068,7 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
                funcnest--;
                popredir();
                INTON;
-               if (evalskip == SKIPFUNC) {
+               if (evalskip == SKIPRETURN) {
                        evalskip = 0;
                        skipcount = 0;
                }
@@ -1242,8 +1243,16 @@ bltincmd(int argc, char **argv)
 int
 breakcmd(int argc, char **argv)
 {
-       int n = argc > 1 ? number(argv[1]) : 1;
+       long n;
+       char *end;
 
+       if (argc > 1) {
+               /* Allow arbitrarily large numbers. */
+               n = strtol(argv[1], &end, 10);
+               if (!is_digit(argv[1][0]) || *end != '\0')
+                       error("Illegal number: %s", argv[1]);
+       } else
+               n = 1;
        if (n > loopnest)
                n = loopnest;
        if (n > 0) {
@@ -1291,7 +1300,7 @@ commandcmd(int argc __unused, char **argv __unused)
         * Do nothing successfully if no command was specified;
         * ksh also does this.
         */
-       return(0);
+       return 0;
 }
 
 
@@ -1304,14 +1313,8 @@ returncmd(int argc, char **argv)
 {
        int ret = argc > 1 ? number(argv[1]) : oexitstatus;
 
-       if (funcnest) {
-               evalskip = SKIPFUNC;
-               skipcount = 1;
-       } else {
-               /* skip the rest of the file */
-               evalskip = SKIPFILE;
+       evalskip = SKIPRETURN;
                skipcount = 1;
-       }
        return ret;
 }
 
index e9eaf1f..d4092be 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  *
  *     @(#)eval.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/eval.h 253650 2013-07-25 15:08:41Z jilles $
+ * $FreeBSD$
  */
 
-extern const char *commandname;        /* currently executing command */
+extern char *commandname;      /* currently executing command */
 extern int exitstatus;         /* exit status of last command */
 extern int oexitstatus;                /* saved exit status */
 extern struct strlist *cmdenviron;  /* environment for builtin command */
@@ -57,7 +53,7 @@ void reseteval(void);
 #define EV_TESTED 02           /* exit status is checked; ignore -e flag */
 #define EV_BACKCMD 04          /* command executing within back quotes */
 
-void evalstring(char *, int);
+void evalstring(const char *, int);
 union node;    /* BLETCH for ansi C */
 void evaltree(union node *, int);
 void evalbackcmd(union node *, struct backcmd *);
@@ -71,5 +67,4 @@ extern int skipcount;
 /* reasons for skipping commands (see comment on breakcmd routine) */
 #define SKIPBREAK      1
 #define SKIPCONT       2
-#define SKIPFUNC       3
-#define SKIPFILE       4
+#define SKIPRETURN     3
index b27e2a6..7e15b31 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)exec.c  8.4 (Berkeley) 6/8/95
- * $FreeBSD: head/bin/sh/exec.c 253650 2013-07-25 15:08:41Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)exec.c     8.4 (Berkeley) 6/8/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -95,6 +100,8 @@ static struct tblentry *cmdlookup(const char *, int);
 static void delete_cmd_entry(void);
 static void addcmdentry(const char *, struct cmdentry *);
 
+
+
 /*
  * Exec a program.  Never returns.  If you change this routine, you may
  * have to change the find_command routine as well.
@@ -180,14 +187,15 @@ padvance(const char **path, const char *name)
 {
        const char *p, *start;
        char *q;
-       size_t len;
+       size_t len, namelen;
 
        if (*path == NULL)
                return NULL;
        start = *path;
        for (p = start; *p && *p != ':' && *p != '%'; p++)
                ; /* nothing */
-       len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
+       namelen = strlen(name);
+       len = p - start + namelen + 2;  /* "2" is for '/' and '\0' */
        STARTSTACKSTR(q);
        CHECKSTRSPACE(len, q);
        if (p != start) {
@@ -195,7 +203,7 @@ padvance(const char **path, const char *name)
                q += p - start;
                *q++ = '/';
        }
-       strcpy(q, name);
+       memcpy(q, name, namelen + 1);
        pathopt = NULL;
        if (*p == '%') {
                pathopt = ++p;
@@ -354,15 +362,13 @@ find_command(const char *name, struct cmdentry *entry, int act,
 
        e = ENOENT;
        idx = -1;
-loop:
-       while ((fullname = padvance(&path, name)) != NULL) {
-               stunalloc(fullname);
+       for (;(fullname = padvance(&path, name)) != NULL; stunalloc(fullname)) {
                idx++;
                if (pathopt) {
-                       if (prefix("func", pathopt)) {
+                       if (strncmp(pathopt, "func", 4) == 0) {
                                /* handled below */
                        } else {
-                               goto loop;      /* ignore unimplemented options */
+                               continue; /* ignore unimplemented options */
                        }
                }
                if (fullname[0] != '/')
@@ -370,13 +376,12 @@ loop:
                if (stat(fullname, &statb) < 0) {
                        if (errno != ENOENT && errno != ENOTDIR)
                                e = errno;
-                       goto loop;
+                       continue;
                }
                e = EACCES;     /* if we fail, this will be the error */
                if (!S_ISREG(statb.st_mode))
-                       goto loop;
+                       continue;
                if (pathopt) {          /* this is a %func directory */
-                       stalloc(strlen(fullname) + 1);
                        readcmdfile(fullname);
                        if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
                                error("%s not defined in %s", name, fullname);
@@ -397,6 +402,7 @@ loop:
 #endif
                TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
                INTOFF;
+               stunalloc(fullname);
                cmdp = cmdlookup(name, 1);
                if (cmdp->cmdtype == CMDFUNCTION)
                        cmdp = &loc_cmd;
@@ -417,14 +423,11 @@ loop:
        return;
 
 success:
-       if (cmdp) {
                if (cd)
                        cmdtable_cd = 1;
                entry->cmdtype = cmdp->cmdtype;
                entry->u = cmdp->param;
                entry->special = cmdp->special;
-       } else
-               entry->cmdtype = CMDUNKNOWN;
 }
 
 
@@ -523,6 +526,7 @@ cmdlookup(const char *name, int add)
        const char *p;
        struct tblentry *cmdp;
        struct tblentry **pp;
+       size_t len;
 
        p = name;
        hashval = *p << 4;
@@ -537,11 +541,11 @@ cmdlookup(const char *name, int add)
        }
        if (add && cmdp == NULL) {
                INTOFF;
-               cmdp = *pp = ckmalloc(sizeof (struct tblentry)
-                                       + strlen(name) + 1);
+               len = strlen(name);
+               cmdp = *pp = ckmalloc(sizeof (struct tblentry) + len + 1);
                cmdp->next = NULL;
                cmdp->cmdtype = CMDUNKNOWN;
-               strcpy(cmdp->cmdname, name);
+               memcpy(cmdp->cmdname, name, len + 1);
                INTON;
        }
        lastcmdentry = pp;
@@ -606,6 +610,7 @@ defun(const char *name, union node *func)
 
 /*
  * Delete a function if it exists.
+ * Called with interrupts off.
  */
 
 int
@@ -616,6 +621,7 @@ unsetfunc(const char *name)
        if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
                unreffunc(cmdp->param.func);
                delete_cmd_entry();
+               return (0);
        }
        return (0);
 }
@@ -646,7 +652,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
        const char * const *pp;
        struct alias *ap;
        int i;
-       int err = 0;
+       int error1 = 0;
 
        if (path != pathval())
                clearcmdentry();
@@ -667,9 +673,11 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
 
                /* Then look at the aliases */
                if ((ap = lookupalias(argv[i], 1)) != NULL) {
-                       if (cmd == TYPECMD_SMALLV)
-                               out1fmt("alias %s='%s'\n", argv[i], ap->val);
-                       else
+                       if (cmd == TYPECMD_SMALLV) {
+                               out1fmt("alias %s=", argv[i]);
+                               out1qstr(ap->val);
+                               outcslow('\n', out1);
+                       } else
                                out1fmt("%s is an alias for %s\n", argv[i],
                                    ap->val);
                        continue;
@@ -704,7 +712,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
                                                " a tracked alias for" : "",
                                            name);
                        } else {
-                               if (access(argv[i], X_OK) == 0) {
+                               if (eaccess(argv[i], X_OK) == 0) {
                                        if (cmd == TYPECMD_SMALLV)
                                                out1fmt("%s\n", argv[i]);
                                        else
@@ -714,7 +722,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
                                        if (cmd != TYPECMD_SMALLV)
                                                outfmt(out2, "%s: %s\n",
                                                    argv[i], strerror(errno));
-                                       err |= 127;
+                                       error1 |= 127;
                                }
                        }
                        break;
@@ -739,7 +747,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
                default:
                        if (cmd != TYPECMD_SMALLV)
                                outfmt(out2, "%s: not found\n", argv[i]);
-                       err |= 127;
+                       error1 |= 127;
                        break;
                }
        }
@@ -747,7 +755,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
        if (path != pathval())
                clearcmdentry();
 
-       return err;
+       return error1;
 }
 
 /*
@@ -757,5 +765,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
 int
 typecmd(int argc, char **argv)
 {
+       if (argc > 2 && strcmp(argv[1], "--") == 0)
+               argc--, argv++;
        return typecmd_impl(argc, argv, TYPECMD_TYPE, bltinlookup("PATH", 1));
 }
index 546ad53..b57b2d5 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)exec.h      8.3 (Berkeley) 6/8/95
- * $FreeBSD: head/bin/sh/exec.h 238468 2012-07-15 10:19:43Z jilles $
+ * $FreeBSD$
  */
 
 /* values of cmdtype */
index cbe4b62..3de1eea 100644 (file)
@@ -15,7 +15,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)expand.c        8.5 (Berkeley) 5/15/95
- * $FreeBSD: head/bin/sh/expand.c 248980 2013-04-01 17:18:22Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)expand.c   8.5 (Berkeley) 5/15/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/stat.h>
@@ -93,17 +98,19 @@ static struct ifsregion ifsfirst;   /* first struct in list of ifs regions */
 static struct ifsregion *ifslastp;     /* last struct in list */
 static struct arglist exparg;          /* holds expanded arg list */
 
-static void argstr(char *, int);
+static char *argstr(char *, int);
 static char *exptilde(char *, int);
+static char *expari(char *);
 static void expbackq(union node *, int, int);
 static int subevalvar(char *, char *, int, int, int, int, int);
 static char *evalvar(char *, int);
-static int varisset(char *, int);
-static void varvalue(char *, int, int, int);
+static int varisset(const char *, int);
+static void strtodest(const char *, int, int, int);
+static void varvalue(const char *, int, int, int);
 static void recordregion(int, int, int);
 static void removerecordregions(int);
 static void ifsbreakup(char *, struct arglist *);
-static void expandmeta(struct strlist *, int);
+static void expandmeta(struct strlist *);
 static void expmeta(char *, char *);
 static void addfname(char *);
 static struct strlist *expsort(struct strlist *);
@@ -165,17 +172,12 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
        STPUTC('\0', expdest);
        p = grabstackstr(expdest);
        exparg.lastp = &exparg.list;
-       /*
-        * TODO - EXP_REDIR
-        */
        if (flag & EXP_FULL) {
                ifsbreakup(p, &exparg);
                *exparg.lastp = NULL;
                exparg.lastp = &exparg.list;
-               expandmeta(exparg.list, flag);
+               expandmeta(exparg.list);
        } else {
-               if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
-                       rmescapes(p);
                sp = (struct strlist *)stalloc(sizeof (struct strlist));
                sp->text = p;
                *exparg.lastp = sp;
@@ -201,17 +203,17 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
 /*
  * Perform parameter expansion, command substitution and arithmetic
  * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
- * Processing ends at a CTLENDVAR character as well as '\0'.
+ * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'.
  * This is used to expand word in ${var+word} etc.
- * If EXP_FULL, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC
+ * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC
  * characters to allow for further processing.
  * If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
  */
-static void
+static char *
 argstr(char *p, int flag)
 {
        char c;
-       int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);  /* do CTLESC */
+       int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
        int firsteq = 1;
        int split_lit;
        int lit_quoted;
@@ -225,8 +227,10 @@ argstr(char *p, int flag)
                CHECKSTRSPACE(2, expdest);
                switch (c = *p++) {
                case '\0':
+                       return (p - 1);
                case CTLENDVAR:
-                       goto breakloop;
+               case CTLENDARI:
+                       return (p);
                case CTLQUOTEMARK:
                        lit_quoted = 1;
                        /* "$@" syntax adherence hack */
@@ -256,8 +260,8 @@ argstr(char *p, int flag)
                        expbackq(argbackq->n, c & CTLQUOTE, flag);
                        argbackq = argbackq->next;
                        break;
-               case CTLENDARI:
-                       expari(flag);
+               case CTLARI:
+                       p = expari(p);
                        break;
                case ':':
                case '=':
@@ -283,7 +287,6 @@ argstr(char *p, int flag)
                                    expdest - stackblock(), 0);
                }
        }
-breakloop:;
 }
 
 /*
@@ -296,9 +299,9 @@ exptilde(char *p, int flag)
        char c, *startp = p;
        struct passwd *pw;
        char *home;
-       int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
 
-       while ((c = *p) != '\0') {
+       for (;;) {
+               c = *p;
                switch(c) {
                case CTLESC: /* This means CTL* are always considered quoted. */
                case CTLVAR:
@@ -309,36 +312,27 @@ exptilde(char *p, int flag)
                case CTLQUOTEMARK:
                        return (startp);
                case ':':
-                       if (flag & EXP_VARTILDE)
-                               goto done;
+                       if ((flag & EXP_VARTILDE) == 0)
                        break;
+                       /* FALLTHROUGH */
+               case '\0':
                case '/':
                case CTLENDVAR:
-                       goto done;
-               }
-               p++;
-       }
-done:
        *p = '\0';
        if (*(startp+1) == '\0') {
-               if ((home = lookupvar("HOME")) == NULL)
-                       goto lose;
+                               home = lookupvar("HOME");
        } else {
-               if ((pw = getpwnam(startp+1)) == NULL)
-                       goto lose;
-               home = pw->pw_dir;
+                               pw = getpwnam(startp+1);
+                               home = pw != NULL ? pw->pw_dir : NULL;
        }
-       if (*home == '\0')
-               goto lose;
-       *p = c;
-       if (quotes)
-               STPUTS_QUOTES(home, SQSYNTAX, expdest);
-       else
-               STPUTS(home, expdest);
-       return (p);
-lose:
        *p = c;
+                       if (home == NULL || *home == '\0')
        return (startp);
+                       strtodest(home, flag, VSNORMAL, 1);
+                       return (p);
+               }
+               p++;
+       }
 }
 
 
@@ -382,59 +376,40 @@ removerecordregions(int endoff)
 }
 
 /*
- * Expand arithmetic expression.  Backup to start of expression,
- * evaluate, place result in (backed up) result, adjust string position.
+ * Expand arithmetic expression.
+ * Note that flag is not required as digits never require CTLESC characters.
  */
-void
-expari(int flag)
+static char *
+expari(char *p)
 {
-       char *p, *q, *start;
+       char *q, *start;
        arith_t result;
        int begoff;
-       int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
        int quoted;
+       int adj;
 
-       /*
-        * This routine is slightly over-complicated for
-        * efficiency.  First we make sure there is
-        * enough space for the result, which may be bigger
-        * than the expression.  Next we
-        * scan backwards looking for the start of arithmetic.  If the
-        * next previous character is a CTLESC character, then we
-        * have to rescan starting from the beginning since CTLESC
-        * characters have to be processed left to right.
-        */
-       CHECKSTRSPACE(DIGITS(result) - 2, expdest);
-       USTPUTC('\0', expdest);
-       start = stackblock();
-       p = expdest - 2;
-       while (p >= start && *p != CTLARI)
-               --p;
-       if (p < start || *p != CTLARI)
-               error("missing CTLARI (shouldn't happen)");
-       if (p > start && *(p - 1) == CTLESC)
-               for (p = start; *p != CTLARI; p++)
-                       if (*p == CTLESC)
-                               p++;
-
-       if (p[1] == '"')
-               quoted=1;
-       else
-               quoted=0;
-       begoff = p - start;
+       quoted = *p++ == '"';
+       begoff = expdest - stackblock();
+       p = argstr(p, 0);
        removerecordregions(begoff);
-       if (quotes)
-               rmescapes(p+2);
+       STPUTC('\0', expdest);
+       start = stackblock() + begoff;
+
        q = grabstackstr(expdest);
-       result = arith(p+2);
+       result = arith(start);
        ungrabstackstr(q, expdest);
-       fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result);
-       while (*p++)
-               ;
-       if (quoted == 0)
-               recordregion(begoff, p - 1 - start, 0);
-       result = expdest - p + 1;
-       STADJUST(-result, expdest);
+
+       start = stackblock() + begoff;
+       adj = start - expdest;
+       STADJUST(adj, expdest);
+
+       CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest);
+       fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result);
+       adj = strlen(expdest);
+       STADJUST(adj, expdest);
+       if (!quoted)
+               recordregion(begoff, expdest - stackblock(), 0);
+       return p;
 }
 
 
@@ -454,7 +429,7 @@ expbackq(union node *cmd, int quoted, int flag)
        char lastc;
        int startloc = dest - stackblock();
        char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
-       int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
+       int quotes = flag & (EXP_FULL | EXP_CASE);
        size_t nnl;
 
        INTOFF;
@@ -505,7 +480,7 @@ expbackq(union node *cmd, int quoted, int flag)
        if (in.buf)
                ckfree(in.buf);
        if (in.jp)
-               exitstatus = waitforjob(in.jp, NULL);
+               exitstatus = waitforjob(in.jp, (int *)NULL);
        if (quoted == 0)
                recordregion(startloc, dest - stackblock(), 0);
        TRACE(("expbackq: size=%td: \"%.*s\"\n",
@@ -518,6 +493,17 @@ expbackq(union node *cmd, int quoted, int flag)
 
 
 
+static void
+recordleft(const char *str, const char *loc, char *startp)
+{
+       int amount;
+
+       amount = ((str - 1) - (loc - startp)) - expdest;
+       STADJUST(amount, expdest);
+       while (loc != str - 1)
+               *startp++ = *loc++;
+}
+
 static int
 subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
   int varflags, int quotes)
@@ -549,11 +535,10 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
        case VSQUESTION:
                if (*p != CTLENDVAR) {
                        outfmt(out2, "%s\n", startp);
-                       error(NULL);
+                       error((char *)NULL);
                }
                error("%.*s: parameter %snot set", (int)(p - str - 1),
-                     str, (varflags & VSNUL) ? "null or "
-                                             : nullstr);
+                     str, (varflags & VSNUL) ? "null or " : "");
                return 0;
 
        case VSTRIMLEFT:
@@ -562,7 +547,8 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
                        *loc = '\0';
                        if (patmatch(str, startp, quotes)) {
                                *loc = c;
-                               goto recordleft;
+                               recordleft(str, loc, startp);
+                               return 1;
                        }
                        *loc = c;
                        if (quotes && *loc == CTLESC)
@@ -576,7 +562,8 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
                        *loc = '\0';
                        if (patmatch(str, startp, quotes)) {
                                *loc = c;
-                               goto recordleft;
+                               recordleft(str, loc, startp);
+                               return 1;
                        }
                        *loc = c;
                        loc--;
@@ -624,13 +611,6 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
        default:
                abort();
        }
-
-recordleft:
-       amount = ((str - 1) - (loc - startp)) - expdest;
-       STADJUST(amount, expdest);
-       while (loc != str - 1)
-               *startp++ = *loc++;
-       return 1;
 }
 
 
@@ -645,7 +625,7 @@ evalvar(char *p, int flag)
        int subtype;
        int varflags;
        char *var;
-       char *val;
+       const char *val;
        int patloc;
        int c;
        int set;
@@ -654,7 +634,8 @@ evalvar(char *p, int flag)
        int varlen;
        int varlenb;
        int easy;
-       int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
+       int quotes = flag & (EXP_FULL | EXP_CASE);
+       int record = 0;
 
        varflags = (unsigned char)*p++;
        subtype = varflags & VSTYPE;
@@ -666,10 +647,8 @@ evalvar(char *p, int flag)
 again: /* jump here after setting a variable with ${var=text} */
        if (varflags & VSLINENO) {
                set = 1;
-               special = 0;
-               val = var;
-               p[-1] = '\0';   /* temporarily overwrite '=' to have \0
-                                  terminated string */
+               special = 1;
+               val = NULL;
        } else if (special) {
                set = varisset(var, varflags & VSNUL);
                val = NULL;
@@ -698,6 +677,9 @@ again: /* jump here after setting a variable with ${var=text} */
        if (set && subtype != VSPLUS) {
                /* insert the value of the variable */
                if (special) {
+                       if (varflags & VSLINENO)
+                               STPUTBIN(var, p - var - 1, expdest);
+                       else
                        varvalue(var, varflags & VSQUOTE, subtype, flag);
                        if (subtype == VSLENGTH) {
                                varlenb = expdest - stackblock() - startloc;
@@ -711,22 +693,15 @@ again: /* jump here after setting a variable with ${var=text} */
                                STADJUST(-varlenb, expdest);
                        }
                } else {
-                       char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
-                                                                 : BASESYNTAX;
-
                        if (subtype == VSLENGTH) {
                                for (;*val; val++)
                                        if (!localeisutf8 ||
                                            (*val & 0xC0) != 0x80)
                                                varlen++;
                        }
-                       else {
-                               if (quotes)
-                                       STPUTS_QUOTES(val, syntax, expdest);
                                else
-                                       STPUTS(val, expdest);
-
-                       }
+                               strtodest(val, flag, subtype,
+                                   varflags & VSQUOTE);
                }
        }
 
@@ -740,15 +715,11 @@ again: /* jump here after setting a variable with ${var=text} */
        switch (subtype) {
        case VSLENGTH:
                expdest = cvtnum(varlen, expdest);
-               goto record;
+               record = 1;
+               break;
 
        case VSNORMAL:
-               if (!easy)
-                       break;
-record:
-               recordregion(startloc, expdest - stackblock(),
-                   varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
-                   (*var == '@' || *var == '*')));
+               record = easy;
                break;
 
        case VSPLUS:
@@ -758,8 +729,7 @@ record:
                            (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0));
                        break;
                }
-               if (easy)
-                       goto record;
+               record = easy;
                break;
 
        case VSTRIMLEFT:
@@ -781,7 +751,8 @@ record:
                }
                /* Remove any recorded regions beyond start of variable */
                removerecordregions(startloc);
-               goto record;
+               record = 1;
+               break;
 
        case VSASSIGN:
        case VSQUESTION:
@@ -798,8 +769,7 @@ record:
                        }
                        break;
                }
-               if (easy)
-                       goto record;
+               record = easy;
                break;
 
        case VSERROR:
@@ -810,7 +780,11 @@ record:
        default:
                abort();
        }
-       p[-1] = '=';    /* recover overwritten '=' */
+
+       if (record)
+               recordregion(startloc, expdest - stackblock(),
+                   varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
+                   (*var == '@' || *var == '*')));
 
        if (subtype != VSNORMAL) {      /* skip to end of alternative */
                int nesting = 1;
@@ -839,7 +813,7 @@ record:
  */
 
 static int
-varisset(char *name, int nulok)
+varisset(const char *name, int nulok)
 {
 
        if (*name == '!')
@@ -858,9 +832,11 @@ varisset(char *name, int nulok)
                }
        } else if (is_digit(*name)) {
                char *ap;
-               int num = atoi(name);
+               long num;
 
-               if (num > shellparam.nparam)
+               errno = 0;
+               num = strtol(name, NULL, 10);
+               if (errno != 0 || num > shellparam.nparam)
                        return 0;
 
                if (num == 0)
@@ -888,35 +864,33 @@ strtodest(const char *p, int flag, int subtype, int quoted)
  */
 
 static void
-varvalue(char *name, int quoted, int subtype, int flag)
+varvalue(const char *name, int quoted, int subtype, int flag)
 {
        int num;
        char *p;
        int i;
-       char sep;
+       char sep[2];
        char **ap;
 
        switch (*name) {
        case '$':
                num = rootpid;
-               goto numvar;
+               break;
        case '?':
                num = oexitstatus;
-               goto numvar;
+               break;
        case '#':
                num = shellparam.nparam;
-               goto numvar;
+               break;
        case '!':
                num = backgndpidval();
-numvar:
-               expdest = cvtnum(num, expdest);
                break;
        case '-':
                for (i = 0 ; i < NOPTS ; i++) {
                        if (optlist[i].val)
                                STPUTC(optlist[i].letter, expdest);
                }
-               break;
+               return;
        case '@':
                if (flag & EXP_FULL && quoted) {
                        for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
@@ -924,36 +898,39 @@ numvar:
                                if (*ap)
                                        STPUTC('\0', expdest);
                        }
-                       break;
+                       return;
                }
                /* FALLTHROUGH */
        case '*':
                if (ifsset())
-                       sep = ifsval()[0];
+                       sep[0] = ifsval()[0];
                else
-                       sep = ' ';
+                       sep[0] = ' ';
+               sep[1] = '\0';
                for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
                        strtodest(p, flag, subtype, quoted);
                        if (!*ap)
                                break;
-                       if (sep || (flag & EXP_FULL && !quoted && **ap != '\0'))
-                               STPUTC(sep, expdest);
+                       if (sep[0])
+                               strtodest(sep, flag, subtype, quoted);
+                       else if (flag & EXP_FULL && !quoted && **ap != '\0')
+                               STPUTC('\0', expdest);
                }
-               break;
-       case '0':
-               p = arg0;
-               strtodest(p, flag, subtype, quoted);
-               break;
+               return;
        default:
                if (is_digit(*name)) {
                        num = atoi(name);
-                       if (num > 0 && num <= shellparam.nparam) {
+                       if (num == 0)
+                               p = arg0;
+                       else if (num > 0 && num <= shellparam.nparam)
                                p = shellparam.p[num - 1];
+                       else
+                               return;
                                strtodest(p, flag, subtype, quoted);
                        }
+               return;
                }
-               break;
-       }
+       expdest = cvtnum(num, expdest);
 }
 
 
@@ -968,6 +945,7 @@ recordregion(int start, int end, int inquotes)
 {
        struct ifsregion *ifsp;
 
+       INTOFF;
        if (ifslastp == NULL) {
                ifsp = &ifsfirst;
        } else {
@@ -975,6 +953,7 @@ recordregion(int start, int end, int inquotes)
                    && ifslastp->inquotes == inquotes) {
                        /* extend previous area */
                        ifslastp->endoff = end;
+                       INTON;
                        return;
                }
                ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
@@ -985,6 +964,7 @@ recordregion(int start, int end, int inquotes)
        ifslastp->begoff = start;
        ifslastp->endoff = end;
        ifslastp->inquotes = inquotes;
+       INTON;
 }
 
 
@@ -1109,33 +1089,31 @@ static char expdir[PATH_MAX];
  * The results are stored in the list exparg.
  */
 static void
-expandmeta(struct strlist *str, int flag __unused)
+expandmeta(struct strlist *str)
 {
        char *p;
        struct strlist **savelastp;
        struct strlist *sp;
        char c;
-       /* TODO - EXP_REDIR */
 
        while (str) {
-               if (fflag)
-                       goto nometa;
-               p = str->text;
-               for (;;) {                      /* fast check for meta chars */
-                       if ((c = *p++) == '\0')
-                               goto nometa;
-                       if (c == '*' || c == '?' || c == '[')
-                               break;
-               }
                savelastp = exparg.lastp;
+               if (!fflag) {
+                       p = str->text;
+                       for (; (c = *p) != '\0'; p++) {
+                               /* fast check for meta chars */
+                               if (c == '*' || c == '?' || c == '[') {
                INTOFF;
                expmeta(expdir, str->text);
                INTON;
+                                       break;
+                               }
+                       }
+               }
                if (exparg.lastp == savelastp) {
                        /*
                         * no matches
                         */
-nometa:
                        *exparg.lastp = str;
                        rmescapes(str->text);
                        exparg.lastp = &str->next;
@@ -1238,9 +1216,9 @@ expmeta(char *enddir, char *name)
                }
        }
        if (enddir == expdir) {
-               p = __DECONST(char *, ".");
+               p = ".";
        } else if (enddir == expdir + 1 && *expdir == '/') {
-               p = __DECONST(char *, "/");
+               p = "/";
        } else {
                p = expdir;
                enddir[-1] = '\0';
@@ -1303,8 +1281,7 @@ addfname(char *name)
        char *p;
        struct strlist *sp;
 
-       p = stalloc(strlen(name) + 1);
-       scopy(name, p);
+       p = stsavestr(name);
        sp = (struct strlist *)stalloc(sizeof *sp);
        sp->text = p;
        *exparg.lastp = sp;
@@ -1494,16 +1471,14 @@ patmatch(const char *pattern, const char *string, int squoted)
                        endp = p;
                        if (*endp == '!' || *endp == '^')
                                endp++;
-                       for (;;) {
+                       do {
                                while (*endp == CTLQUOTEMARK)
                                        endp++;
                                if (*endp == 0)
                                        goto dft;               /* no matching ] */
                                if (*endp == CTLESC)
                                        endp++;
-                               if (*++endp == ']')
-                                       break;
-                       }
+                       } while (*++endp != ']');
                        invert = 0;
                        if (*p == '!' || *p == '^') {
                                invert++;
index 0f0032a..93c80f3 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)expand.h    8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/expand.h 246288 2013-02-03 15:54:57Z jilles $
+ * $FreeBSD$
  */
 
 struct strlist {
@@ -54,7 +50,6 @@ struct arglist {
 #define EXP_FULL       0x1     /* perform word splitting & file globbing */
 #define EXP_TILDE      0x2     /* do normal tilde expansion */
 #define        EXP_VARTILDE    0x4     /* expand tildes in an assignment */
-#define        EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
 #define EXP_CASE       0x10    /* keeps quotes around for CASE pattern */
 #define EXP_SPLIT_LIT  0x20    /* IFS split literal text ${v+-a b c} */
 #define EXP_LIT_QUOTED 0x40    /* for EXP_SPLIT_LIT, start off quoted */
@@ -62,6 +57,5 @@ struct arglist {
 
 union node;
 void expandarg(union node *, struct arglist *, int);
-void expari(int);
 void rmescapes(char *);
 int casematch(union node *, const char *);
index 5676f77..2b92c60 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)cmv 8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/cmv 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 # Conditional move--don't replace an existing file.
 
index b6aa59d..95f6857 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)dirs        8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/dirs 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
index 1863b26..68802a0 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)login       8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/login 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 # replaces the login builtin in the BSD shell
 login () exec login "$@"
index 8d7d8ce..57ac1ce 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,6 +32,6 @@
 # SUCH DAMAGE.
 #
 #      @(#)newgrp      8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/newgrp 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 newgrp() exec newgrp "$@"
index 12b3c6e..bc1cd5c 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)popd        8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/popd 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
index b3058ed..9e31f2a 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)pushd       8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/pushd 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD$
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
index 6817d4a..1749298 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -34,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)suspend     8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/funcs/suspend 215268 2010-11-13 22:20:46Z jilles $
+# $FreeBSD$
 
 suspend() {
        local -
index 362e009..7295c3f 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)histedit.c      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/histedit.c 240541 2012-09-15 21:56:30Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/param.h>
 #include <limits.h>
 #include <paths.h>
@@ -49,8 +54,8 @@
 #include "main.h"
 #include "output.h"
 #include "mystring.h"
-#include "myhistedit.h"
 #ifndef NO_HISTORY
+#include "myhistedit.h"
 #include "error.h"
 #include "eval.h"
 #include "memalloc.h"
@@ -108,10 +113,8 @@ histedit(void)
                        if (el_in == NULL || el_err == NULL || el_out == NULL)
                                goto bad;
                        term = lookupvar("TERM");
-                       if (term) {
-                               if (setenv("TERM", term, 1) == -1)
-                                       error("setenv: cannot set TERM=1");
-                       }
+                       if (term)
+                               setenv("TERM", term, 1);
                        else
                                unsetenv("TERM");
                        el = el_init(arg0, el_in, el_out, el_err);
@@ -119,9 +122,9 @@ histedit(void)
                                if (hist)
                                        el_set(el, EL_HIST, history, hist);
                                el_set(el, EL_PROMPT, getprompt);
-                               el_set(el, EL_ADDFN, "rl-complete",
-                                   "ReadLine compatible completion function",
-                                   _el_fn_complete);
+                               el_set(el, EL_ADDFN, "sh-complete",
+                                   "Filename completion",
+                                   _el_fn_sh_complete);
                        } else {
 bad:
                                out2fmt_flush("sh: can't initialize editing\n");
@@ -138,8 +141,7 @@ bad:
                                el_set(el, EL_EDITOR, "vi");
                        else if (Eflag)
                                el_set(el, EL_EDITOR, "emacs");
-                       el_set(el, EL_BIND, "^I",
-                           tabcomplete ? "rl-complete" : "ed-insert", NULL);
+                       el_set(el, EL_BIND, "^I", "sh-complete", NULL);
                        el_source(el, NULL);
                }
        } else {
@@ -164,9 +166,10 @@ sethistsize(const char *hs)
        HistEvent he;
 
        if (hist != NULL) {
-               if (hs == NULL || *hs == '\0' ||
-                  (histsize = atoi(hs)) < 0)
+               if (hs == NULL || !is_number(hs))
                        histsize = 100;
+               else
+                       histsize = atoi(hs);
                history(hist, &he, H_SETSIZE, histsize);
                history(hist, &he, H_SETUNIQUE, 1);
        }
@@ -183,11 +186,11 @@ int
 histcmd(int argc, char **argv __unused)
 {
        int ch;
-       const char *volatile editor = NULL;
+       const char *editor = NULL;
        HistEvent he;
-       volatile int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
+       int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
        int i, retval;
-       const char *firststr = NULL, *laststr = NULL;
+       const char *firststr, *laststr;
        int first, last, direction;
        char *pat = NULL, *repl = NULL;
        static int active = 0;
@@ -335,9 +338,8 @@ histcmd(int argc, char **argv __unused)
                                out1fmt("%5d ", he.num);
                        out1str(he.str);
                } else {
-                       char *s = pat ?
-                          fc_replace(he.str, pat, repl) :
-                          __DECONST(char *, he.str);
+                       const char *s = pat ?
+                          fc_replace(he.str, pat, repl) : he.str;
 
                        if (sflg) {
                                if (displayhist) {
@@ -475,14 +477,14 @@ bindcmd(int argc, char **argv)
 
        if (el == NULL)
                error("line editing is disabled");
-       return (el_parse(el, argc, (const char **)argv));
+       return (el_parse(el, argc, __DECONST(const char **, argv)));
 }
 
 #else
 #include "error.h"
 
 int
-histcmd(int argc __unused, char **argv __unused)
+histcmd(int argc, char **argv)
 {
 
        error("not compiled with history support");
@@ -491,7 +493,7 @@ histcmd(int argc __unused, char **argv __unused)
 }
 
 int
-bindcmd(int argc __unused, char **argv __unused)
+bindcmd(int argc, char **argv)
 {
 
        error("not compiled with line editing support");
index f470748..412f144 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)input.c 8.3 (Berkeley) 6/9/95
- * $FreeBSD: head/bin/sh/input.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)input.c    8.3 (Berkeley) 6/9/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <stdio.h>     /* defines BUFSIZ */
 #include <fcntl.h>
 #include <errno.h>
@@ -111,33 +116,6 @@ resetinput(void)
 }
 
 
-/*
- * Read a line from the script.
- */
-
-char *
-pfgets(char *line, int len)
-{
-       char *p = line;
-       int nleft = len;
-       int c;
-
-       while (--nleft > 0) {
-               c = pgetc_macro();
-               if (c == PEOF) {
-                       if (p == line)
-                               return NULL;
-                       break;
-               }
-               *p++ = c;
-               if (c == '\n')
-                       break;
-       }
-       *p = '\0';
-       return line;
-}
-
-
 
 /*
  * Read a character from the script, returning PEOF on end of file.
@@ -157,20 +135,16 @@ preadfd(void)
        int nr;
        parsenextc = parsefile->buf;
 
-#ifndef NO_HISTORY
-       if (el != NULL && gotwinch) {
-               gotwinch = 0;
-               el_resize(el);
-       }
-#endif
 retry:
 #ifndef NO_HISTORY
        if (parsefile->fd == 0 && el) {
                static const char *rl_cp;
                static int el_len;
 
-               if (rl_cp == NULL)
+               if (rl_cp == NULL) {
+                       el_resize(el);
                        rl_cp = el_gets(el, &el_len);
+               }
                if (rl_cp == NULL)
                        nr = el_len == 0 ? 0 : -1;
                else {
@@ -223,10 +197,16 @@ preadbuffer(void)
 {
        char *p, *q;
        int more;
-       int something;
        char savec;
 
-       if (parsefile->strpush) {
+       while (parsefile->strpush) {
+               /*
+                * Add a space to the end of an alias to ensure that the
+                * alias remains in use while parsing its last word.
+                * This avoids alias recursions.
+                */
+               if (parsenleft == -1 && parsefile->strpush->ap != NULL)
+                       return ' ';
                popstring();
                if (--parsenleft >= 0)
                        return (*parsenextc++);
@@ -247,24 +227,18 @@ again:
        q = p = parsefile->buf + (parsenextc - parsefile->buf);
 
        /* delete nul characters */
-       something = 0;
        for (more = 1; more;) {
                switch (*p) {
                case '\0':
                        p++;    /* Skip nul */
                        goto check;
 
-               case '\t':
-               case ' ':
-                       break;
-
                case '\n':
                        parsenleft = q - parsenextc;
                        more = 0; /* Stop processing here */
                        break;
 
                default:
-                       something = 1;
                        break;
                }
 
@@ -283,7 +257,8 @@ check:
        *q = '\0';
 
 #ifndef NO_HISTORY
-       if (parsefile->fd == 0 && hist && something) {
+       if (parsefile->fd == 0 && hist &&
+           parsenextc[strspn(parsenextc, " \t\n")] != '\0') {
                HistEvent he;
                INTOFF;
                history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
@@ -336,7 +311,7 @@ pungetc(void)
  * We handle aliases this way.
  */
 void
-pushstring(char *s, int len, struct alias *ap)
+pushstring(const char *s, int len, struct alias *ap)
 {
        struct strpush *sp;
 
@@ -365,12 +340,16 @@ popstring(void)
        struct strpush *sp = parsefile->strpush;
 
        INTOFF;
+       if (sp->ap) {
+               if (parsenextc != sp->ap->val &&
+                   (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
+                       forcealias();
+               sp->ap->flag &= ~ALIASINUSE;
+       }
        parsenextc = sp->prevstring;
        parsenleft = sp->prevnleft;
        parselleft = sp->prevlleft;
 /*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
-       if (sp->ap)
-               sp->ap->flag &= ~ALIASINUSE;
        parsefile->strpush = sp->prev;
        if (sp != &(parsefile->basestrpush))
                ckfree(sp);
@@ -389,18 +368,10 @@ setinputfile(const char *fname, int push)
        int fd2;
 
        INTOFF;
-#ifndef O_CLOEXEC
-       if ((fd = open(fname, O_RDONLY)) < 0)
-#else
        if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
-#endif
                error("cannot open %s: %s", fname, strerror(errno));
        if (fd < 10) {
-#ifndef F_DUPFD_CLOEXEC
-               fd2 = fcntl(fd, F_DUPFD, 10);
-#else
                fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
-#endif
                close(fd);
                if (fd2 < 0)
                        error("Out of file descriptors");
@@ -419,9 +390,6 @@ setinputfile(const char *fname, int push)
 void
 setinputfd(int fd, int push)
 {
-#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
-       fcntl(fd, F_SETFD, FD_CLOEXEC);
-#endif
        if (push) {
                pushfile();
                parsefile->buf = ckmalloc(BUFSIZ + 1);
index 09a19fc..cb0af77 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)input.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/input.h 253650 2013-07-25 15:08:41Z jilles $
+ * $FreeBSD$
  */
 
 /* PEOF (the end of file marker) is defined in syntax.h */
@@ -52,12 +48,11 @@ struct alias;
 struct parsefile;
 
 void resetinput(void);
-char *pfgets(char *, int);
 int pgetc(void);
 int preadbuffer(void);
 int preadateof(void);
 void pungetc(void);
-void pushstring(char *, int, struct alias *);
+void pushstring(const char *, int, struct alias *);
 void setinputfile(const char *, int);
 void setinputfd(int, int);
 void setinputstring(const char *, int);
index 4ce9064..2dab8c0 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)jobs.c  8.5 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/jobs.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)jobs.c     8.5 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/resource.h>
@@ -78,21 +83,21 @@ static struct job *bgjob = NULL; /* last background process */
 static struct job *jobmru;     /* most recently used job list */
 static pid_t initialpgrp;      /* pgrp of shell on invocation */
 #endif
-int in_waitcmd = 0;            /* are we in waitcmd()? */
-volatile sig_atomic_t breakwaitcmd = 0;        /* should wait be terminated? */
 static int ttyfd = -1;
 
 /* mode flags for dowait */
 #define DOWAIT_BLOCK   0x1 /* wait until a child exits */
-#define DOWAIT_SIG     0x2 /* if DOWAIT_BLOCK, abort on signals */
+#define DOWAIT_SIG     0x2 /* if DOWAIT_BLOCK, abort on signal */
+#define DOWAIT_SIG_TRAP        0x4 /* if DOWAIT_SIG, abort on trapped signal only */
 
 #if JOBS
 static void restartjob(struct job *);
 #endif
 static void freejob(struct job *);
 static int waitcmdloop(struct job *);
-static struct job *getjob_nonotfound(char *);
-static struct job *getjob(char *);
+static struct job *getjob_nonotfound(const char *);
+static struct job *getjob(const char *);
+pid_t killjob(const char *, int);
 static pid_t dowait(int, struct job *);
 static void checkzombies(void);
 static void cmdtxt(union node *);
@@ -113,6 +118,24 @@ static void showjob(struct job *, int);
 static int jobctl;
 
 #if JOBS
+static void
+jobctl_notty(void)
+{
+       if (ttyfd >= 0) {
+               close(ttyfd);
+               ttyfd = -1;
+       }
+       if (!iflag) {
+               setsignal(SIGTSTP);
+               setsignal(SIGTTOU);
+               setsignal(SIGTTIN);
+               jobctl = 1;
+               return;
+       }
+       out2fmt_flush("sh: can't access tty; job control turned off\n");
+       mflag = 0;
+}
+
 void
 setjobctl(int on)
 {
@@ -123,54 +146,40 @@ setjobctl(int on)
        if (on) {
                if (ttyfd != -1)
                        close(ttyfd);
-#ifndef O_CLOEXEC
-               if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
-#else
                if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
-#endif
                        i = 0;
                        while (i <= 2 && !isatty(i))
                                i++;
                        if (i > 2 ||
-#ifndef F_DUPFD_CLOEXEC
-                           (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
-#else
-                           (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0)
-#endif
-                               goto out;
+                           (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) {
+                               jobctl_notty();
+                               return;
+                       }
                }
                if (ttyfd < 10) {
                        /*
                         * Keep our TTY file descriptor out of the way of
                         * the user's redirections.
                         */
-#ifndef F_DUPFD_CLOEXEC
-                       if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
-#else
                        if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
-#endif
-                               close(ttyfd);
-                               ttyfd = -1;
-                               goto out;
+                               jobctl_notty();
+                               return;
                        }
                        close(ttyfd);
                        ttyfd = i;
                }
-#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
-               if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
-                       close(ttyfd);
-                       ttyfd = -1;
-                       goto out;
-               }
-#endif
                do { /* while we are in the background */
                        initialpgrp = tcgetpgrp(ttyfd);
                        if (initialpgrp < 0) {
-out:                           out2fmt_flush("sh: can't access tty; job control turned off\n");
-                               mflag = 0;
+                               jobctl_notty();
                                return;
                        }
                        if (initialpgrp != getpgrp()) {
+                               if (!iflag) {
+                                       initialpgrp = -1;
+                                       jobctl_notty();
+                                       return;
+                               }
                                kill(0, SIGTTIN);
                                continue;
                        }
@@ -182,9 +191,11 @@ out:                               out2fmt_flush("sh: can't access tty; job control turned off\n");
                tcsetpgrp(ttyfd, rootpid);
        } else { /* turning job control off */
                setpgid(0, initialpgrp);
+               if (ttyfd >= 0) {
                tcsetpgrp(ttyfd, initialpgrp);
                close(ttyfd);
                ttyfd = -1;
+               }
                setsignal(SIGTSTP);
                setsignal(SIGTTOU);
                setsignal(SIGTTIN);
@@ -196,35 +207,38 @@ out:                              out2fmt_flush("sh: can't access tty; job control turned off\n");
 
 #if JOBS
 int
-fgcmd(int argc __unused, char **argv)
+fgcmd(int argc __unused, char **argv __unused)
 {
        struct job *jp;
        pid_t pgrp;
        int status;
 
-       jp = getjob(argv[1]);
+       nextopt("");
+       jp = getjob(*argptr);
        if (jp->jobctl == 0)
                error("job not created under job control");
        printjobcmd(jp);
        flushout(&output);
        pgrp = jp->ps[0].pid;
+       if (ttyfd >= 0)
        tcsetpgrp(ttyfd, pgrp);
        restartjob(jp);
        jp->foreground = 1;
        INTOFF;
-       status = waitforjob(jp, NULL);
+       status = waitforjob(jp, (int *)NULL);
        INTON;
        return status;
 }
 
 
 int
-bgcmd(int argc, char **argv)
+bgcmd(int argc __unused, char **argv __unused)
 {
        struct job *jp;
 
+       nextopt("");
        do {
-               jp = getjob(*++argv);
+               jp = getjob(*argptr);
                if (jp->jobctl == 0)
                        error("job not created under job control");
                if (jp->state == JOBDONE)
@@ -233,7 +247,7 @@ bgcmd(int argc, char **argv)
                jp->foreground = 0;
                out1fmt("[%td] ", jp - jobtab + 1);
                printjobcmd(jp);
-       } while (--argc > 1);
+       } while (*argptr != NULL && *++argptr != NULL);
        return 0;
 }
 
@@ -359,13 +373,13 @@ showjob(struct job *jp, int mode)
                        strcat(statestr, " (core dumped)");
        }
 
-       for (ps = jp->ps ; ; ps++) {    /* for each process */
+       for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */
                if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
                        out1fmt("%d\n", (int)ps->pid);
-                       goto skip;
+                       continue;
                }
                if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
-                       goto skip;
+                       continue;
                if (jobno == curr && ps == jp->ps)
                        c = '+';
                else if (jobno == prev && ps == jp->ps)
@@ -396,8 +410,6 @@ showjob(struct job *jp, int mode)
                        out1c('\n');
                } else
                        printjobcmd(jp);
-skip:          if (--procno <= 0)
-                       break;
        }
 }
 
@@ -495,7 +507,7 @@ waitcmd(int argc __unused, char **argv __unused)
 static int
 waitcmdloop(struct job *job)
 {
-       int status, retval;
+       int status, retval, sig;
        struct job *jp;
 
        /*
@@ -503,17 +515,12 @@ waitcmdloop(struct job *job)
         * received.
         */
 
-       in_waitcmd++;
        do {
                if (job != NULL) {
-                       if (job->state) {
+                       if (job->state == JOBDONE) {
                                status = job->ps[job->nprocs - 1].status;
                                if (WIFEXITED(status))
                                        retval = WEXITSTATUS(status);
-#if JOBS
-                               else if (WIFSTOPPED(status))
-                                       retval = WSTOPSIG(status) + 128;
-#endif
                                else
                                        retval = WTERMSIG(status) + 128;
                                if (! iflag || ! job->changed)
@@ -523,7 +530,6 @@ waitcmdloop(struct job *job)
                                        if (job == bgjob)
                                                bgjob = NULL;
                                }
-                               in_waitcmd--;
                                return retval;
                        }
                } else {
@@ -539,28 +545,29 @@ waitcmdloop(struct job *job)
                                }
                        for (jp = jobtab ; ; jp++) {
                                if (jp >= jobtab + njobs) {     /* no running procs */
-                                       in_waitcmd--;
                                        return 0;
                                }
                                if (jp->used && jp->state == 0)
                                        break;
                        }
                }
-       } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, NULL) != -1);
-       in_waitcmd--;
+       } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
 
-       return pendingsig + 128;
+       sig = pendingsig_waitcmd;
+       pendingsig_waitcmd = 0;
+       return sig + 128;
 }
 
 
 
 int
-jobidcmd(int argc __unused, char **argv)
+jobidcmd(int argc __unused, char **argv __unused)
 {
        struct job *jp;
        int i;
 
-       jp = getjob(argv[1]);
+       nextopt("");
+       jp = getjob(*argptr);
        for (i = 0 ; i < jp->nprocs ; ) {
                out1fmt("%d", (int)jp->ps[i].pid);
                out1c(++i < jp->nprocs? ' ' : '\n');
@@ -575,32 +582,33 @@ jobidcmd(int argc __unused, char **argv)
  */
 
 static struct job *
-getjob_nonotfound(char *name)
+getjob_nonotfound(const char *name)
 {
        int jobno;
        struct job *found, *jp;
+       size_t namelen;
        pid_t pid;
        int i;
 
        if (name == NULL) {
 #if JOBS
-currentjob:    if ((jp = getcurjob(NULL)) == NULL)
-                       error("No current job");
-               return (jp);
+               name = "%+";
 #else
                error("No current job");
 #endif
-       } else if (name[0] == '%') {
+       }
+       if (name[0] == '%') {
                if (is_digit(name[1])) {
                        jobno = number(name + 1);
                        if (jobno > 0 && jobno <= njobs
                         && jobtab[jobno - 1].used != 0)
                                return &jobtab[jobno - 1];
 #if JOBS
-               } else if (name[1] == '%' && name[2] == '\0') {
-                       goto currentjob;
-               } else if (name[1] == '+' && name[2] == '\0') {
-                       goto currentjob;
+               } else if ((name[1] == '%' || name[1] == '+') &&
+                   name[2] == '\0') {
+                       if ((jp = getcurjob(NULL)) == NULL)
+                               error("No current job");
+                       return (jp);
                } else if (name[1] == '-' && name[2] == '\0') {
                        if ((jp = getcurjob(NULL)) == NULL ||
                            (jp = getcurjob(jp)) == NULL)
@@ -620,10 +628,12 @@ currentjob:       if ((jp = getcurjob(NULL)) == NULL)
                        if (found != NULL)
                                return (found);
                } else {
+                       namelen = strlen(name);
                        found = NULL;
                        for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
                                if (jp->used && jp->nprocs > 0
-                                && prefix(name + 1, jp->ps[0].cmd)) {
+                                && strncmp(jp->ps[0].cmd, name + 1,
+                                namelen - 1) == 0) {
                                        if (found)
                                                error("%s: ambiguous", name);
                                        found = jp;
@@ -645,7 +655,7 @@ currentjob: if ((jp = getcurjob(NULL)) == NULL)
 
 
 static struct job *
-getjob(char *name)
+getjob(const char *name)
 {
        struct job *jp;
 
@@ -656,13 +666,26 @@ getjob(char *name)
 }
 
 
-pid_t
-getjobpgrp(char *name)
+int
+killjob(const char *name, int sig)
 {
        struct job *jp;
+       int i, ret;
 
        jp = getjob(name);
-       return -jp->ps[0].pid;
+       if (jp->state == JOBDONE)
+               return 0;
+       if (jp->jobctl)
+               return kill(-jp->ps[0].pid, sig);
+       ret = -1;
+       errno = ESRCH;
+       for (i = 0; i < jp->nprocs; i++)
+               if (jp->ps[i].status == -1 || WIFSTOPPED(jp->ps[i].status)) {
+                       if (kill(jp->ps[i].pid, sig) == 0)
+                               ret = 0;
+               } else
+                       ret = 0;
+       return ret;
 }
 
 /*
@@ -848,7 +871,8 @@ forkshell(struct job *jp, union node *n, int mode)
                                pgrp = getpid();
                        else
                                pgrp = jp->ps[0].pid;
-                       if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
+                       if (setpgid(0, pgrp) == 0 && mode == FORK_FG &&
+                           ttyfd >= 0) {
                                /*** this causes superfluous TIOCSPGRPS ***/
                                if (tcsetpgrp(ttyfd, pgrp) < 0)
                                        error("tcsetpgrp failed, errno=%d", errno);
@@ -995,7 +1019,6 @@ int
 waitforjob(struct job *jp, int *origstatus)
 {
 #if JOBS
-       pid_t mypgrp = getpgrp();
        int propagate_int = jp->jobctl && jp->foreground;
 #endif
        int status;
@@ -1004,11 +1027,12 @@ waitforjob(struct job *jp, int *origstatus)
        INTOFF;
        TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
        while (jp->state == 0)
-               if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG : 0), jp) == -1)
+               if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG |
+                   DOWAIT_SIG_TRAP : 0), jp) == -1)
                        dotrap();
 #if JOBS
        if (jp->jobctl) {
-               if (tcsetpgrp(ttyfd, mypgrp) < 0)
+               if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0)
                        error("tcsetpgrp failed, errno=%d\n", errno);
        }
        if (jp->state == JOBSTOPPED)
@@ -1033,7 +1057,7 @@ waitforjob(struct job *jp, int *origstatus)
                        CLEAR_PENDING_INT;
        }
 #if JOBS
-       else if (rootshell && iflag && propagate_int &&
+       else if (rootshell && propagate_int &&
                        WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
                kill(getpid(), SIGINT);
 #endif
@@ -1092,15 +1116,20 @@ dowait(int mode, struct job *job)
                        wflags = 0;
                if ((mode & (DOWAIT_BLOCK | DOWAIT_SIG)) != DOWAIT_BLOCK)
                        wflags |= WNOHANG;
-               pid = wait3(&status, wflags, NULL);
+               pid = wait3(&status, wflags, (struct rusage *)NULL);
                TRACE(("wait returns %d, status=%d\n", (int)pid, status));
                if (pid == 0 && (mode & DOWAIT_SIG) != 0) {
-                       sigsuspend(&omask);
                        pid = -1;
+                       if (((mode & DOWAIT_SIG_TRAP) != 0 ?
+                           pendingsig : pendingsig_waitcmd) != 0) {
+                               errno = EINTR;
+                               break;
+                       }
+                       sigsuspend(&omask);
                        if (int_pending())
                                break;
                }
-       } while (pid == -1 && errno == EINTR && breakwaitcmd == 0);
+       } while (pid == -1 && errno == EINTR);
        if (pid == -1 && errno == ECHILD && job != NULL)
                job->state = JOBDONE;
        if ((mode & DOWAIT_SIG) != 0) {
@@ -1109,15 +1138,6 @@ dowait(int mode, struct job *job)
                sigprocmask(SIG_SETMASK, &omask, NULL);
                INTON;
        }
-       if (breakwaitcmd != 0) {
-               breakwaitcmd = 0;
-               /*
-                * Do not early terminate if the pid is positive, else the
-                * job will not be properly recorded.
-                */
-               if (pid <= 0)
-                       return -1;
-       }
        if (pid <= 0)
                return pid;
        INTOFF;
@@ -1129,7 +1149,8 @@ dowait(int mode, struct job *job)
                        for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
                                if (sp->pid == -1)
                                        continue;
-                               if (sp->pid == pid) {
+                               if (sp->pid == pid && (sp->status == -1 ||
+                                   WIFSTOPPED(sp->status))) {
                                        TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
                                                   (int)pid, sp->status,
                                                   status));
@@ -1266,14 +1287,44 @@ commandtext(union node *n)
 }
 
 
+static void
+cmdtxtdogroup(union node *n)
+{
+       cmdputs("; do ");
+       cmdtxt(n);
+       cmdputs("; done");
+}
+
+
+static void
+cmdtxtredir(union node *n, const char *op, int deffd)
+{
+       char s[2];
+
+       if (n->nfile.fd != deffd) {
+               s[0] = n->nfile.fd + '0';
+               s[1] = '\0';
+               cmdputs(s);
+       }
+       cmdputs(op);
+       if (n->type == NTOFD || n->type == NFROMFD) {
+               if (n->ndup.dupfd >= 0)
+                       s[0] = n->ndup.dupfd + '0';
+               else
+                       s[0] = '-';
+               s[1] = '\0';
+               cmdputs(s);
+       } else {
+               cmdtxt(n->nfile.fname);
+       }
+}
+
+
 static void
 cmdtxt(union node *n)
 {
        union node *np;
        struct nodelist *lp;
-       const char *p;
-       int i;
-       char s[2];
 
        if (n == NULL)
                return;
@@ -1318,14 +1369,13 @@ cmdtxt(union node *n)
                break;
        case NWHILE:
                cmdputs("while ");
-               goto until;
+               cmdtxt(n->nbinary.ch1);
+               cmdtxtdogroup(n->nbinary.ch2);
+               break;
        case NUNTIL:
                cmdputs("until ");
-until:
                cmdtxt(n->nbinary.ch1);
-               cmdputs("; do ");
-               cmdtxt(n->nbinary.ch2);
-               cmdputs("; done");
+               cmdtxtdogroup(n->nbinary.ch2);
                break;
        case NFOR:
                cmdputs("for ");
@@ -1360,36 +1410,25 @@ until:
                cmdputs(n->narg.text);
                break;
        case NTO:
-               p = ">";  i = 1;  goto redir;
+               cmdtxtredir(n, ">", 1);
+               break;
        case NAPPEND:
-               p = ">>";  i = 1;  goto redir;
+               cmdtxtredir(n, ">>", 1);
+               break;
        case NTOFD:
-               p = ">&";  i = 1;  goto redir;
+               cmdtxtredir(n, ">&", 1);
+               break;
        case NCLOBBER:
-               p = ">|"; i = 1; goto redir;
+               cmdtxtredir(n, ">|", 1);
+               break;
        case NFROM:
-               p = "<";  i = 0;  goto redir;
+               cmdtxtredir(n, "<", 0);
+               break;
        case NFROMTO:
-               p = "<>";  i = 0;  goto redir;
+               cmdtxtredir(n, "<>", 0);
+               break;
        case NFROMFD:
-               p = "<&";  i = 0;  goto redir;
-redir:
-               if (n->nfile.fd != i) {
-                       s[0] = n->nfile.fd + '0';
-                       s[1] = '\0';
-                       cmdputs(s);
-               }
-               cmdputs(p);
-               if (n->type == NTOFD || n->type == NFROMFD) {
-                       if (n->ndup.dupfd >= 0)
-                               s[0] = n->ndup.dupfd + '0';
-                       else
-                               s[0] = '-';
-                       s[1] = '\0';
-                       cmdputs(s);
-               } else {
-                       cmdtxt(n->nfile.fname);
-               }
+               cmdtxtredir(n, "<&", 0);
                break;
        case NHERE:
        case NXHERE:
index fc325f0..892f129 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)jobs.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/jobs.h 238470 2012-07-15 10:49:16Z jilles $
+ * $FreeBSD$
  */
 
 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
@@ -87,12 +83,9 @@ enum {
 };
 
 extern int job_warning;                /* user was warned about stopped jobs */
-extern int in_waitcmd;         /* are we in waitcmd()? */
-extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
 
 void setjobctl(int);
 void showjobs(int, int);
-pid_t getjobpgrp(char *);
 struct job *makejob(union node *, int);
 pid_t forkshell(struct job *, union node *, int);
 pid_t vforkexecshell(struct job *, char **, char **, const char *, int, int []);
index af66cdb..720cab0 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)mail.c  8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mail.c 213760 2010-10-13 04:01:01Z obrien $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mail.c     8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * Routines to check for mail.  (Perhaps make part of main.c?)
  */
@@ -80,7 +85,7 @@ chkmail(int silent)
        setstackmark(&smark);
        mpath = mpathset()? mpathval() : mailval();
        for (i = 0 ; i < nmboxes ; i++) {
-               p = padvance(&mpath, nullstr);
+               p = padvance(&mpath, "");
                if (p == NULL)
                        break;
                if (*p == '\0')
index e5947b9..8222bde 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)mail.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mail.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD$
  */
 
 void   chkmail(int);
index ced93f3..08f234e 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#) Copyright (c) 1991, 1993 The Regents of the University of California.  All rights reserved.
- * @(#)main.c  8.6 (Berkeley) 5/28/95
- * $FreeBSD: head/bin/sh/main.c 253650 2013-07-25 15:08:41Z jilles $
  */
 
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)main.c     8.6 (Berkeley) 5/28/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <stdio.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -72,7 +82,7 @@ int localeisutf8, initial_localeisutf8;
 static void reset(void);
 static void cmdloop(int);
 static void read_profile(const char *);
-static const char *find_dot_file(const char *);
+static char *find_dot_file(char *);
 
 /*
  * Main routine.  We initialize things, parse the arguments, execute
@@ -89,7 +99,7 @@ main(int argc, char *argv[])
        volatile int state;
        char *shinit;
 
-       setlocale(LC_ALL, "");
+       (void) setlocale(LC_ALL, "");
        initcharset();
        state = 0;
        if (setjmp(main_handler.loc)) {
@@ -130,11 +140,13 @@ main(int argc, char *argv[])
 #endif
        rootpid = getpid();
        rootshell = 1;
+       INTOFF;
        initvar();
        setstackmark(&smark);
        setstackmark(&smark2);
        procargs(argc, argv);
        pwd_init(iflag);
+       INTON;
        if (iflag)
                chkmail(1);
        if (argv[0] && argv[0][0] == '-') {
@@ -175,8 +187,6 @@ reset(void)
 {
        reseteval();
        resetinput();
-       resetparser();
-       resetredir();
 }
 
 /*
@@ -223,7 +233,7 @@ cmdloop(int top)
                popstackmark(&smark);
                setstackmark(&smark);
                if (evalskip != 0) {
-                       if (evalskip == SKIPFILE)
+                       if (evalskip == SKIPRETURN)
                                evalskip = 0;
                        break;
                }
@@ -243,15 +253,11 @@ read_profile(const char *name)
        int fd;
        const char *expandedname;
 
-       expandedname = expandstr(__DECONST(char *, name));
+       expandedname = expandstr(name);
        if (expandedname == NULL)
                return;
        INTOFF;
-#ifndef O_CLOEXEC
-       if ((fd = open(expandedname, O_RDONLY)) >= 0)
-#else
        if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
-#endif
                setinputfd(fd, 1);
        INTON;
        if (fd < 0)
@@ -282,8 +288,8 @@ readcmdfile(const char *name)
  */
 
 
-static const char *
-find_dot_file(const char *basename)
+static char *
+find_dot_file(char *basename)
 {
        char *fullname;
        const char *path = pathval();
@@ -309,8 +315,7 @@ find_dot_file(const char *basename)
 int
 dotcmd(int argc, char **argv)
 {
-       const char *fullname;
-       char *filename;
+       char *filename, *fullname;
 
        if (argc < 2)
                error("missing filename");
index 027273d..3c48e33 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)main.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/main.h 229220 2012-01-01 22:17:12Z jilles $
+ * $FreeBSD$
  */
 
 extern int rootpid;    /* pid of main shell */
index fe945cb..a04020f 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)memalloc.c      8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/memalloc.c 250527 2013-05-11 20:51:00Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/param.h>
 #include "shell.h"
 #include "output.h"
@@ -93,9 +98,11 @@ char *
 savestr(const char *s)
 {
        char *p;
+       size_t len;
 
-       p = ckmalloc(strlen(s) + 1);
-       scopy(s, p);
+       len = strlen(s);
+       p = ckmalloc(len + 1);
+       memcpy(p, s, len + 1);
        return p;
 }
 
@@ -173,6 +180,18 @@ stunalloc(pointer p)
 }
 
 
+char *
+stsavestr(const char *s)
+{
+       char *p;
+       size_t len;
+
+       len = strlen(s);
+       p = stalloc(len + 1);
+       memcpy(p, s, len + 1);
+       return p;
+}
+
 
 void
 setstackmark(struct stackmark *mark)
index 61cb1a1..e8df7cb 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)memalloc.h  8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/memalloc.h 250527 2013-05-11 20:51:00Z jilles $
+ * $FreeBSD$
  */
 
 #include <string.h>
@@ -56,6 +52,7 @@ void ckfree(pointer);
 char *savestr(const char *);
 pointer stalloc(int);
 void stunalloc(pointer);
+char *stsavestr(const char *);
 void setstackmark(struct stackmark *);
 void popstackmark(struct stackmark *);
 char *growstackstr(void);
index cf7feb4..715e324 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)miscbltin.c     8.4 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/miscbltin.c 250214 2013-05-03 15:28:31Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)miscbltin.c        8.4 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * Miscellaneous builtins.
  */
 #include "syntax.h"
 #include "trap.h"
 
+#undef eflag
+
 int readcmd(int, char **);
 int umaskcmd(int, char **);
 int ulimitcmd(int, char **);
 
-#undef eflag
-
 /*
  * The read builtin.  The -r option causes backslashes to be treated like
  * ordinary characters.
@@ -87,7 +92,7 @@ readcmd(int argc __unused, char **argv __unused)
        int backslash;
        char c;
        int rflag;
-       const char *prompt;
+       char *prompt;
        const char *ifs;
        char *p;
        int startword;
@@ -260,7 +265,7 @@ readcmd(int argc __unused, char **argv __unused)
 
        /* Set any remaining args to "" */
        while (*++ap != NULL)
-               setvar(*ap, nullstr, 0);
+               setvar(*ap, "", 0);
        return status;
 }
 
@@ -330,7 +335,7 @@ umaskcmd(int argc __unused, char **argv __unused)
                } else {
                        void *set;
                        INTOFF;
-                       if ((set = setmode (ap)) == NULL)
+                       if ((set = setmode (ap)) == 0)
                                error("Illegal number: %s", ap);
 
                        mask = getmode (set, ~mask & 0777);
@@ -383,10 +388,10 @@ static const struct limits limits[] = {
        { "locked memory",      "kbytes",       RLIMIT_MEMLOCK, 1024, 'l' },
 #endif
 #ifdef RLIMIT_NPROC
-       { "max user processes", NULL,           RLIMIT_NPROC,      1, 'u' },
+       { "max user processes", (char *)0,      RLIMIT_NPROC,      1, 'u' },
 #endif
 #ifdef RLIMIT_NOFILE
-       { "open files",         NULL,           RLIMIT_NOFILE,     1, 'n' },
+       { "open files",         (char *)0,      RLIMIT_NOFILE,     1, 'n' },
 #endif
 #ifdef RLIMIT_VMEM
        { "virtual mem size",   "kbytes",       RLIMIT_VMEM,    1024, 'v' },
@@ -397,26 +402,48 @@ static const struct limits limits[] = {
 #ifdef RLIMIT_SBSIZE
        { "sbsize",             "bytes",        RLIMIT_SBSIZE,     1, 'b' },
 #endif
-#ifdef RLIMIT_POSIXLOCK
-       { "posixlocks",         NULL,           RLIMIT_POSIXLOCK,  1, 'k' },
+#ifdef RLIMIT_NPTS
+       { "pseudo-terminals",   (char *)0,      RLIMIT_NPTS,       1, 'p' },
 #endif
-       { NULL,                 NULL,           0,                 0, '\0' }
+#ifdef RLIMIT_KQUEUES
+       { "kqueues",            (char *)0,      RLIMIT_KQUEUES,    1, 'k' },
+#endif
+       { (char *) 0,           (char *)0,      0,                 0, '\0' }
 };
 
+enum limithow { SOFT = 0x1, HARD = 0x2 };
+
+static void
+printlimit(enum limithow how, const struct rlimit *limit,
+    const struct limits *l)
+{
+       rlim_t val = 0;
+
+       if (how & SOFT)
+               val = limit->rlim_cur;
+       else if (how & HARD)
+               val = limit->rlim_max;
+       if (val == RLIM_INFINITY)
+               out1str("unlimited\n");
+       else
+       {
+               val /= l->factor;
+               out1fmt("%jd\n", (intmax_t)val);
+       }
+}
+
 int
 ulimitcmd(int argc __unused, char **argv __unused)
 {
-       int     c;
        rlim_t val = 0;
-       enum { SOFT = 0x1, HARD = 0x2 }
-                       how = SOFT | HARD;
+       enum limithow how = SOFT | HARD;
        const struct limits     *l;
        int             set, all = 0;
        int             optc, what;
        struct rlimit   limit;
 
        what = 'f';
-       while ((optc = nextopt("HSatfdsmcnuvlbk")) != '\0')
+       while ((optc = nextopt("HSatfdsmcnuvlbpwk")) != '\0')
                switch (optc) {
                case 'H':
                        how = HARD;
@@ -445,17 +472,22 @@ ulimitcmd(int argc __unused, char **argv __unused)
                if (strcmp(p, "unlimited") == 0)
                        val = RLIM_INFINITY;
                else {
-                       val = 0;
+                       char *end;
+                       uintmax_t uval;
 
-                       while ((c = *p++) >= '0' && c <= '9')
-                       {
-                               val = (val * 10) + (long)(c - '0');
-                               if (val < 0)
-                                       break;
-                       }
-                       if (c)
+                       if (*p < '0' || *p > '9')
+                               error("bad number");
+                       errno = 0;
+                       uval = strtoumax(p, &end, 10);
+                       if (errno != 0 || *end != '\0')
+                               error("bad number");
+                       if (uval > UINTMAX_MAX / l->factor)
+                               error("bad number");
+                       uval *= l->factor;
+                       val = (rlim_t)uval;
+                       if (val < 0 || (uintmax_t)val != uval ||
+                           val == RLIM_INFINITY)
                                error("bad number");
-                       val *= l->factor;
                }
        }
        if (all) {
@@ -463,10 +495,6 @@ ulimitcmd(int argc __unused, char **argv __unused)
                        char optbuf[40];
                        if (getrlimit(l->cmd, &limit) < 0)
                                error("can't get limit: %s", strerror(errno));
-                       if (how & SOFT)
-                               val = limit.rlim_cur;
-                       else if (how & HARD)
-                               val = limit.rlim_max;
 
                        if (l->units)
                                snprintf(optbuf, sizeof(optbuf),
@@ -475,13 +503,7 @@ ulimitcmd(int argc __unused, char **argv __unused)
                                snprintf(optbuf, sizeof(optbuf),
                                        "(-%c) ", l->option);
                        out1fmt("%-18s %18s ", l->name, optbuf);
-                       if (val == RLIM_INFINITY)
-                               out1str("unlimited\n");
-                       else
-                       {
-                               val /= l->factor;
-                               out1fmt("%jd\n", (intmax_t)val);
-                       }
+                       printlimit(how, &limit, l);
                }
                return 0;
        }
@@ -495,19 +517,7 @@ ulimitcmd(int argc __unused, char **argv __unused)
                        limit.rlim_max = val;
                if (setrlimit(l->cmd, &limit) < 0)
                        error("bad limit: %s", strerror(errno));
-       } else {
-               if (how & SOFT)
-                       val = limit.rlim_cur;
-               else if (how & HARD)
-                       val = limit.rlim_max;
-
-               if (val == RLIM_INFINITY)
-                       out1str("unlimited\n");
-               else
-               {
-                       val /= l->factor;
-                       out1fmt("%jd\n", (intmax_t)val);
-               }
-       }
+       } else
+               printlimit(how, &limit, l);
        return 0;
 }
index d97e3fd..1be7ff1 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)mkbuiltins  8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/mkbuiltins 235927 2012-05-24 19:48:15Z marcel $
+# $FreeBSD$
 
 temp=`/usr/bin/mktemp -t ka`
 havehist=1
@@ -62,7 +58,7 @@ cat <<\!
 !
 awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
     print $0}' $srcdir/builtins.def | sed 's/-[hj]//' > $temp
-echo 'int (*const builtinfunc[])(int, char *[]) = {'
+echo 'int (*const builtinfunc[])(int, char **) = {'
 awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
 echo '};
 
@@ -95,8 +91,8 @@ struct builtincmd {
       int special;
 };
 
-extern int (*const builtinfunc[])(int, char *[]);
+extern int (*const builtinfunc[])(int, char **);
 extern const struct builtincmd builtincmd[];
 '
-awk '{ printf "int %s(int, char *[]);\n", $1}' $temp
+awk '{ printf "int %s(int, char **);\n", $1}' $temp
 rm -f $temp
index 3ca8e90..cb88301 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#) Copyright (c) 1991, 1993 The Regents of the University of California.  All rights reserved.
- * @(#)mknodes.c       8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mknodes.c 196634 2009-08-28 22:41:25Z jilles $
  */
 
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mknodes.c  8.2 (Berkeley) 5/4/95";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * This program reads the nodetypes file and nodes.c.pat file.  It generates
  * the files nodes.h and nodes.c.
@@ -194,7 +204,7 @@ parsefield(void)
 }
 
 
-char writer[] = "\
+static const char writer[] = "\
 /*\n\
  * This file was generated by the mknodes program.\n\
  */\n\
@@ -416,9 +426,9 @@ error(const char *msg, ...)
        va_list va;
        va_start(va, msg);
 
-       fprintf(stderr, "line %d: ", linno);
-       vfprintf(stderr, msg, va);
-       fputc('\n', stderr);
+       (void) fprintf(stderr, "line %d: ", linno);
+       (void) vfprintf(stderr, msg, va);
+       (void) fputc('\n', stderr);
 
        va_end(va);
 
@@ -434,6 +444,6 @@ savestr(const char *s)
 
        if ((p = malloc(strlen(s) + 1)) == NULL)
                error("Out of space");
-       strcpy(p, s);
+       (void) strcpy(p, s);
        return p;
 }
index 1c328d5..1f81828 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#) Copyright (c) 1991, 1993 The Regents of the University of California.  All rights reserved.
- * @(#)mksyntax.c      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mksyntax.c 246522 2013-02-07 22:42:33Z jilles $
  */
 
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * This program creates syntax.h and syntax.c.
  */
@@ -50,7 +60,7 @@ struct synclass {
 };
 
 /* Syntax classes */
-struct synclass synclass[] = {
+static const struct synclass synclass[] = {
        { "CWORD",      "character is nothing special" },
        { "CNL",        "newline character" },
        { "CBACK",      "a backslash character" },
@@ -75,7 +85,7 @@ struct synclass synclass[] = {
  * Syntax classes for is_ functions.  Warning:  if you add new classes
  * you may have to change the definition of the is_in_name macro.
  */
-struct synclass is_entry[] = {
+static const struct synclass is_entry[] = {
        { "ISDIGIT",    "a digit" },
        { "ISUPPER",    "an upper case letter" },
        { "ISLOWER",    "a lower case letter" },
@@ -84,7 +94,7 @@ struct synclass is_entry[] = {
        { NULL,         NULL }
 };
 
-static char writer[] = "\
+static const char writer[] = "\
 /*\n\
  * This file was generated by the mksyntax program.\n\
  */\n\
index bdcaaeb..b6f5f97 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -36,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)mktokens    8.1 (Berkeley) 5/31/93
-# $FreeBSD: head/bin/sh/mktokens 223186 2011-06-17 13:03:49Z jilles $
+# $FreeBSD$
 
 # The following is a list of tokens.  The second column is nonzero if the
 # token marks the end of a list.  The third column is the name to print in
@@ -78,11 +74,11 @@ exec > token.h
 awk '{print "#define " $1 " " NR-1}' $temp
 echo '
 /* Array indicating which tokens mark the end of a list */
-const char tokendlist[] = {'
+static const char tokendlist[] = {'
 awk '{print "\t" $2 ","}' $temp
 echo '};
 
-const char *const tokname[] = {'
+static const char *const tokname[] = {'
 sed -e 's/"/\\"/g' \
     -e 's/[^    ]*[     ][      ]*[^    ]*[     ][      ]*\(.*\)/      "\1",/' \
     $temp
@@ -91,7 +87,7 @@ echo '};
 sed 's/"//g' $temp | awk '
 /TIF/{print "#define KWDOFFSET " NR-1; print ""; print "const char *const parsekwd[] = {"}
 /TIF/,/neverfound/{print "     \"" $3 "\","}'
-echo ' NULL
+echo ' 0
 };'
 
 rm $temp
index ae20522..e31276d 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -31,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)myhistedit.h        8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/myhistedit.h 229220 2012-01-01 22:17:12Z jilles $
+ * $FreeBSD$
  */
 
 #include <histedit.h>
index 4d78dfc..92ddb9a 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)mystring.c      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mystring.c 229219 2012-01-01 22:15:38Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * String functions.
  *
  *     equal(s1, s2)           Return true if strings are equal.
- *     scopy(from, to)         Copy a string.
  *     number(s)               Convert a string of digits to an integer.
  *     is_number(s)            Return true if s is a string of digits.
  */
@@ -55,25 +59,6 @@ char nullstr[1];             /* zero length string */
  * equal - #defined in mystring.h
  */
 
-/*
- * scopy - #defined in mystring.h
- */
-
-
-/*
- * prefix -- see if pfx is a prefix of string.
- */
-
-int
-prefix(const char *pfx, const char *string)
-{
-       while (*pfx) {
-               if (*pfx++ != *string++)
-                       return 0;
-       }
-       return 1;
-}
-
 
 /*
  * Convert a string of digits to an integer, printing an error message on
@@ -97,9 +82,17 @@ number(const char *s)
 int
 is_number(const char *p)
 {
-       do {
-               if (! is_digit(*p))
+       const char *q;
+
+       if (*p == '\0')
+               return 0;
+       while (*p == '0')
+               p++;
+       for (q = p; *q != '\0'; q++)
+               if (! is_digit(*q))
+                       return 0;
+       if (q - p > 10 ||
+           (q - p == 10 && memcmp(p, "2147483647", 10) > 0))
                        return 0;
-       } while (*++p != '\0');
        return 1;
 }
index 6e5abc2..919fc86 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  *
  *     @(#)mystring.h  8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mystring.h 229219 2012-01-01 22:15:38Z jilles $
+ * $FreeBSD$
  */
 
 #include <string.h>
 
-int prefix(const char *, const char *);
 int number(const char *);
 int is_number(const char *);
 
 #define equal(s1, s2)  (strcmp(s1, s2) == 0)
-#define scopy(s1, s2)  ((void)strcpy(s2, s1))
index cfc3ffd..e99e3ab 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/nodes.c.pat 249235 2013-04-07 16:28:36Z jilles $
+ * $FreeBSD$
  */
 
 #include <sys/param.h>
index a0915b7..d480093 100644 (file)
 # 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.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
@@ -34,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #      @(#)nodetypes   8.2 (Berkeley) 5/4/95
-# $FreeBSD: head/bin/sh/nodetypes 246288 2013-02-03 15:54:57Z jilles $
+# $FreeBSD$
 
 # This file describes the nodes used in parse trees.  Unindented lines
 # contain a node type followed by a structure tag.  Subsequent indented
@@ -122,16 +118,16 @@ NFROMTO nfile                     # fd<> fname
 NAPPEND nfile                  # fd>> fname
 NCLOBBER nfile                 # fd>| fname
        type      int
-       next      nodeptr               # next redirection in list
        fd        int                   # file descriptor being redirected
+       next      nodeptr               # next redirection in list
        fname     nodeptr               # file name, in a NARG node
        expfname  temp  char *expfname  # actual file name
 
 NTOFD ndup                     # fd<&dupfd
 NFROMFD ndup                   # fd>&dupfd
        type      int
-       next      nodeptr               # next redirection in list
        fd        int                   # file descriptor being redirected
+       next      nodeptr               # next redirection in list
        dupfd     int                   # file descriptor to duplicate
        vname     nodeptr               # file name if fd>&$var
 
@@ -139,10 +135,10 @@ NFROMFD ndup                      # fd>&dupfd
 NHERE nhere                    # fd<<\!
 NXHERE nhere                   # fd<<!
        type      int
-       next      nodeptr               # next redirection in list
        fd        int                   # file descriptor being redirected
+       next      nodeptr               # next redirection in list
        doc       nodeptr               # input to command (NARG node)
-       expdoc    temp  char *expdoc    # actual document (for NXHERE)
+       expdoc    temp  const char *expdoc      # actual document (for NXHERE)
 
 NNOT nnot                      # ! command  (actually pipeline)
        type    int
index b9710dd..2d0ddce 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)options.c       8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/options.c 240247 2012-09-08 19:24:03Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <signal.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -59,7 +64,7 @@
 char *arg0;                    /* value of $0 */
 struct shparam shellparam;     /* current positional parameters */
 char **argptr;                 /* argument list for builtin commands */
-const char *shoptarg;          /* set by nextopt (like getopt) */
+char *shoptarg;                        /* set by nextopt (like getopt) */
 char *nextopt_optptr;          /* used by nextopt */
 
 char *minusc;                  /* argument to -c option */
@@ -97,8 +102,6 @@ procargs(int argc, char **argv)
        }
        if (mflag == 2)
                mflag = iflag;
-       /* turn on tabcomplete in an interactive shell by default */
-       tabcomplete = iflag;
        for (i = 0; i < NOPTS; i++)
                if (optlist[i].val == 2)
                        optlist[i].val = 0;
@@ -322,6 +325,7 @@ setparam(char **argv)
        shellparam.malloc = 1;
        shellparam.nparam = nparam;
        shellparam.p = newparam;
+       shellparam.optp = NULL;
        shellparam.reset = 1;
        shellparam.optnext = NULL;
 }
@@ -332,7 +336,7 @@ setparam(char **argv)
  */
 
 void
-freeparam(volatile struct shparam *param)
+freeparam(struct shparam *param)
 {
        char **ap;
 
@@ -341,6 +345,11 @@ freeparam(volatile struct shparam *param)
                        ckfree(*ap);
                ckfree(param->p);
        }
+       if (param->optp) {
+               for (ap = param->optp ; *ap ; ap++)
+                       ckfree(*ap);
+               ckfree(param->optp);
+       }
 }
 
 
@@ -414,20 +423,33 @@ getoptsreset(const char *value)
 int
 getoptscmd(int argc, char **argv)
 {
-       char **optbase = NULL;
+       char **optbase = NULL, **ap;
+       int i;
 
        if (argc < 3)
                error("usage: getopts optstring var [arg]");
-       else if (argc == 3)
-               optbase = shellparam.p;
-       else
-               optbase = &argv[3];
 
        if (shellparam.reset == 1) {
+               INTOFF;
+               if (shellparam.optp) {
+                       for (ap = shellparam.optp ; *ap ; ap++)
+                               ckfree(*ap);
+                       ckfree(shellparam.optp);
+                       shellparam.optp = NULL;
+               }
+               if (argc > 3) {
+                       shellparam.optp = ckmalloc((argc - 2) * sizeof *ap);
+                       memset(shellparam.optp, '\0', (argc - 2) * sizeof *ap);
+                       for (i = 0; i < argc - 3; i++)
+                               shellparam.optp[i] = savestr(argv[i + 3]);
+               }
+               INTON;
+               optbase = argc == 3 ? shellparam.p : shellparam.optp;
                shellparam.optnext = optbase;
                shellparam.optptr = NULL;
                shellparam.reset = 0;
-       }
+       } else
+               optbase = shellparam.optp ? shellparam.optp : shellparam.p;
 
        return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
                       &shellparam.optptr);
@@ -435,7 +457,7 @@ getoptscmd(int argc, char **argv)
 
 static int
 getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
-    char **optp)
+    char **optptr)
 {
        char *p, *q;
        char c = '?';
@@ -443,8 +465,9 @@ getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
        int ind = 0;
        int err = 0;
        char s[10];
+       const char *newoptarg = NULL;
 
-       if ((p = *optp) == NULL || *p == '\0') {
+       if ((p = *optptr) == NULL || *p == '\0') {
                /* Current word is done, advance */
                if (*optnext == NULL)
                        return 1;
@@ -468,14 +491,12 @@ atend:
                        if (optstr[0] == ':') {
                                s[0] = c;
                                s[1] = '\0';
-                               err |= setvarsafe("OPTARG", s, 0);
-                       }
-                       else {
-                               out1fmt("Illegal option -%c\n", c);
-                               unsetvar("OPTARG");
+                               newoptarg = s;
                        }
+                       else
+                               out2fmt_flush("Illegal option -%c\n", c);
                        c = '?';
-                       goto bad;
+                       goto out;
                }
                if (*++q == ':')
                        q++;
@@ -486,33 +507,33 @@ atend:
                        if (optstr[0] == ':') {
                                s[0] = c;
                                s[1] = '\0';
-                               err |= setvarsafe("OPTARG", s, 0);
+                               newoptarg = s;
                                c = ':';
                        }
                        else {
-                               out1fmt("No arg for -%c option\n", c);
-                               unsetvar("OPTARG");
+                               out2fmt_flush("No arg for -%c option\n", c);
                                c = '?';
                        }
-                       goto bad;
+                       goto out;
                }
 
                if (p == **optnext)
                        (*optnext)++;
-               setvarsafe("OPTARG", p, 0);
+               newoptarg = p;
                p = NULL;
        }
-       else
-               setvarsafe("OPTARG", "", 0);
-       ind = *optnext - optfirst + 1;
-       goto out;
-
-bad:
-       ind = 1;
-       *optnext = NULL;
-       p = NULL;
+
 out:
-       *optp = p;
+       if (*optnext != NULL)
+               ind = *optnext - optfirst + 1;
+       *optptr = p;
+       if (newoptarg != NULL)
+               err |= setvarsafe("OPTARG", newoptarg, 0);
+       else {
+               INTOFF;
+               err |= unsetvar("OPTARG");
+               INTON;
+       }
        fmtstr(s, sizeof(s), "%d", ind);
        err |= setvarsafe("OPTIND", s, VNOFUNC);
        s[0] = c;
@@ -520,7 +541,7 @@ out:
        err |= setvarsafe(optvar, s, 0);
        if (err) {
                *optnext = NULL;
-               *optp = NULL;
+               *optptr = NULL;
                flushall();
                exraise(EXERROR);
        }
index 37d33e8..2048a35 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)options.h   8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/options.h 223281 2011-06-18 23:43:28Z jilles $
+ * $FreeBSD$
  */
 
 struct shparam {
@@ -42,6 +38,7 @@ struct shparam {
        unsigned char malloc;   /* if parameter list dynamically allocated */
        unsigned char reset;    /* if getopts has been reset */
        char **p;               /* parameter list */
+       char **optp;            /* parameter list for getopts */
        char **optnext;         /* next parameter to be processed by getopts */
        char *optptr;           /* used by getopts */
 };
@@ -67,9 +64,8 @@ struct shparam {
 #define        Tflag optlist[16].val
 #define        Pflag optlist[17].val
 #define        hflag optlist[18].val
-#define        tabcomplete optlist[19].val
 
-#define NOPTS  20
+#define NOPTS  19
 
 struct optent {
        const char *name;
@@ -77,6 +73,7 @@ struct optent {
        char val;
 };
 
+extern struct optent optlist[NOPTS];
 #ifdef DEFINE_OPTIONS
 struct optent optlist[NOPTS] = {
        { "errexit",    'e',    0 },
@@ -98,10 +95,7 @@ struct optent optlist[NOPTS] = {
        { "trapsasync", 'T',    0 },
        { "physical",   'P',    0 },
        { "trackall",   'h',    0 },
-       { "tabcomplete", '\0',  0 },
 };
-#else
-extern struct optent optlist[NOPTS];
 #endif
 
 
@@ -109,12 +103,12 @@ extern char *minusc;              /* argument to -c option */
 extern char *arg0;             /* $0 */
 extern struct shparam shellparam;  /* $@ */
 extern char **argptr;          /* argument list for builtin commands */
-extern const char *shoptarg;   /* set by nextopt */
+extern char *shoptarg;         /* set by nextopt */
 extern char *nextopt_optptr;   /* used by nextopt */
 
 void procargs(int, char **);
 void optschanged(void);
 void setparam(char **);
-void freeparam(volatile struct shparam *);
+void freeparam(struct shparam *);
 int nextopt(const char *);
 void getoptsreset(const char *);
index 25b9501..d5e57d0 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)output.c        8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/output.c 253649 2013-07-25 13:09:17Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)output.c   8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 /*
  * Shell output routines.  We use our own output routines because:
  *     When a builtin command is interrupted we have to discard
@@ -49,6 +54,8 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #include "shell.h"
 #include "syntax.h"
@@ -106,42 +113,85 @@ outstr(const char *p, struct output *file)
        outbin(p, strlen(p), file);
 }
 
+static void
+byteseq(int ch, struct output *file)
+{
+       char seq[4];
+
+       seq[0] = '\\';
+       seq[1] = (ch >> 6 & 0x3) + '0';
+       seq[2] = (ch >> 3 & 0x7) + '0';
+       seq[3] = (ch & 0x7) + '0';
+       outbin(seq, 4, file);
+}
+
+static void
+outdqstr(const char *p, struct output *file)
+{
+       const char *end;
+       mbstate_t mbs;
+       size_t clen;
+       wchar_t wc;
+
+       memset(&mbs, '\0', sizeof(mbs));
+       end = p + strlen(p);
+       outstr("$'", file);
+       while ((clen = mbrtowc(&wc, p, end - p + 1, &mbs)) != 0) {
+               if (clen == (size_t)-2) {
+                       while (p < end)
+                               byteseq(*p++, file);
+                       break;
+               }
+               if (clen == (size_t)-1) {
+                       memset(&mbs, '\0', sizeof(mbs));
+                       byteseq(*p++, file);
+                       continue;
+               }
+               if (wc == L'\n')
+                       outcslow('\n', file), p++;
+               else if (wc == L'\r')
+                       outstr("\\r", file), p++;
+               else if (wc == L'\t')
+                       outstr("\\t", file), p++;
+               else if (!iswprint(wc)) {
+                       for (; clen > 0; clen--)
+                               byteseq(*p++, file);
+               } else {
+                       if (wc == L'\'' || wc == L'\\')
+                               outcslow('\\', file);
+                       outbin(p, clen, file);
+                       p += clen;
+               }
+       }
+       outcslow('\'', file);
+}
+
 /* Like outstr(), but quote for re-input into the shell. */
 void
 outqstr(const char *p, struct output *file)
 {
-       char ch;
-       int inquotes;
+       int i;
 
        if (p[0] == '\0') {
                outstr("''", file);
                return;
        }
-       /* Caller will handle '=' if necessary */
-       if (p[strcspn(p, "|&;<>()$`\\\"' \t\n*?[~#")] == '\0' ||
+       for (i = 0; p[i] != '\0'; i++) {
+               if ((p[i] > '\0' && p[i] < ' ' && p[i] != '\n') ||
+                   (p[i] & 0x80) != 0 || p[i] == '\'') {
+                       outdqstr(p, file);
+                       return;
+               }
+       }
+
+       if (p[strcspn(p, "|&;<>()$`\\\" \n*?[~#=")] == '\0' ||
                        strcmp(p, "[") == 0) {
                outstr(p, file);
                return;
        }
 
-       inquotes = 0;
-       while ((ch = *p++) != '\0') {
-               switch (ch) {
-               case '\'':
-                       /* Can't quote single quotes inside single quotes. */
-                       if (inquotes)
-                               outcslow('\'', file);
-                       inquotes = 0;
-                       outstr("\\'", file);
-                       break;
-               default:
-                       if (!inquotes)
                                outcslow('\'', file);
-                       inquotes = 1;
-                       outc(ch, file);
-               }
-       }
-       if (inquotes)
+       outstr(p, file);
                outcslow('\'', file);
 }
 
index fab2967..51974d8 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)output.h    8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/output.h 244162 2012-12-12 22:01:10Z jilles $
+ * $FreeBSD$
  */
 
 #ifndef OUTPUT_INCL
index 202023f..8ebb869 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)parser.c        8.7 (Berkeley) 5/16/95
- * $FreeBSD: head/bin/sh/parser.c 253659 2013-07-25 20:50:35Z jilles $
  */
 
-#include <stdio.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)parser.c   8.7 (Berkeley) 5/16/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include "shell.h"
 #include "parser.h"
@@ -61,7 +66,6 @@
  * Shell command parser.
  */
 
-#define        EOFMARKLEN      79
 #define        PROMPTLEN       128
 
 /* values of checkkwd variable */
@@ -91,7 +95,7 @@ static struct heredoc *heredoclist;   /* list of here documents to read */
 static int doprompt;           /* if set, prompt the user */
 static int needprompt;         /* true if interactive and at start of line */
 static int lasttoken;          /* last token read */
-int tokpushback;               /* last token pushed back */
+static int tokpushback;                /* last token pushed back */
 static char *wordtext;         /* text of last word returned by readtoken */
 static int checkkwd;
 static struct nodelist *backquotelist;
@@ -103,12 +107,13 @@ static int funclinno;             /* line # where the current function started */
 static struct parser_temp *parser_temp;
 
 
-static union node *list(int, int);
+static union node *list(int);
 static union node *andor(void);
 static union node *pipeline(void);
 static union node *command(void);
 static union node *simplecmd(union node **, union node *);
 static union node *makename(void);
+static union node *makebinary(int type, union node *n1, union node *n2);
 static void parsefname(void);
 static void parseheredoc(void);
 static int peektoken(void);
@@ -116,9 +121,11 @@ static int readtoken(void);
 static int xxreadtoken(void);
 static int readtoken1(int, const char *, const char *, int);
 static int noexpand(char *);
+static void consumetoken(int);
 static void synexpect(int) __dead2;
 static void synerror(const char *) __dead2;
 static void setprompt(int);
+static int pgetc_linecont(void);
 
 
 static void *
@@ -205,6 +212,7 @@ parsecmd(int interact)
        heredoclist = NULL;
 
        tokpushback = 0;
+       checkkwd = 0;
        doprompt = interact;
        if (doprompt)
                setprompt(1);
@@ -217,18 +225,18 @@ parsecmd(int interact)
        if (t == TNL)
                return NULL;
        tokpushback++;
-       return list(1, 1);
+       return list(1);
 }
 
 
 static union node *
-list(int nlflag, int erflag)
+list(int nlflag)
 {
        union node *ntop, *n1, *n2, *n3;
        int tok;
 
        checkkwd = CHKNL | CHKKWD | CHKALIAS;
-       if (!nlflag && !erflag && tokendlist[peektoken()])
+       if (!nlflag && tokendlist[peektoken()])
                return NULL;
        ntop = n1 = NULL;
        for (;;) {
@@ -250,17 +258,11 @@ list(int nlflag, int erflag)
                if (ntop == NULL)
                        ntop = n2;
                else if (n1 == NULL) {
-                       n1 = (union node *)stalloc(sizeof (struct nbinary));
-                       n1->type = NSEMI;
-                       n1->nbinary.ch1 = ntop;
-                       n1->nbinary.ch2 = n2;
+                       n1 = makebinary(NSEMI, ntop, n2);
                        ntop = n1;
                }
                else {
-                       n3 = (union node *)stalloc(sizeof (struct nbinary));
-                       n3->type = NSEMI;
-                       n3->nbinary.ch1 = n1->nbinary.ch2;
-                       n3->nbinary.ch2 = n2;
+                       n3 = makebinary(NSEMI, n1->nbinary.ch2, n2);
                        n1->nbinary.ch2 = n3;
                        n1 = n3;
                }
@@ -281,8 +283,7 @@ list(int nlflag, int erflag)
                                tokpushback++;
                        }
                        checkkwd = CHKNL | CHKKWD | CHKALIAS;
-                       if (!nlflag && (erflag ? peektoken() == TEOF :
-                           tokendlist[peektoken()]))
+                       if (!nlflag && tokendlist[peektoken()])
                                return ntop;
                        break;
                case TEOF:
@@ -292,7 +293,7 @@ list(int nlflag, int erflag)
                                pungetc();              /* push back EOF on input */
                        return ntop;
                default:
-                       if (nlflag || erflag)
+                       if (nlflag)
                                synexpect(-1);
                        tokpushback++;
                        return ntop;
@@ -305,10 +306,10 @@ list(int nlflag, int erflag)
 static union node *
 andor(void)
 {
-       union node *n1, *n2, *n3;
+       union node *n;
        int t;
 
-       n1 = pipeline();
+       n = pipeline();
        for (;;) {
                if ((t = readtoken()) == TAND) {
                        t = NAND;
@@ -316,14 +317,9 @@ andor(void)
                        t = NOR;
                } else {
                        tokpushback++;
-                       return n1;
+                       return n;
                }
-               n2 = pipeline();
-               n3 = (union node *)stalloc(sizeof (struct nbinary));
-               n3->type = t;
-               n3->nbinary.ch1 = n1;
-               n3->nbinary.ch2 = n2;
-               n1 = n3;
+               n = makebinary(t, n, pipeline());
        }
 }
 
@@ -405,49 +401,39 @@ command(void)
        case TIF:
                n1 = (union node *)stalloc(sizeof (struct nif));
                n1->type = NIF;
-               if ((n1->nif.test = list(0, 0)) == NULL)
+               if ((n1->nif.test = list(0)) == NULL)
                        synexpect(-1);
-               if (readtoken() != TTHEN)
-                       synexpect(TTHEN);
-               n1->nif.ifpart = list(0, 0);
+               consumetoken(TTHEN);
+               n1->nif.ifpart = list(0);
                n2 = n1;
                while (readtoken() == TELIF) {
                        n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
                        n2 = n2->nif.elsepart;
                        n2->type = NIF;
-                       if ((n2->nif.test = list(0, 0)) == NULL)
+                       if ((n2->nif.test = list(0)) == NULL)
                                synexpect(-1);
-                       if (readtoken() != TTHEN)
-                               synexpect(TTHEN);
-                       n2->nif.ifpart = list(0, 0);
+                       consumetoken(TTHEN);
+                       n2->nif.ifpart = list(0);
                }
                if (lasttoken == TELSE)
-                       n2->nif.elsepart = list(0, 0);
+                       n2->nif.elsepart = list(0);
                else {
                        n2->nif.elsepart = NULL;
                        tokpushback++;
                }
-               if (readtoken() != TFI)
-                       synexpect(TFI);
+               consumetoken(TFI);
                checkkwd = CHKKWD | CHKALIAS;
                break;
        case TWHILE:
-       case TUNTIL: {
-               int got;
-               n1 = (union node *)stalloc(sizeof (struct nbinary));
-               n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
-               if ((n1->nbinary.ch1 = list(0, 0)) == NULL)
+       case TUNTIL:
+               t = lasttoken;
+               if ((n1 = list(0)) == NULL)
                        synexpect(-1);
-               if ((got=readtoken()) != TDO) {
-TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
-                       synexpect(TDO);
-               }
-               n1->nbinary.ch2 = list(0, 0);
-               if (readtoken() != TDONE)
-                       synexpect(TDONE);
+               consumetoken(TDO);
+               n1 = makebinary((t == TWHILE)? NWHILE : NUNTIL, n1, list(0));
+               consumetoken(TDONE);
                checkkwd = CHKKWD | CHKALIAS;
                break;
-       }
        case TFOR:
                if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
                        synerror("Bad for loop variable");
@@ -459,10 +445,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
                if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) {
                        app = &ap;
                        while (readtoken() == TWORD) {
-                               n2 = (union node *)stalloc(sizeof (struct narg));
-                               n2->type = NARG;
-                               n2->narg.text = wordtext;
-                               n2->narg.backquote = backquotelist;
+                               n2 = makename();
                                *app = n2;
                                app = &n2->narg.next;
                        }
@@ -494,21 +477,15 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
                        t = TEND;
                else
                        synexpect(-1);
-               n1->nfor.body = list(0, 0);
-               if (readtoken() != t)
-                       synexpect(t);
+               n1->nfor.body = list(0);
+               consumetoken(t);
                checkkwd = CHKKWD | CHKALIAS;
                break;
        case TCASE:
                n1 = (union node *)stalloc(sizeof (struct ncase));
                n1->type = NCASE;
-               if (readtoken() != TWORD)
-                       synexpect(TWORD);
-               n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
-               n2->type = NARG;
-               n2->narg.text = wordtext;
-               n2->narg.backquote = backquotelist;
-               n2->narg.next = NULL;
+               consumetoken(TWORD);
+               n1->ncase.expr = makename();
                while (readtoken() == TNL);
                if (lasttoken != TWORD || ! equal(wordtext, "in"))
                        synerror("expecting \"in\"");
@@ -521,10 +498,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
                        if (lasttoken == TLP)
                                readtoken();
                        for (;;) {
-                               *app = ap = (union node *)stalloc(sizeof (struct narg));
-                               ap->type = NARG;
-                               ap->narg.text = wordtext;
-                               ap->narg.backquote = backquotelist;
+                               *app = ap = makename();
                                checkkwd = CHKNL | CHKKWD;
                                if (readtoken() != TPIPE)
                                        break;
@@ -534,7 +508,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
                        ap->narg.next = NULL;
                        if (lasttoken != TRP)
                                synexpect(TRP);
-                       cp->nclist.body = list(0, 0);
+                       cp->nclist.body = list(0);
 
                        checkkwd = CHKNL | CHKKWD | CHKALIAS;
                        if ((t = readtoken()) != TESAC) {
@@ -554,34 +528,31 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
        case TLP:
                n1 = (union node *)stalloc(sizeof (struct nredir));
                n1->type = NSUBSHELL;
-               n1->nredir.n = list(0, 0);
+               n1->nredir.n = list(0);
                n1->nredir.redirect = NULL;
-               if (readtoken() != TRP)
-                       synexpect(TRP);
+               consumetoken(TRP);
                checkkwd = CHKKWD | CHKALIAS;
                is_subshell = 1;
                break;
        case TBEGIN:
-               n1 = list(0, 0);
-               if (readtoken() != TEND)
-                       synexpect(TEND);
+               n1 = list(0);
+               consumetoken(TEND);
                checkkwd = CHKKWD | CHKALIAS;
                break;
-       /* Handle an empty command like other simple commands.  */
+       /* A simple command must have at least one redirection or word. */
        case TBACKGND:
        case TSEMI:
        case TAND:
        case TOR:
-               /*
-                * An empty command before a ; doesn't make much sense, and
-                * should certainly be disallowed in the case of `if ;'.
-                */
+       case TPIPE:
+       case TENDCASE:
+       case TFALLTHRU:
+       case TEOF:
+       case TNL:
+       case TRP:
                if (!redir)
                        synexpect(-1);
-       case TNL:
-       case TEOF:
        case TWORD:
-       case TRP:
                tokpushback++;
                n1 = simplecmd(rpp, redir);
                return n1;
@@ -622,7 +593,7 @@ simplecmd(union node **rpp, union node *redir)
 
        /* If we don't have any redirections already, then we must reset */
        /* rpp to be the address of the local redir variable.  */
-       if (redir == NULL)
+       if (redir == 0)
                rpp = &redir;
 
        args = NULL;
@@ -639,10 +610,7 @@ simplecmd(union node **rpp, union node *redir)
        for (;;) {
                checkkwd = savecheckkwd;
                if (readtoken() == TWORD) {
-                       n = (union node *)stalloc(sizeof (struct narg));
-                       n->type = NARG;
-                       n->narg.text = wordtext;
-                       n->narg.backquote = backquotelist;
+                       n = makename();
                        *app = n;
                        app = &n->narg.next;
                        if (savecheckkwd != 0 && !isassignment(wordtext))
@@ -654,8 +622,7 @@ simplecmd(union node **rpp, union node *redir)
                } else if (lasttoken == TLP && app == &args->narg.next
                                            && rpp == orig_rpp) {
                        /* We have a function */
-                       if (readtoken() != TRP)
-                               synexpect(TRP);
+                       consumetoken(TRP);
                        funclinno = plinno;
                        /*
                         * - Require plain text.
@@ -703,6 +670,24 @@ makename(void)
        return n;
 }
 
+static union node *
+makebinary(int type, union node *n1, union node *n2)
+{
+       union node *n;
+
+       n = (union node *)stalloc(sizeof (struct nbinary));
+       n->type = type;
+       n->nbinary.ch1 = n1;
+       n->nbinary.ch2 = n2;
+       return (n);
+}
+
+void
+forcealias(void)
+{
+       checkkwd |= CHKALIAS;
+}
+
 void
 fixredir(union node *n, const char *text, int err)
 {
@@ -729,12 +714,10 @@ parsefname(void)
 {
        union node *n = redirnode;
 
-       if (readtoken() != TWORD)
-               synexpect(-1);
+       consumetoken(TWORD);
        if (n->type == NHERE) {
                struct heredoc *here = heredoc;
                struct heredoc *p;
-               int i;
 
                if (quoteflag == 0)
                        n->type = NXHERE;
@@ -743,7 +726,7 @@ parsefname(void)
                        while (*wordtext == '\t')
                                wordtext++;
                }
-               if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
+               if (! noexpand(wordtext))
                        synerror("Illegal eof marker for << redirection");
                rmescapes(wordtext);
                here->eofmark = wordtext;
@@ -781,11 +764,7 @@ parseheredoc(void)
                }
                readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
                                here->eofmark, here->striptabs);
-               n = (union node *)stalloc(sizeof (struct narg));
-               n->narg.type = NARG;
-               n->narg.next = NULL;
-               n->narg.text = wordtext;
-               n->narg.backquote = backquotelist;
+               n = makename();
                here->here->nhere.doc = n;
        }
 }
@@ -911,7 +890,9 @@ xxreadtoken(void)
                                continue;
                        }
                        pungetc();
-                       goto breakloop;
+                       /* FALLTHROUGH */
+               default:
+                       return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
                case '\n':
                        plinno++;
                        needprompt = doprompt;
@@ -919,17 +900,17 @@ xxreadtoken(void)
                case PEOF:
                        RETURN(TEOF);
                case '&':
-                       if (pgetc() == '&')
+                       if (pgetc_linecont() == '&')
                                RETURN(TAND);
                        pungetc();
                        RETURN(TBACKGND);
                case '|':
-                       if (pgetc() == '|')
+                       if (pgetc_linecont() == '|')
                                RETURN(TOR);
                        pungetc();
                        RETURN(TPIPE);
                case ';':
-                       c = pgetc();
+                       c = pgetc_linecont();
                        if (c == ';')
                                RETURN(TENDCASE);
                        else if (c == '&')
@@ -940,17 +921,13 @@ xxreadtoken(void)
                        RETURN(TLP);
                case ')':
                        RETURN(TRP);
-               default:
-                       goto breakloop;
                }
        }
-breakloop:
-       return readtoken1(c, BASESYNTAX, NULL, 0);
 #undef RETURN
 }
 
 
-#define MAXNEST_STATIC 8
+#define MAXNEST_static 8
 struct tokenstate
 {
        const char *syntax; /* *SYNTAX */
@@ -965,6 +942,98 @@ struct tokenstate
 };
 
 
+/*
+ * Check to see whether we are at the end of the here document.  When this
+ * is called, c is set to the first character of the next input line.  If
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ * The new value of c is returned.
+ */
+
+static int
+checkend(int c, const char *eofmark, int striptabs)
+{
+       if (striptabs) {
+               while (c == '\t')
+                       c = pgetc();
+       }
+       if (c == *eofmark) {
+               int c2;
+               const char *q;
+
+               for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++)
+                       ;
+               if ((c2 == PEOF || c2 == '\n') && *q == '\0') {
+                       c = PEOF;
+                       if (c2 == '\n') {
+                               plinno++;
+                               needprompt = doprompt;
+                       }
+               } else {
+                       pungetc();
+                       pushstring(eofmark + 1, q - (eofmark + 1), NULL);
+               }
+       }
+       return (c);
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+static void
+parseredir(char *out, int c)
+{
+       char fd = *out;
+       union node *np;
+
+       np = (union node *)stalloc(sizeof (struct nfile));
+       if (c == '>') {
+               np->nfile.fd = 1;
+               c = pgetc_linecont();
+               if (c == '>')
+                       np->type = NAPPEND;
+               else if (c == '&')
+                       np->type = NTOFD;
+               else if (c == '|')
+                       np->type = NCLOBBER;
+               else {
+                       np->type = NTO;
+                       pungetc();
+               }
+       } else {        /* c == '<' */
+               np->nfile.fd = 0;
+               c = pgetc_linecont();
+               if (c == '<') {
+                       if (sizeof (struct nfile) != sizeof (struct nhere)) {
+                               np = (union node *)stalloc(sizeof (struct nhere));
+                               np->nfile.fd = 0;
+                       }
+                       np->type = NHERE;
+                       heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+                       heredoc->here = np;
+                       if ((c = pgetc_linecont()) == '-') {
+                               heredoc->striptabs = 1;
+                       } else {
+                               heredoc->striptabs = 0;
+                               pungetc();
+                       }
+               } else if (c == '&')
+                       np->type = NFROMFD;
+               else if (c == '>')
+                       np->type = NFROMTO;
+               else {
+                       np->type = NFROM;
+                       pungetc();
+               }
+       }
+       if (fd != '\0')
+               np->nfile.fd = digit_val(fd);
+       redirnode = np;
+}
+
 /*
  * Called to parse command substitutions.
  */
@@ -1011,13 +1080,13 @@ parsebackq(char *out, struct nodelist **pbqlist,
        heredoclist = NULL;
        INTON;
        if (oldstyle) {
-               /*
-                * We must read until the closing backquote, giving special
-                * treatment to some slashes, and then push the string and
-                * reread it as input, interpreting it normally.
-                */
+                /* We must read until the closing backquote, giving special
+                   treatment to some slashes, and then push the string and
+                   reread it as input, interpreting it normally.  */
                char *oout;
-               int c, olen;
+                int c;
+                int olen;
+
 
                STARTSTACKSTR(oout);
                for (;;) {
@@ -1026,25 +1095,12 @@ parsebackq(char *out, struct nodelist **pbqlist,
                                needprompt = 0;
                        }
                        CHECKSTRSPACE(2, oout);
-                       switch (c = pgetc()) {
-                       case '`':
-                               goto done;
-
+                       c = pgetc_linecont();
+                       if (c == '`')
+                               break;
+                       switch (c) {
                        case '\\':
-                               if ((c = pgetc()) == '\n') {
-                                       plinno++;
-                                       if (doprompt)
-                                               setprompt(2);
-                                       else
-                                               setprompt(0);
-                                       /*
-                                        * If eating a newline, avoid putting
-                                        * the newline into the new character
-                                        * stream (via the USTPUTC after the
-                                        * switch).
-                                        */
-                                       continue;
-                               }
+                               c = pgetc();
                                if (c != '\\' && c != '`' && c != '$'
                                    && (!dblquote || c != '"'))
                                        USTPUTC('\\', oout);
@@ -1065,7 +1121,6 @@ parsebackq(char *out, struct nodelist **pbqlist,
                        }
                        USTPUTC(c, oout);
                }
-done:
                USTPUTC('\0', oout);
                olen = oout - stackblock();
                INTOFF;
@@ -1085,14 +1140,14 @@ done:
                doprompt = 0;
        }
 
-       n = list(0, oldstyle);
+       n = list(0);
 
-       if (oldstyle)
+       if (oldstyle) {
+               if (peektoken() != TEOF)
+                       synexpect(-1);
                doprompt = saveprompt;
-       else {
-               if (readtoken() != TRP)
-                       synexpect(TRP);
-       }
+       } else
+               consumetoken(TRP);
 
        (*nlpp)->n = n;
        if (oldstyle) {
@@ -1266,6 +1321,13 @@ readcstyleesc(char *out)
                                c = pgetc();
                        if (c == PEOF)
                                synerror("Unterminated quoted string");
+                       if (c == '\n') {
+                               plinno++;
+                               if (doprompt)
+                                       setprompt(2);
+                               else
+                                       setprompt(0);
+                       }
                }
                pungetc();
                return out;
@@ -1289,8 +1351,6 @@ readcstyleesc(char *out)
  * will run code that appears at the end of readtoken1.
  */
 
-#define CHECKEND()     {goto checkend; checkend_return:;}
-#define PARSEREDIR()   {goto parseredir; parseredir_return:;}
 #define PARSESUB()     {goto parsesub; parsesub_return:;}
 #define        PARSEARITH()    {goto parsearith; parsearith_return:;}
 
@@ -1299,16 +1359,15 @@ readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
     int striptabs)
 {
        int c = firstc;
-       char * volatile out;
+       char *out;
        int len;
-       char line[EOFMARKLEN + 1];
        struct nodelist *bqlist;
-       volatile int quotef;
+       int quotef;
        int newvarnest;
        int level;
        int synentry;
-       struct tokenstate state_static[MAXNEST_STATIC];
-       int maxnest = MAXNEST_STATIC;
+       struct tokenstate state_static[MAXNEST_static];
+       int maxnest = MAXNEST_static;
        struct tokenstate *state = state_static;
        int sqiscstyle = 0;
 
@@ -1323,7 +1382,9 @@ readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
 
        STARTSTACKSTR(out);
        loop: { /* for each line, until end of word */
-               CHECKEND();     /* set c to PEOF if at end of here document */
+               if (eofmark)
+                       /* set c to PEOF if at end of here document */
+                       c = checkend(c, eofmark, striptabs);
                for (;;) {      /* until end of line or end of word */
                        CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
 
@@ -1434,7 +1495,7 @@ readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
                                        USTPUTC(c, out);
                                        --state[level].parenlevel;
                                } else {
-                                       if (pgetc() == ')') {
+                                       if (pgetc_linecont() == ')') {
                                                if (level > 0 &&
                                                    state[level].category == TSTATE_ARITH) {
                                                        level--;
@@ -1489,7 +1550,7 @@ endword:
                 && quotef == 0
                 && len <= 2
                 && (*out == '\0' || is_digit(*out))) {
-                       PARSEREDIR();
+                       parseredir(out, c);
                        return lasttoken = TREDIR;
                } else {
                        pungetc();
@@ -1503,97 +1564,6 @@ endword:
 /* end of readtoken routine */
 
 
-/*
- * Check to see whether we are at the end of the here document.  When this
- * is called, c is set to the first character of the next input line.  If
- * we are at the end of the here document, this routine sets the c to PEOF.
- */
-
-checkend: {
-       if (eofmark) {
-               if (striptabs) {
-                       while (c == '\t')
-                               c = pgetc();
-               }
-               if (c == *eofmark) {
-                       if (pfgets(line, sizeof line) != NULL) {
-                               const char *p, *q;
-
-                               p = line;
-                               for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
-                               if ((*p == '\0' || *p == '\n') && *q == '\0') {
-                                       c = PEOF;
-                                       if (*p == '\n') {
-                                               plinno++;
-                                               needprompt = doprompt;
-                                       }
-                               } else {
-                                       pushstring(line, strlen(line), NULL);
-                               }
-                       }
-               }
-       }
-       goto checkend_return;
-}
-
-
-/*
- * Parse a redirection operator.  The variable "out" points to a string
- * specifying the fd to be redirected.  The variable "c" contains the
- * first character of the redirection operator.
- */
-
-parseredir: {
-       char fd = *out;
-       union node *np;
-
-       np = (union node *)stalloc(sizeof (struct nfile));
-       if (c == '>') {
-               np->nfile.fd = 1;
-               c = pgetc();
-               if (c == '>')
-                       np->type = NAPPEND;
-               else if (c == '&')
-                       np->type = NTOFD;
-               else if (c == '|')
-                       np->type = NCLOBBER;
-               else {
-                       np->type = NTO;
-                       pungetc();
-               }
-       } else {        /* c == '<' */
-               np->nfile.fd = 0;
-               c = pgetc();
-               if (c == '<') {
-                       if (sizeof (struct nfile) != sizeof (struct nhere)) {
-                               np = (union node *)stalloc(sizeof (struct nhere));
-                               np->nfile.fd = 0;
-                       }
-                       np->type = NHERE;
-                       heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
-                       heredoc->here = np;
-                       if ((c = pgetc()) == '-') {
-                               heredoc->striptabs = 1;
-                       } else {
-                               heredoc->striptabs = 0;
-                               pungetc();
-                       }
-               } else if (c == '&')
-                       np->type = NFROMFD;
-               else if (c == '>')
-                       np->type = NFROMTO;
-               else {
-                       np->type = NFROM;
-                       pungetc();
-               }
-       }
-       if (fd != '\0')
-               np->nfile.fd = digit_val(fd);
-       redirnode = np;
-       goto parseredir_return;
-}
-
-
 /*
  * Parse a substitution.  At this point, we have read the dollar sign
  * and nothing else.
@@ -1611,9 +1581,9 @@ parsesub: {
        int length;
        int c1;
 
-       c = pgetc();
+       c = pgetc_linecont();
        if (c == '(') { /* $(command) or $((arith)) */
-               if (pgetc() == '(') {
+               if (pgetc_linecont() == '(') {
                        PARSEARITH();
                } else {
                        pungetc();
@@ -1631,7 +1601,7 @@ parsesub: {
                flags = 0;
                if (c == '{') {
                        bracketed_name = 1;
-                       c = pgetc();
+                       c = pgetc_linecont();
                        subtype = 0;
                }
 varname:
@@ -1639,7 +1609,7 @@ varname:
                        length = 0;
                        do {
                                STPUTC(c, out);
-                               c = pgetc();
+                               c = pgetc_linecont();
                                length++;
                        } while (!is_eof(c) && is_in_name(c));
                        if (length == 6 &&
@@ -1658,22 +1628,22 @@ varname:
                        if (bracketed_name) {
                                do {
                                        STPUTC(c, out);
-                                       c = pgetc();
+                                       c = pgetc_linecont();
                                } while (is_digit(c));
                        } else {
                                STPUTC(c, out);
-                               c = pgetc();
+                               c = pgetc_linecont();
                        }
                } else if (is_special(c)) {
                        c1 = c;
-                       c = pgetc();
+                       c = pgetc_linecont();
                        if (subtype == 0 && c1 == '#') {
                                subtype = VSLENGTH;
                                if (strchr(types, c) == NULL && c != ':' &&
                                    c != '#' && c != '%')
                                        goto varname;
                                c1 = c;
-                               c = pgetc();
+                               c = pgetc_linecont();
                                if (c1 != '}' && c == '}') {
                                        pungetc();
                                        c = c1;
@@ -1698,7 +1668,7 @@ varname:
                        switch (c) {
                        case ':':
                                flags |= VSNUL;
-                               c = pgetc();
+                               c = pgetc_linecont();
                                /*FALLTHROUGH*/
                        default:
                                p = strchr(types, c);
@@ -1718,7 +1688,7 @@ varname:
                                        int cc = c;
                                        subtype = c == '#' ? VSTRIMLEFT :
                                                             VSTRIMRIGHT;
-                                       c = pgetc();
+                                       c = pgetc_linecont();
                                        if (c == cc)
                                                subtype++;
                                        else
@@ -1743,7 +1713,7 @@ varname:
                                        state = parser_temp_alloc(
                                            maxnest * sizeof(*state));
                                        memcpy(state, state_static,
-                                           MAXNEST_STATIC * sizeof(*state));
+                                           MAXNEST_static * sizeof(*state));
                                } else
                                        state = parser_temp_realloc(state,
                                            maxnest * sizeof(*state));
@@ -1794,7 +1764,7 @@ parsearith: {
                        state = parser_temp_alloc(
                            maxnest * sizeof(*state));
                        memcpy(state, state_static,
-                           MAXNEST_STATIC * sizeof(*state));
+                           MAXNEST_static * sizeof(*state));
                } else
                        state = parser_temp_realloc(state,
                            maxnest * sizeof(*state));
@@ -1814,14 +1784,6 @@ parsearith: {
 } /* end of readtoken */
 
 
-void
-resetparser(void)
-{
-       tokpushback = 0;
-       checkkwd = 0;
-}
-
-
 /*
  * Returns true if the text contains nothing to expand (no dollar signs
  * or backquotes).
@@ -1883,6 +1845,14 @@ isassignment(const char *p)
 }
 
 
+static void
+consumetoken(int token)
+{
+       if (readtoken() != token)
+               synexpect(token);
+}
+
+
 /*
  * Called when an unexpected token is read during the parse.  The argument
  * is the token that is expected, or -1 if more than one type of token can
@@ -1909,8 +1879,10 @@ synerror(const char *msg)
 {
        if (commandname)
                outfmt(out2, "%s: %d: ", commandname, startlinno);
+       else if (arg0)
+               outfmt(out2, "%s: ", arg0);
        outfmt(out2, "Syntax error: %s\n", msg);
-       error(NULL);
+       error((char *)NULL);
 }
 
 static void
@@ -1927,17 +1899,41 @@ setprompt(int which)
        }
 }
 
+static int
+pgetc_linecont(void)
+{
+       int c;
+
+       while ((c = pgetc_macro()) == '\\') {
+               c = pgetc();
+               if (c == '\n') {
+                       plinno++;
+                       if (doprompt)
+                               setprompt(2);
+                       else
+                               setprompt(0);
+               } else {
+                       pungetc();
+                       /* Allow the backslash to be pushed back. */
+                       pushstring("\\", 1, NULL);
+                       return (pgetc());
+               }
+       }
+       return (c);
+}
+
 /*
  * called by editline -- any expansions to the prompt
  *    should be added here.
  */
-const char *
+char *
 getprompt(void *unused __unused)
 {
        static char ps[PROMPTLEN];
        const char *fmt;
        const char *pwd;
        int i, trim;
+       static char internal_error[] = "??";
 
        /*
         * Select prompt format.
@@ -1953,7 +1949,7 @@ getprompt(void *unused __unused)
                fmt = ps2val();
                break;
        default:
-               return "??";
+               return internal_error;
        }
 
        /*
@@ -2048,7 +2044,7 @@ expandstr(const char *ps)
                parser_temp = NULL;
                setinputstring(ps, 1);
                doprompt = 0;
-               readtoken1(pgetc(), DQSYNTAX, __DECONST(char *, "\n\n"), 0);
+               readtoken1(pgetc(), DQSYNTAX, "", 0);
                if (backquotelist != NULL)
                        error("Command substitution not allowed here");
 
index 9457eb0..5982594 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)parser.h    8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/parser.h 253650 2013-07-25 15:08:41Z jilles $
+ * $FreeBSD$
  */
 
 /* control characters in argument strings */
 
 /*
  * NEOF is returned by parsecmd when it encounters an end of file.  It
- * must be distinct from NULL, so we use the address of a variable that
- * happens to be handy.
+ * must be distinct from NULL.
  */
-extern int tokpushback;
-#define NEOF ((union node *)&tokpushback)
+#define NEOF ((union node *)-1)
 extern int whichprompt;                /* 1 == PS1, 2 == PS2 */
 extern const char *const parsekwd[];
 
 
 union node *parsecmd(int);
+void forcealias(void);
 void fixredir(union node *, const char *, int);
-void resetparser(void);
 int goodname(const char *);
 int isassignment(const char *);
-const char *getprompt(void *);
+char *getprompt(void *);
 const char *expandstr(const char *);
index 7c03c36..95d3238 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)redir.c 8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/redir.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)redir.c    8.2 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <signal.h>
@@ -64,6 +69,7 @@
 struct redirtab {
        struct redirtab *next;
        int renamed[10];
+       int fd0_redirected;
 };
 
 
@@ -86,6 +92,13 @@ static int openhere(union node *);
  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
  * standard output, and the standard error if it becomes a duplicate of
  * stdout, is saved in memory.
+*
+ * We suppress interrupts so that we won't leave open file
+ * descriptors around.  Because the signal handler remains
+ * installed and we do not use system call restart, interrupts
+ * will still abort blocking opens such as fifos (they will fail
+ * with EINTR). There is, however, a race condition if an interrupt
+ * arrives after INTOFF and before open blocks.
  */
 
 void
@@ -97,6 +110,7 @@ redirect(union node *redir, int flags)
        int fd;
        char memory[10];        /* file descriptors to write to memory */
 
+       INTOFF;
        for (i = 10 ; --i >= 0 ; )
                memory[i] = 0;
        memory[1] = flags & REDIR_BACKQ;
@@ -104,22 +118,21 @@ redirect(union node *redir, int flags)
                sv = ckmalloc(sizeof (struct redirtab));
                for (i = 0 ; i < 10 ; i++)
                        sv->renamed[i] = EMPTY;
+               sv->fd0_redirected = fd0_redirected;
                sv->next = redirlist;
                redirlist = sv;
        }
        for (n = redir ; n ; n = n->nfile.next) {
                fd = n->nfile.fd;
+               if (fd == 0)
+                       fd0_redirected = 1;
                if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
                    n->ndup.dupfd == fd)
                        continue; /* redirect from/to same file descriptor */
 
                if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
                        INTOFF;
-#ifndef F_DUPFD_CLOEXEC
-                       if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
-#else
                        if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) {
-#endif
                                switch (errno) {
                                case EBADF:
                                        i = CLOSED;
@@ -130,21 +143,18 @@ redirect(union node *redir, int flags)
                                        break;
                                }
                        }
-#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
-                       else
-                               fcntl(i, F_SETFD, FD_CLOEXEC);
-#endif
                        sv->renamed[fd] = i;
                        INTON;
                }
-               if (fd == 0)
-                       fd0_redirected++;
                openredirect(n, memory);
+               INTON;
+               INTOFF;
        }
        if (memory[1])
                out1 = &memout;
        if (memory[2])
                out2 = &memout;
+       INTON;
 }
 
 
@@ -153,40 +163,22 @@ openredirect(union node *redir, char memory[10])
 {
        struct stat sb;
        int fd = redir->nfile.fd;
-       char *fname;
-       int f = 0;
+       const char *fname;
+       int f;
        int e;
 
-       /*
-        * We suppress interrupts so that we won't leave open file
-        * descriptors around.  Because the signal handler remains
-        * installed and we do not use system call restart, interrupts
-        * will still abort blocking opens such as fifos (they will fail
-        * with EINTR). There is, however, a race condition if an interrupt
-        * arrives after INTOFF and before open blocks.
-        */
-       INTOFF;
        memory[fd] = 0;
        switch (redir->nfile.type) {
        case NFROM:
                fname = redir->nfile.expfname;
                if ((f = open(fname, O_RDONLY)) < 0)
                        error("cannot open %s: %s", fname, strerror(errno));
-movefd:
-               if (f != fd) {
-                       if (dup2(f, fd) == -1) {
-                               e = errno;
-                               close(f);
-                               error("%d: %s", fd, strerror(e));
-                       }
-                       close(f);
-               }
                break;
        case NFROMTO:
                fname = redir->nfile.expfname;
                if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
                        error("cannot create %s: %s", fname, strerror(errno));
-               goto movefd;
+               break;
        case NTO:
                if (Cflag) {
                        fname = redir->nfile.expfname;
@@ -204,19 +196,19 @@ movefd:
                        } else
                                error("cannot create %s: %s", fname,
                                    strerror(EEXIST));
-                       goto movefd;
+                       break;
                }
                /* FALLTHROUGH */
        case NCLOBBER:
                fname = redir->nfile.expfname;
                if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
                        error("cannot create %s: %s", fname, strerror(errno));
-               goto movefd;
+               break;
        case NAPPEND:
                fname = redir->nfile.expfname;
                if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
                        error("cannot create %s: %s", fname, strerror(errno));
-               goto movefd;
+               break;
        case NTOFD:
        case NFROMFD:
                if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
@@ -230,15 +222,22 @@ movefd:
                } else {
                        close(fd);
                }
-               break;
+               return;
        case NHERE:
        case NXHERE:
                f = openhere(redir);
-               goto movefd;
+               break;
        default:
                abort();
        }
-       INTON;
+       if (f != fd) {
+               if (dup2(f, fd) == -1) {
+                       e = errno;
+                       close(f);
+                       error("%d: %s", fd, strerror(e));
+               }
+               close(f);
+       }
 }
 
 
@@ -251,7 +250,7 @@ movefd:
 static int
 openhere(union node *redir)
 {
-       char *p;
+       const char *p;
        int pip[2];
        size_t len = 0;
        int flags;
@@ -277,7 +276,7 @@ openhere(union node *redir)
                fcntl(pip[1], F_SETFL, flags);
        }
 
-       if (forkshell(NULL, NULL, FORK_NOJOB) == 0) {
+       if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
                close(pip[0]);
                signal(SIGINT, SIG_IGN);
                signal(SIGQUIT, SIG_IGN);
@@ -306,8 +305,6 @@ popredir(void)
 
        for (i = 0 ; i < 10 ; i++) {
                if (rp->renamed[i] != EMPTY) {
-                        if (i == 0)
-                                fd0_redirected--;
                        if (rp->renamed[i] >= 0) {
                                dup2(rp->renamed[i], i);
                                close(rp->renamed[i]);
@@ -317,23 +314,12 @@ popredir(void)
                }
        }
        INTOFF;
+       fd0_redirected = rp->fd0_redirected;
        redirlist = rp->next;
        ckfree(rp);
        INTON;
 }
 
-/*
- * Undo all redirections.  Called on error or interrupt.
- */
-
-void
-resetredir(void)
-{
-       while (redirlist)
-               popredir();
-}
-
-
 /* Return true if fd 0 has already been redirected at least once.  */
 int
 fd0_redirected_p(void)
index 7689df1..4fdc04d 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)redir.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/redir.h 253650 2013-07-25 15:08:41Z jilles $
+ * $FreeBSD$
  */
 
 /* flags passed to redirect */
@@ -44,6 +40,5 @@
 union node;
 void redirect(union node *, int);
 void popredir(void);
-void resetredir(void);
 int fd0_redirected_p(void);
 void clearredir(void);
index 088fa66..e5707c0 100644 (file)
@@ -13,7 +13,7 @@
 .\" 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.
-.\" 3. Neither the name of the University nor the names of its contributors
+.\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -30,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    from: @(#)sh.1  8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: head/bin/sh/sh.1 251763 2013-06-14 22:06:18Z jilles $
+.\" $FreeBSD$
 .\"
-.Dd June 14, 2013
+.Dd April 18, 2015
 .Dt SH 1
 .Os
 .Sh NAME
 .Nd command interpreter (shell)
 .Sh SYNOPSIS
 .Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
 .Op Fl /+o Ar longname
 .Oo
 .Ar script
 .Op Ar arg ...
 .Oc
 .Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
 .Op Fl /+o Ar longname
 .Fl c Ar string
 .Oo
@@ -55,7 +55,7 @@
 .Op Ar arg ...
 .Oc
 .Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
 .Op Fl /+o Ar longname
 .Fl s
 .Op Ar arg ...
@@ -235,10 +235,16 @@ or
 .Dq Li ||
 operator; or if the command is a pipeline preceded by the
 .Ic !\&
-operator.
+keyword.
 If a shell function is executed and its exit status is explicitly
 tested, all commands of the function are considered to be tested as
 well.
+.Pp
+It is recommended to check for failures explicitly
+instead of relying on
+.Fl e
+because it tends to behave in unexpected ways,
+particularly in larger scripts.
 .It Fl f Li noglob
 Disable pathname expansion.
 .It Fl h Li trackall
@@ -253,6 +259,12 @@ from input when in interactive mode.
 Force the shell to behave interactively.
 .It Fl m Li monitor
 Turn on job control (set automatically when interactive).
+A new process group is created for each pipeline (called a job).
+It is possible to suspend jobs or to have them run in the foreground or
+in the background.
+In a non-interactive shell,
+this option can be set even if no terminal is available
+and is useful to place processes in separate process groups.
 .It Fl n Li noexec
 If not interactive, read commands but do not
 execute them.
@@ -331,13 +343,6 @@ Write each command
 variable subjected to parameter expansion and arithmetic expansion)
 to standard error before it is executed.
 Useful for debugging.
-.It "\ \ " Em tabcomplete
-Enables filename completion in the command line editor.
-Typing a tab character will extend the current input word to match a
-filename.
-If more than one filename matches it is only extended to be the common prefix.
-Typing a second tab character will list all the matching names.
-Turned on by default in an interactive shell.
 .El
 .Pp
 The
@@ -534,6 +539,20 @@ would become
 .Pp
 .Dl "ls -F foobar"
 .Pp
+Aliases are also recognized after an alias
+whose value ends with a space or tab.
+For example, if there is also an alias called
+.Dq Li nohup
+with the value
+.Dq Li "nohup " ,
+then the input
+.Pp
+.Dl "nohup lf foobar"
+.Pp
+would become
+.Pp
+.Dl "nohup ls -F foobar"
+.Pp
 Aliases provide a convenient way for naive users to
 create shorthands for commands without having to learn how
 to create functions with arguments.
@@ -571,7 +590,8 @@ the following actions:
 Leading words of the form
 .Dq Li name=value
 are stripped off and assigned to the environment of
-the simple command.
+the simple command
+(they do not affect expansions).
 Redirection operators and
 their arguments (as described below) are stripped
 off and saved for processing.
@@ -775,10 +795,13 @@ should indicate the various exit codes and what they mean.
 Additionally, the built-in commands return exit codes, as does
 an executed shell function.
 .Pp
-If a command is terminated by a signal, its exit status is 128 plus
-the signal number.
-Signal numbers are defined in the header file
-.In sys/signal.h .
+If a command is terminated by a signal, its exit status is greater than 128.
+The signal name can be found by passing the exit status to
+.Li kill -l .
+.Pp
+If there is no command word,
+the exit status is the exit status of the last command substitution executed,
+or zero if the command does not contain any command substitutions.
 .Ss Complex Commands
 Complex commands are combinations of simple commands
 with control operators or keywords, together creating a larger complex
@@ -798,7 +821,8 @@ function definition
 .El
 .Pp
 Unless otherwise stated, the exit status of a command is
-that of the last simple command executed by the command.
+that of the last simple command executed by the command,
+or zero if no simple command was executed.
 .Ss Pipelines
 A pipeline is a sequence of one or more commands separated
 by the control operator
@@ -882,6 +906,8 @@ The format for running a command in background is:
 If the shell is not interactive, the standard input of an
 asynchronous command is set to
 .Pa /dev/null .
+.Pp
+The exit status is zero.
 .Ss Lists (Generally Speaking)
 A list is a sequence of zero or more commands separated by
 newlines, semicolons, or ampersands,
@@ -920,6 +946,13 @@ command is:
 .Ic fi
 .Ed
 .Pp
+The exit status is that of selected
+.Ic then
+or
+.Ic else
+list,
+or zero if no list was selected.
+.Pp
 The syntax of the
 .Ic while
 command is:
@@ -940,6 +973,9 @@ in place of
 which causes it to
 repeat until the exit status of the first list is zero.
 .Pp
+The exit status is that of the last execution of the second list,
+or zero if it was never executed.
+.Pp
 The syntax of the
 .Ic for
 command is:
@@ -1020,10 +1056,6 @@ continuing until a list terminated with
 or the end of the
 .Ic case
 command.
-The exit code of the
-.Ic case
-command is the exit code of the last command executed in the list or
-zero if no patterns were matched.
 .Ss Grouping Commands Together
 Commands may be grouped by writing either
 .Pp
@@ -1111,6 +1143,8 @@ and the syntax is:
 The
 .Ic local
 command is implemented as a built-in command.
+The exit status is zero
+unless the command is not in a function or a variable name is invalid.
 .Pp
 When a variable is made local, it inherits the initial
 value and exported and readonly flags from the variable
@@ -1152,25 +1186,28 @@ command is
 .Pp
 .D1 Ic return Op Ar exitstatus
 .Pp
-It terminates the current executional scope, returning from the previous
-nested function, sourced script, or shell instance, in that order.
+It terminates the current executional scope, returning from the closest
+nested function or sourced script;
+if no function or sourced script is being executed,
+it exits the shell instance.
 The
 .Ic return
 command is implemented as a special built-in command.
 .Ss Variables and Parameters
 The shell maintains a set of parameters.
 A parameter
-denoted by a name is called a variable.
+denoted by a name
+(consisting solely
+of alphabetics, numerics, and underscores,
+and starting with an alphabetic or an underscore)
+is called a variable.
 When starting up,
-the shell turns all the environment variables into shell
+the shell turns all environment variables with valid names into shell
 variables.
 New variables can be set using the form
 .Pp
 .D1 Ar name Ns = Ns Ar value
 .Pp
-Variables set by the user must have a name consisting solely
-of alphabetics, numerics, and underscores.
-The first letter of a variable name must not be numeric.
 A parameter can also be denoted by a number
 or a special character as explained below.
 .Pp
@@ -1333,6 +1370,10 @@ This variable overrides the
 .Va MAIL
 setting.
 There is a maximum of 10 mailboxes that can be monitored at once.
+.It Va OPTIND
+The index of the next argument to be processed by
+.Ic getopts .
+This is initialized to 1 at startup.
 .It Va PATH
 The default search path for executables.
 See the
@@ -1864,7 +1905,7 @@ it is sought in the current working directory.
 .It Ic \&[
 A built-in equivalent of
 .Xr test 1 .
-.It Ic alias Oo Ar name Ns Oo = Ns Ar string Oc Ar ... Oc
+.It Ic alias Oo Ar name Ns Oo = Ns Ar string Oc ... Oc
 If
 .Ar name Ns = Ns Ar string
 is specified, the shell defines the alias
@@ -2084,7 +2125,7 @@ options may be specified.
 .It Ic eval Ar string ...
 Concatenate all the arguments with spaces.
 Then re-parse and execute the command.
-.It Ic exec Op Ar command Op Ar arg ...
+.It Ic exec Op Ar command Op arg ...
 Unless
 .Ar command
 is omitted,
@@ -2261,6 +2302,8 @@ If an invalid option is encountered,
 is set to
 .Ql \&? .
 It returns a false value (1) when it encounters the end of the options.
+A new set of arguments may be parsed by assigning
+.Li OPTIND=1 .
 .It Ic hash Oo Fl rv Oc Op Ar command ...
 The shell maintains a hash table which remembers the locations of commands.
 With no arguments whatsoever, the
@@ -2500,7 +2543,8 @@ and so on,
 decreasing the value of
 .Li $#
 by one.
-If there are zero positional parameters, shifting does not do anything.
+For portability, shifting if there are zero positional parameters
+should be avoided, since the shell may abort.
 .It Ic test
 A built-in equivalent of
 .Xr test 1 .
@@ -2530,8 +2574,7 @@ the former causes the specified signal to be ignored
 and the latter causes the default action to be taken.
 Omitting the
 .Ar action
-is another way to request the default action, for compatibility reasons this
-usage is not recommended though.
+and using only signal numbers is another way to request the default action.
 In a subshell or utility environment,
 the shell resets trapped (but not ignored) signals to the default action.
 The
@@ -2556,7 +2599,7 @@ and not found.
 For aliases the alias expansion is printed;
 for commands and tracked aliases
 the complete pathname of the command is printed.
-.It Ic ulimit Oo Fl HSabcdflmnstuv Oc Op Ar limit
+.It Ic ulimit Oo Fl HSabcdfklmnpstuvw Oc Op Ar limit
 Set or display resource limits (see
 .Xr getrlimit 2 ) .
 If
@@ -2603,6 +2646,11 @@ The maximal size of core dump files, in 512-byte blocks.
 The maximal size of the data segment of a process, in kilobytes.
 .It Fl f Ar filesize
 The maximal size of a file, in 512-byte blocks.
+.It Fl k Ar kqueues
+The maximal number of kqueues
+(see
+.Xr kqueue 2 )
+for this user ID.
 .It Fl l Ar lockedmem
 The maximal size of memory that can be locked by a process, in
 kilobytes.
@@ -2610,6 +2658,8 @@ kilobytes.
 The maximal resident set size of a process, in kilobytes.
 .It Fl n Ar nofiles
 The maximal number of descriptors that could be opened by a process.
+.It Fl p Ar pseudoterminals
+The maximal number of pseudo-terminals for this user ID.
 .It Fl s Ar stacksize
 The maximal size of the stack segment, in kilobytes.
 .It Fl t Ar time
@@ -2618,6 +2668,9 @@ The maximal amount of CPU time to be used by each process, in seconds.
 The maximal number of simultaneous processes for this user ID.
 .It Fl v Ar virtualmem
 The maximal virtual size of a process, in kilobytes.
+.It Fl w Ar swapuse
+The maximum amount of swap space reserved or used for this user ID,
+in kilobytes.
 .El
 .It Ic umask Oo Fl S Oc Op Ar mask
 Set the file creation mask (see
@@ -2724,7 +2777,7 @@ This is inherited by children of the shell, and is used in the history
 editing modes.
 .El
 .Pp
-Additionally, all environment variables are turned into shell variables
+Additionally, environment variables are turned into shell variables
 at startup,
 which may affect the shell as described under
 .Sx Special Variables .
@@ -2754,7 +2807,7 @@ will return the argument.
 .Xr chsh 1 ,
 .Xr echo 1 ,
 .Xr ed 1 ,
-.Xr emacs 1 Pq Pa editors/emacs ,
+.Xr emacs 1 ,
 .Xr kill 1 ,
 .Xr printf 1 ,
 .Xr pwd 1 ,
@@ -2765,8 +2818,7 @@ will return the argument.
 .Xr umask 2 ,
 .Xr wctype 3 ,
 .Xr editrc 5 ,
-.Xr shells 5 ,
-.Xr script 7
+.Xr shells 5
 .Sh HISTORY
 A
 .Nm
@@ -2797,7 +2849,3 @@ Splitting using
 and the line editing library
 .Xr editline 3
 do not recognize multibyte characters.
-.Pp
-The characters generated by filename completion should probably be quoted
-to ensure that the filename is still valid after the input line has been
-processed.
index c47eae8..679efc7 100644 (file)
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)shell.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/shell.h 253658 2013-07-25 19:48:15Z jilles $
+ * $FreeBSD$
  */
 
 #ifndef SHELL_H_
index 904bd1e..db18ae9 100644 (file)
@@ -13,7 +13,7 @@
  * 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.
- * 3. Neither the name of the University nor the names of its contributors
+ * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 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.
- *
- * @(#)show.c  8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/show.c 213811 2010-10-13 22:18:03Z obrien $
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)show.c     8.3 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -293,9 +298,9 @@ sh_trace(const char *fmt, ...)
        va_list va;
        va_start(va, fmt);
        if (tracefile != NULL) {
-               vfprintf(tracefile, fmt, va);
+               (void) vfprintf(tracefile, fmt, va);
                if (strchr(fmt, '\n'))
-                       fflush(tracefile);
+                       (void) fflush(tracefile);
        }
        va_end(va);
 }
@@ -385,11 +390,11 @@ opentrace(void)
                        else
                                p = "/tmp";
                }
-               scopy(p, s);
+               strcpy(s, p);
                strcat(s, "/trace");
        }
 #else
-       scopy("./trace", s);
+       strcpy(s, "./trace");
 #endif /* not_this_way */
        if ((tracefile = fopen(s, "a")) == NULL) {
                fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
index 73460dd..4528fb1 100644 (file)
  * 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 w