sh: Sync with FreeBSD
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 31 Jul 2013 02:47:45 +0000 (19:47 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Wed, 31 Jul 2013 18:42:10 +0000 (11:42 -0700)
* Recognize "--" and explicitly reject options in wait builtin.
* Mention possible ambiguities with $(( and ((.
* Write as much into the heredoc pipe as possible, to avoid forking.
* Don't modify exit status when break/continue/return passes !.
* Document a few expansions for the $PS1 and $PS2 environmental
  variables.
* Don't consider jobs -s/-p as reporting the status of jobs.
* Improve error handling in read builtin.
* Use O_CLOEXEC and F_DUPFD_CLOEXEC instead of separate fcntl() call.
* Remove linked list of stack marks.
* Allow multiple operands in wait builtin.
* Return status 127 for unknown jobs in wait builtin.
* Do not read from stdin if an error occurs during -i -c cmd.
* Remove mkinit.

Obtained-from:   FreeBSD

36 files changed:
bin/sh/Makefile
bin/sh/TOUR
bin/sh/eval.c
bin/sh/eval.h
bin/sh/exec.c
bin/sh/expand.c
bin/sh/init.h [deleted file]
bin/sh/input.c
bin/sh/input.h
bin/sh/jobs.c
bin/sh/main.c
bin/sh/memalloc.c
bin/sh/memalloc.h
bin/sh/miscbltin.c
bin/sh/mkinit.c [deleted file]
bin/sh/nodes.c.pat
bin/sh/output.c
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/trap.c
tools/regression/bin/sh/builtins/break4.4 [new file with mode: 0644]
tools/regression/bin/sh/builtins/break5.4 [new file with mode: 0644]
tools/regression/bin/sh/builtins/eval6.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/local2.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/local3.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/read7.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/wait10.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/wait8.0 [new file with mode: 0644]
tools/regression/bin/sh/builtins/wait9.127 [new file with mode: 0644]
tools/regression/bin/sh/execution/int-cmd1.0 [new file with mode: 0644]
tools/regression/bin/sh/execution/not1.0 [new file with mode: 0644]
tools/regression/bin/sh/execution/not2.0 [new file with mode: 0644]

index bab4cf3..86bbd25 100644 (file)
@@ -8,7 +8,7 @@ SHSRCS= alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \
        histedit.c input.c jobs.c kill.c mail.c main.c memalloc.c miscbltin.c \
        mystring.c options.c output.c parser.c printf.c redir.c show.c \
        test.c trap.c var.c
-GENSRCS= builtins.c init.c nodes.c syntax.c
+GENSRCS= builtins.c nodes.c syntax.c
 GENHDRS= builtins.h nodes.h syntax.h token.h
 SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS}
 
@@ -34,26 +34,21 @@ CFLAGS+= -DNO_HISTORY
        ${.CURDIR}/../test \
        ${.CURDIR}/../../usr.bin/printf
 
-CLEANFILES+= mkinit.nx mkinit.no mknodes.nx mknodes.no \
+CLEANFILES+= mknodes.nx mknodes.no \
        mksyntax.nx mksyntax.no
 CLEANFILES+= ${GENSRCS} ${GENHDRS}
 
-build-tools: mkinit.nx mknodes.nx mksyntax.nx
+build-tools: mknodes.nx mksyntax.nx
 
 .ORDER: builtins.c builtins.h
 builtins.c builtins.h: mkbuiltins builtins.def
        sh ${.CURDIR}/mkbuiltins ${.CURDIR}
 
-init.c: mkinit.nx alias.c eval.c exec.c input.c jobs.c options.c parser.c \
-       redir.c trap.c var.c
-       ./mkinit.nx ${.ALLSRC:S/^mkinit.nx$//}
-
 # XXX this is just to stop the default .c rule being used, so that the
 # intermediate object has a fixed name.
 # XXX we have a default .c rule, but no default .o rule.
 .o:
        ${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
-mkinit.nx: mkinit.no
 mknodes.nx: mknodes.no
 mksyntax.nx: mksyntax.no
 
index 50f83ca..6d180ed 100644 (file)
@@ -1,5 +1,5 @@
 #      @(#)TOUR        8.1 (Berkeley) 5/31/93
-# $FreeBSD: head/bin/sh/TOUR 245689 2013-01-20 12:44:50Z jilles $
+# $FreeBSD: head/bin/sh/TOUR 253650 2013-07-25 15:08:41Z jilles $
 
 NOTE -- This is the original TOUR paper distributed with ash and
 does not represent the current state of the shell.  It is provided anyway
@@ -25,38 +25,11 @@ programs is:
         program         input files         generates
         -------         -----------         ---------
         mkbuiltins      builtins            builtins.h builtins.c
-        mkinit          *.c                 init.c
         mknodes         nodetypes           nodes.h nodes.c
         mksyntax            -               syntax.h syntax.c
         mktokens            -               token.h
 
-There are undoubtedly too many of these.  Mkinit searches all the
-C source files for entries looking like:
-
-        RESET {
-              x = 2;    /* executed when the shell does a longjmp
-                           back to the main command loop */
-        }
-
-It pulls this code out into routines which are when particular
-events occur.  The intent is to improve modularity by isolating
-the information about which modules need to be explicitly
-initialized/reset within the modules themselves.
-
-Mkinit recognizes several constructs for placing declarations in
-the init.c file.
-        INCLUDE "file.h"
-includes a file.  The storage class MKINIT makes a declaration
-available in the init.c file, for example:
-        MKINIT int funcnest;    /* depth of function calls */
-MKINIT alone on a line introduces a structure or union declara-
-tion:
-        MKINIT
-        struct redirtab {
-              short renamed[10];
-        };
-Preprocessor #define statements are copied to init.c without any
-special action to request this.
+There are undoubtedly too many of these.
 
 EXCEPTIONS:  Code for dealing with exceptions appears in
 exceptions.c.  The C language doesn't include exception handling,
index 026f936..8f9a017 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)eval.c  8.9 (Berkeley) 6/8/95
- * $FreeBSD: head/bin/sh/eval.c 247206 2013-02-23 22:50:57Z jilles $
+ * $FreeBSD: head/bin/sh/eval.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #include <sys/time.h>
@@ -73,7 +73,7 @@
 
 int evalskip;                  /* set if we are skipping commands */
 int skipcount;                 /* number of levels to skip */
-MKINIT int loopnest;           /* current loop nesting level */
+static int loopnest;           /* current loop nesting level */
 int funcnest;                  /* depth of function calls */
 static int builtin_flags;      /* evalcommand flags for builtins */
 
@@ -101,16 +101,13 @@ static void prehash(union node *);
  * Called to reset things after an exception.
  */
 
-#ifdef mkinit
-INCLUDE "eval.h"
-
-RESET {
+void
+reseteval(void)
+{
        evalskip = 0;
        loopnest = 0;
        funcnest = 0;
 }
-#endif
-
 
 
 /*
@@ -276,6 +273,8 @@ evaltree(union node *n, int flags)
                        break;
                case NNOT:
                        evaltree(n->nnot.com, EV_TESTED);
+                       if (evalskip)
+                               goto out;
                        exitstatus = !exitstatus;
                        break;
 
index 33f5e02..e9eaf1f 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)eval.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/eval.h 230212 2012-01-16 11:07:46Z dumbbell $
+ * $FreeBSD: head/bin/sh/eval.h 253650 2013-07-25 15:08:41Z jilles $
  */
 
 extern const char *commandname;        /* currently executing command */
@@ -50,6 +50,8 @@ struct backcmd {              /* result of evalbackcmd */
        struct job *jp;         /* job structure for command */
 };
 
+void reseteval(void);
+
 /* flags in argument to evaltree/evalstring */
 #define EV_EXIT 01             /* exit after evaluating tree */
 #define EV_TESTED 02           /* exit status is checked; ignore -e flag */
index fc5f1ea..b27e2a6 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)exec.c  8.4 (Berkeley) 6/8/95
- * $FreeBSD: head/bin/sh/exec.c 245426 2013-01-14 16:40:50Z jilles $
+ * $FreeBSD: head/bin/sh/exec.c 253650 2013-07-25 15:08:41Z jilles $
  */
 
 #include <sys/types.h>
@@ -65,7 +65,6 @@
 #include "syntax.h"
 #include "memalloc.h"
 #include "error.h"
-#include "init.h"
 #include "mystring.h"
 #include "show.h"
 #include "jobs.h"
@@ -181,7 +180,7 @@ padvance(const char **path, const char *name)
 {
        const char *p, *start;
        char *q;
-       int len;
+       size_t len;
 
        if (*path == NULL)
                return NULL;
index 8a202ea..cbe4b62 100644 (file)
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  *
  * @(#)expand.c        8.5 (Berkeley) 5/15/95
- * $FreeBSD: head/bin/sh/expand.c 246288 2013-02-03 15:54:57Z jilles $
+ * $FreeBSD: head/bin/sh/expand.c 248980 2013-04-01 17:18:22Z jilles $
  */
 
 #include <sys/types.h>
@@ -455,7 +455,7 @@ expbackq(union node *cmd, int quoted, int flag)
        int startloc = dest - stackblock();
        char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
        int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
-       int nnl;
+       size_t nnl;
 
        INTOFF;
        saveifs = ifsfirst;
@@ -1158,9 +1158,9 @@ nometa:
 static void
 expmeta(char *enddir, char *name)
 {
-       char *p;
-       char *q;
-       char *start;
+       const char *p;
+       const char *q;
+       const char *start;
        char *endname;
        int metaflag;
        struct stat statb;
@@ -1224,7 +1224,7 @@ expmeta(char *enddir, char *name)
                        addfname(expdir);
                return;
        }
-       endname = p;
+       endname = name + (p - name);
        if (start != name) {
                p = name;
                while (p < start) {
@@ -1407,7 +1407,8 @@ match_charclass(const char *p, wchar_t chr, const char **end)
        *end = NULL;
        p++;
        nameend = strstr(p, ":]");
-       if (nameend == NULL || nameend - p >= (int)sizeof(name) || nameend == p)
+       if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) ||
+           nameend == p)
                return 0;
        memcpy(name, p, nameend - p);
        name[nameend - p] = '\0';
diff --git a/bin/sh/init.h b/bin/sh/init.h
deleted file mode 100644 (file)
index 2b9ad02..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)init.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/init.h 245689 2013-01-20 12:44:50Z jilles $
- */
-
-void   reset(void);
index 421fcd9..811eaaf 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)input.c 8.3 (Berkeley) 6/9/95
- * $FreeBSD: head/bin/sh/input.c 245676 2013-01-19 22:12:08Z jilles $
+ * $FreeBSD: head/bin/sh/input.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #include <stdio.h>     /* defines BUFSIZ */
@@ -61,7 +61,7 @@
 
 struct strpush {
        struct strpush *prev;   /* preceding string on stack */
-       char *prevstring;
+       const char *prevstring;
        int prevnleft;
        int prevlleft;
        struct alias *ap;       /* if push was associated with an alias */
@@ -78,7 +78,7 @@ struct parsefile {
        int fd;                 /* file descriptor (or -1 if string) */
        int nleft;              /* number of chars left in this line */
        int lleft;              /* number of lines left in this buffer */
-       char *nextc;            /* next char in buffer */
+       const char *nextc;      /* next char in buffer */
        char *buf;              /* input buffer */
        struct strpush *strpush; /* for pushing strings at this level */
        struct strpush basestrpush; /* so pushing one is fast */
@@ -87,8 +87,8 @@ struct parsefile {
 
 int plinno = 1;                        /* input line number */
 int parsenleft;                        /* copy of parsefile->nleft */
-MKINIT int parselleft;         /* copy of parsefile->lleft */
-char *parsenextc;              /* copy of parsefile->nextc */
+static int parselleft;         /* copy of parsefile->lleft */
+const char *parsenextc;                /* copy of parsefile->nextc */
 static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
 static struct parsefile basepf = {     /* top level input file */
        .nextc = basebuf,
@@ -103,16 +103,12 @@ static void pushfile(void);
 static int preadfd(void);
 static void popstring(void);
 
-#ifdef mkinit
-INCLUDE <stdio.h>
-INCLUDE "input.h"
-INCLUDE "error.h"
-
-RESET {
+void
+resetinput(void)
+{
        popallfiles();
        parselleft = parsenleft = 0;    /* clear input buffer */
 }
-#endif
 
 
 /*
@@ -181,7 +177,7 @@ retry:
                        nr = el_len;
                        if (nr > BUFSIZ)
                                nr = BUFSIZ;
-                       memcpy(parsenextc, rl_cp, nr);
+                       memcpy(parsefile->buf, rl_cp, nr);
                        if (nr != el_len) {
                                el_len -= nr;
                                rl_cp += nr;
@@ -190,7 +186,7 @@ retry:
                }
        } else
 #endif
-               nr = read(parsefile->fd, parsenextc, BUFSIZ);
+               nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
 
        if (nr <= 0) {
                 if (nr < 0) {
@@ -248,7 +244,7 @@ again:
                }
        }
 
-       q = p = parsenextc;
+       q = p = parsefile->buf + (parsenextc - parsefile->buf);
 
        /* delete nul characters */
        something = 0;
@@ -393,10 +389,10 @@ setinputfile(const char *fname, int push)
        int fd2;
 
        INTOFF;
-       if ((fd = open(fname, O_RDONLY)) < 0)
+       if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
                error("cannot open %s: %s", fname, strerror(errno));
        if (fd < 10) {
-               fd2 = fcntl(fd, F_DUPFD, 10);
+               fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
                close(fd);
                if (fd2 < 0)
                        error("Out of file descriptors");
@@ -408,14 +404,13 @@ setinputfile(const char *fname, int push)
 
 
 /*
- * Like setinputfile, but takes an open file descriptor.  Call this with
- * interrupts off.
+ * Like setinputfile, but takes an open file descriptor (which should have
+ * its FD_CLOEXEC flag already set).  Call this with interrupts off.
  */
 
 void
 setinputfd(int fd, int push)
 {
-       fcntl(fd, F_SETFD, FD_CLOEXEC);
        if (push) {
                pushfile();
                parsefile->buf = ckmalloc(BUFSIZ + 1);
@@ -435,7 +430,7 @@ setinputfd(int fd, int push)
  */
 
 void
-setinputstring(char *string, int push)
+setinputstring(const char *string, int push)
 {
        INTOFF;
        if (push)
index 6a3c7fd..09a19fc 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)input.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/input.h 243027 2012-11-14 14:08:24Z jilles $
+ * $FreeBSD: head/bin/sh/input.h 253650 2013-07-25 15:08:41Z jilles $
  */
 
 /* PEOF (the end of file marker) is defined in syntax.h */
  */
 extern int plinno;
 extern int parsenleft;         /* number of characters left in input buffer */
-extern char *parsenextc;       /* next character in input buffer */
+extern const char *parsenextc; /* next character in input buffer */
 
 struct alias;
 struct parsefile;
 
+void resetinput(void);
 char *pfgets(char *, int);
 int pgetc(void);
 int preadbuffer(void);
@@ -59,7 +60,7 @@ void pungetc(void);
 void pushstring(char *, int, struct alias *);
 void setinputfile(const char *, int);
 void setinputfd(int, int);
-void setinputstring(char *, int);
+void setinputstring(const char *, int);
 void popfile(void);
 struct parsefile *getcurrentfile(void);
 void popfilesupto(struct parsefile *);
index a4a4327..a5b8183 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)jobs.c  8.5 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/jobs.c 248349 2013-03-15 20:29:31Z jilles $
+ * $FreeBSD: head/bin/sh/jobs.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #include <sys/ioctl.h>
@@ -72,8 +72,8 @@
 
 static struct job *jobtab;     /* array of jobs */
 static int njobs;              /* size of array */
-MKINIT pid_t backgndpid = -1;  /* pid of last background process */
-MKINIT struct job *bgjob = NULL; /* last background process */
+static pid_t backgndpid = -1;  /* pid of last background process */
+static struct job *bgjob = NULL; /* last background process */
 #if JOBS
 static struct job *jobmru;     /* most recently used job list */
 static pid_t initialpgrp;      /* pgrp of shell on invocation */
@@ -90,6 +90,8 @@ static int ttyfd = -1;
 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 pid_t dowait(int, struct job *);
 static void checkzombies(void);
@@ -108,7 +110,7 @@ static void showjob(struct job *, int);
  * Turn job control on and off.
  */
 
-MKINIT int jobctl;
+static int jobctl;
 
 #if JOBS
 void
@@ -121,11 +123,12 @@ setjobctl(int on)
        if (on) {
                if (ttyfd != -1)
                        close(ttyfd);
-               if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
+               if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
                        i = 0;
                        while (i <= 2 && !isatty(i))
                                i++;
-                       if (i > 2 || (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
+                       if (i > 2 ||
+                           (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0)
                                goto out;
                }
                if (ttyfd < 10) {
@@ -133,7 +136,7 @@ setjobctl(int on)
                         * Keep our TTY file descriptor out of the way of
                         * the user's redirections.
                         */
-                       if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
+                       if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
                                close(ttyfd);
                                ttyfd = -1;
                                goto out;
@@ -141,11 +144,6 @@ setjobctl(int on)
                        close(ttyfd);
                        ttyfd = i;
                }
-               if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
-                       close(ttyfd);
-                       ttyfd = -1;
-                       goto out;
-               }
                do { /* while we are in the background */
                        initialpgrp = tcgetpgrp(ttyfd);
                        if (initialpgrp < 0) {
@@ -411,13 +409,15 @@ showjobs(int change, int mode)
                if (change && ! jp->changed)
                        continue;
                showjob(jp, mode);
-               jp->changed = 0;
-               /* Hack: discard jobs for which $! has not been referenced
-                * in interactive mode when they terminate.
-                */
-               if (jp->state == JOBDONE && !jp->remembered &&
-                               (iflag || jp != bgjob)) {
-                       freejob(jp);
+               if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) {
+                       jp->changed = 0;
+                       /* Hack: discard jobs for which $! has not been
+                        * referenced in interactive mode when they terminate.
+                        */
+                       if (jp->state == JOBDONE && !jp->remembered &&
+                                       (iflag || jp != bgjob)) {
+                               freejob(jp);
+                       }
                }
        }
 }
@@ -452,18 +452,33 @@ freejob(struct job *jp)
 
 
 int
-waitcmd(int argc, char **argv)
+waitcmd(int argc __unused, char **argv __unused)
 {
        struct job *job;
+       int retval;
+
+       nextopt("");
+       if (*argptr == NULL)
+               return (waitcmdloop(NULL));
+
+       do {
+               job = getjob_nonotfound(*argptr);
+               if (job == NULL)
+                       retval = 127;
+               else
+                       retval = waitcmdloop(job);
+               argptr++;
+       } while (*argptr != NULL);
+
+       return (retval);
+}
+
+static int
+waitcmdloop(struct job *job)
+{
        int status, retval;
        struct job *jp;
 
-       if (argc > 1) {
-               job = getjob(argv[1]);
-       } else {
-               job = NULL;
-       }
-
        /*
         * Loop until a process is terminated or stopped, or a SIGINT is
         * received.
@@ -541,7 +556,7 @@ jobidcmd(int argc __unused, char **argv)
  */
 
 static struct job *
-getjob(char *name)
+getjob_nonotfound(char *name)
 {
        int jobno;
        struct job *found, *jp;
@@ -606,12 +621,22 @@ currentjob:       if ((jp = getcurjob(NULL)) == NULL)
                                return jp;
                }
        }
-       error("No such job: %s", name);
-       /*NOTREACHED*/
        return NULL;
 }
 
 
+static struct job *
+getjob(char *name)
+{
+       struct job *jp;
+
+       jp = getjob_nonotfound(name);
+       if (jp == NULL)
+               error("No such job: %s", name);
+       return (jp);
+}
+
+
 pid_t
 getjobpgrp(char *name)
 {
@@ -661,7 +686,8 @@ makejob(union node *node __unused, int nprocs)
                                jobtab = jp;
                        }
                        jp = jobtab + njobs;
-                       for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
+                       for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0)
+                               ;
                        INTON;
                        break;
                }
index 9a08de3..04e06ae 100644 (file)
@@ -31,7 +31,7 @@
  *
  * @(#) 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 247206 2013-02-23 22:50:57Z jilles $
+ * $FreeBSD: head/bin/sh/main.c 253650 2013-07-25 15:08:41Z jilles $
  */
 
 #include <stdio.h>
 #include "show.h"
 #include "memalloc.h"
 #include "error.h"
-#include "init.h"
 #include "mystring.h"
 #include "exec.h"
 #include "cd.h"
+#include "redir.h"
 #include "builtins.h"
 
 int rootpid;
@@ -69,6 +69,7 @@ int rootshell;
 struct jmploc main_handler;
 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 *);
@@ -160,8 +161,8 @@ state3:
        if (minusc) {
                evalstring(minusc, sflag ? 0 : EV_EXIT);
        }
+state4:
        if (sflag || minusc == NULL) {
-state4:        /* XXX ??? - why isn't this before the "if" statement */
                cmdloop(1);
        }
        exitshell(exitstatus);
@@ -169,6 +170,14 @@ state4:    /* XXX ??? - why isn't this before the "if" statement */
        return 0;
 }
 
+static void
+reset(void)
+{
+       reseteval();
+       resetinput();
+       resetparser();
+       resetredir();
+}
 
 /*
  * Read and execute commands.  "Top" is nonzero for the top level command
@@ -238,7 +247,7 @@ read_profile(const char *name)
        if (expandedname == NULL)
                return;
        INTOFF;
-       if ((fd = open(expandedname, O_RDONLY)) >= 0)
+       if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
                setinputfd(fd, 1);
        INTON;
        if (fd < 0)
index afe3521..fe945cb 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)memalloc.c      8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/memalloc.c 217209 2011-01-09 22:47:58Z jilles $
+ * $FreeBSD: head/bin/sh/memalloc.c 250527 2013-05-11 20:51:00Z jilles $
  */
 
 #include <sys/param.h>
@@ -119,7 +119,6 @@ struct stack_block {
 #define SPACE(sp)      ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
 
 static struct stack_block *stackp;
-static struct stackmark *markp;
 char *stacknxt;
 int stacknleft;
 char *sstrend;
@@ -181,8 +180,9 @@ setstackmark(struct stackmark *mark)
        mark->stackp = stackp;
        mark->stacknxt = stacknxt;
        mark->stacknleft = stacknleft;
-       mark->marknext = markp;
-       markp = mark;
+       /* Ensure this block stays in place. */
+       if (stackp != NULL && stacknxt == SPACE(stackp))
+               stalloc(1);
 }
 
 
@@ -192,7 +192,6 @@ popstackmark(struct stackmark *mark)
        struct stack_block *sp;
 
        INTOFF;
-       markp = mark->marknext;
        while (stackp != mark->stackp) {
                sp = stackp;
                stackp = sp->prev;
@@ -224,11 +223,11 @@ growstackblock(int min)
        int oldlen;
        struct stack_block *sp;
        struct stack_block *oldstackp;
-       struct stackmark *xmark;
 
        if (min < stacknleft)
                min = stacknleft;
-       if (min >= INT_MAX / 2 - (int)ALIGN(sizeof(struct stack_block)))
+       if ((unsigned int)min >=
+           INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
                error("Out of space");
        min += stacknleft;
        min += ALIGN(sizeof(struct stack_block));
@@ -248,18 +247,6 @@ growstackblock(int min)
                stacknxt = SPACE(sp);
                stacknleft = newlen - (stacknxt - (char*)sp);
                sstrend = stacknxt + stacknleft;
-
-               /*
-                * Stack marks pointing to the start of the old block
-                * must be relocated to point to the new block
-                */
-               xmark = markp;
-               while (xmark != NULL && xmark->stackp == oldstackp) {
-                       xmark->stackp = stackp;
-                       xmark->stacknxt = stacknxt;
-                       xmark->stacknleft = stacknleft;
-                       xmark = xmark->marknext;
-               }
                INTON;
        } else {
                newlen -= ALIGN(sizeof(struct stack_block));
@@ -322,7 +309,7 @@ makestrspace(int min, char *p)
 
 
 char *
-stputbin(const char *data, int len, char *p)
+stputbin(const char *data, size_t len, char *p)
 {
        CHECKSTRSPACE(len, p);
        memcpy(p, data, len);
index 88da554..61cb1a1 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)memalloc.h  8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/memalloc.h 217209 2011-01-09 22:47:58Z jilles $
+ * $FreeBSD: head/bin/sh/memalloc.h 250527 2013-05-11 20:51:00Z jilles $
  */
 
 #include <string.h>
@@ -43,7 +43,6 @@ struct stackmark {
        struct stack_block *stackp;
        char *stacknxt;
        int stacknleft;
-        struct stackmark *marknext;
 };
 
 
@@ -61,7 +60,7 @@ void setstackmark(struct stackmark *);
 void popstackmark(struct stackmark *);
 char *growstackstr(void);
 char *makestrspace(int, char *);
-char *stputbin(const char *data, int len, char *p);
+char *stputbin(const char *data, size_t len, char *p);
 char *stputs(const char *data, char *p);
 
 
@@ -71,7 +70,7 @@ char *stputs(const char *data, char *p);
 #define grabstackblock(n) stalloc(n)
 #define STARTSTACKSTR(p)       p = stackblock()
 #define STPUTC(c, p)   do { if (p == sstrend) p = growstackstr(); *p++ = (c); } while(0)
-#define CHECKSTRSPACE(n, p)    { if (sstrend - p < n) p = makestrspace(n, p); }
+#define CHECKSTRSPACE(n, p)    { if ((size_t)(sstrend - p) < n) p = makestrspace(n, p); }
 #define USTPUTC(c, p)  (*p++ = (c))
 /*
  * STACKSTRNUL's use is where we want to be able to turn a stack
index 10eaa54..cf7feb4 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)miscbltin.c     8.4 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/miscbltin.c 246167 2013-01-31 22:10:57Z jilles $
+ * $FreeBSD: head/bin/sh/miscbltin.c 250214 2013-05-03 15:28:31Z jilles $
  */
 
 /*
@@ -55,6 +55,7 @@
 #include "error.h"
 #include "mystring.h"
 #include "syntax.h"
+#include "trap.h"
 
 int readcmd(int, char **);
 int umaskcmd(int, char **);
@@ -97,6 +98,8 @@ readcmd(int argc __unused, char **argv __unused)
        struct timeval tv;
        char *tvptr;
        fd_set ifds;
+       ssize_t nread;
+       int sig;
 
        rflag = 0;
        prompt = NULL;
@@ -151,8 +154,10 @@ readcmd(int argc __unused, char **argv __unused)
                /*
                 * If there's nothing ready, return an error.
                 */
-               if (status <= 0)
-                       return(1);
+               if (status <= 0) {
+                       sig = pendingsig;
+                       return (128 + (sig != 0 ? sig : SIGALRM));
+               }
        }
 
        status = 0;
@@ -160,7 +165,19 @@ readcmd(int argc __unused, char **argv __unused)
        backslash = 0;
        STARTSTACKSTR(p);
        for (;;) {
-               if (read(STDIN_FILENO, &c, 1) != 1) {
+               nread = read(STDIN_FILENO, &c, 1);
+               if (nread == -1) {
+                       if (errno == EINTR) {
+                               sig = pendingsig;
+                               if (sig == 0)
+                                       continue;
+                               status = 128 + sig;
+                               break;
+                       }
+                       warning("read error: %s", strerror(errno));
+                       status = 2;
+                       break;
+               } else if (nread != 1) {
                        status = 1;
                        break;
                }
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
deleted file mode 100644 (file)
index 6def704..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 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
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#) Copyright (c) 1991, 1993 The Regents of the University of California.  All rights reserved.
- * @(#)mkinit.c        8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/mkinit.c 245689 2013-01-20 12:44:50Z jilles $
- */
-
-/*
- * This program scans all the source files for code to handle various
- * special events and combines this code into one file.  This (allegedly)
- * improves the structure of the program since there is no need for
- * anyone outside of a module to know that that module performs special
- * operations on particular events.
- *
- * Usage:  mkinit sourcefile...
- */
-
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-
-/*
- * OUTFILE is the name of the output file.  Output is initially written
- * to the file OUTTEMP, which is then moved to OUTFILE.
- */
-
-#define OUTFILE "init.c"
-#define OUTTEMP "init.c.new"
-
-
-/*
- * A text structure is basically just a string that grows as more characters
- * are added onto the end of it.  It is implemented as a linked list of
- * blocks of characters.  The routines addstr and addchar append a string
- * or a single character, respectively, to a text structure.  Writetext
- * writes the contents of a text structure to a file.
- */
-
-#define BLOCKSIZE 512
-
-struct text {
-       char *nextc;
-       int nleft;
-       struct block *start;
-       struct block *last;
-};
-
-struct block {
-       struct block *next;
-       char text[BLOCKSIZE];
-};
-
-
-/*
- * There is one event structure for each event that mkinit handles.
- */
-
-struct event {
-       const char *name;       /* name of event (e.g. RESET) */
-       const char *routine;    /* name of routine called on event */
-       const char *comment;    /* comment describing routine */
-       struct text code;       /* code for handling event */
-};
-
-
-char writer[] = "\
-/*\n\
- * This file was generated by the mkinit program.\n\
- */\n\
-\n";
-
-char reset[] = "\
-/*\n\
- * This routine is called when an error or an interrupt occurs in an\n\
- * interactive shell and control is returned to the main command loop.\n\
- */\n";
-
-
-struct event event[] = {
-       { "RESET", "reset", reset, { NULL, 0, NULL, NULL } },
-       { NULL, NULL, NULL, { NULL, 0, NULL, NULL } }
-};
-
-
-const char *curfile;                   /* current file */
-int linno;                             /* current line */
-const char *header_files[200];         /* list of header files */
-struct text defines;                   /* #define statements */
-struct text decls;                     /* declarations */
-int amiddecls;                         /* for formatting */
-
-
-void readfile(const char *);
-int match(const char *, const char *);
-int gooddefine(const char *);
-void doevent(struct event *, FILE *, const char *);
-void doinclude(char *);
-void dodecl(char *, FILE *);
-void output(void);
-void addstr(const char *, struct text *);
-void addchar(int, struct text *);
-void writetext(struct text *, FILE *);
-FILE *ckfopen(const char *, const char *);
-void *ckmalloc(size_t);
-char *savestr(const char *);
-void error(const char *);
-
-#define equal(s1, s2)  (strcmp(s1, s2) == 0)
-
-int
-main(int argc __unused, char *argv[])
-{
-       char **ap;
-
-       header_files[0] = savestr("\"shell.h\"");
-       header_files[1] = savestr("\"mystring.h\"");
-       header_files[2] = savestr("\"init.h\"");
-       for (ap = argv + 1 ; *ap ; ap++)
-               readfile(*ap);
-       output();
-       rename(OUTTEMP, OUTFILE);
-       exit(0);
-}
-
-
-/*
- * Parse an input file.
- */
-
-void
-readfile(const char *fname)
-{
-       FILE *fp;
-       char line[1024];
-       struct event *ep;
-
-       fp = ckfopen(fname, "r");
-       curfile = fname;
-       linno = 0;
-       amiddecls = 0;
-       while (fgets(line, sizeof line, fp) != NULL) {
-               linno++;
-               for (ep = event ; ep->name ; ep++) {
-                       if (line[0] == ep->name[0] && match(ep->name, line)) {
-                               doevent(ep, fp, fname);
-                               break;
-                       }
-               }
-               if (line[0] == 'I' && match("INCLUDE", line))
-                       doinclude(line);
-               if (line[0] == 'M' && match("MKINIT", line))
-                       dodecl(line, fp);
-               if (line[0] == '#' && gooddefine(line)) {
-                       char *cp;
-                       char line2[1024];
-                       static const char undef[] = "#undef ";
-
-                       strcpy(line2, line);
-                       memcpy(line2, undef, sizeof(undef) - 1);
-                       cp = line2 + sizeof(undef) - 1;
-                       while(*cp && (*cp == ' ' || *cp == '\t'))
-                               cp++;
-                       while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
-                               cp++;
-                       *cp++ = '\n'; *cp = '\0';
-                       addstr(line2, &defines);
-                       addstr(line, &defines);
-               }
-       }
-       fclose(fp);
-}
-
-
-int
-match(const char *name, const char *line)
-{
-       const char *p, *q;
-
-       p = name, q = line;
-       while (*p) {
-               if (*p++ != *q++)
-                       return 0;
-       }
-       if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
-               return 0;
-       return 1;
-}
-
-
-int
-gooddefine(const char *line)
-{
-       const char *p;
-
-       if (! match("#define", line))
-               return 0;                       /* not a define */
-       p = line + 7;
-       while (*p == ' ' || *p == '\t')
-               p++;
-       while (*p != ' ' && *p != '\t') {
-               if (*p == '(')
-                       return 0;               /* macro definition */
-               p++;
-       }
-       while (*p != '\n' && *p != '\0')
-               p++;
-       if (p[-1] == '\\')
-               return 0;                       /* multi-line definition */
-       return 1;
-}
-
-
-void
-doevent(struct event *ep, FILE *fp, const char *fname)
-{
-       char line[1024];
-       int indent;
-       const char *p;
-
-       sprintf(line, "\n      /* from %s: */\n", fname);
-       addstr(line, &ep->code);
-       addstr("      {\n", &ep->code);
-       for (;;) {
-               linno++;
-               if (fgets(line, sizeof line, fp) == NULL)
-                       error("Unexpected EOF");
-               if (equal(line, "}\n"))
-                       break;
-               indent = 6;
-               for (p = line ; *p == '\t' ; p++)
-                       indent += 8;
-               for ( ; *p == ' ' ; p++)
-                       indent++;
-               if (*p == '\n' || *p == '#')
-                       indent = 0;
-               while (indent >= 8) {
-                       addchar('\t', &ep->code);
-                       indent -= 8;
-               }
-               while (indent > 0) {
-                       addchar(' ', &ep->code);
-                       indent--;
-               }
-               addstr(p, &ep->code);
-       }
-       addstr("      }\n", &ep->code);
-}
-
-
-void
-doinclude(char *line)
-{
-       char *p;
-       char *name;
-       const char **pp;
-
-       for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
-       if (*p == '\0')
-               error("Expecting '\"' or '<'");
-       name = p;
-       while (*p != ' ' && *p != '\t' && *p != '\n')
-               p++;
-       if (p[-1] != '"' && p[-1] != '>')
-               error("Missing terminator");
-       *p = '\0';
-
-       /* name now contains the name of the include file */
-       for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
-       if (*pp == NULL)
-               *pp = savestr(name);
-}
-
-
-void
-dodecl(char *line1, FILE *fp)
-{
-       char line[1024];
-       char *p, *q;
-
-       if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
-               addchar('\n', &decls);
-               do {
-                       linno++;
-                       if (fgets(line, sizeof line, fp) == NULL)
-                               error("Unterminated structure declaration");
-                       addstr(line, &decls);
-               } while (line[0] != '}');
-               amiddecls = 0;
-       } else {
-               if (! amiddecls)
-                       addchar('\n', &decls);
-               q = NULL;
-               for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
-                       continue;
-               if (*p == '=') {                /* eliminate initialization */
-                       for (q = p ; *q && *q != ';' ; q++);
-                       if (*q == '\0')
-                               q = NULL;
-                       else {
-                               while (p[-1] == ' ')
-                                       p--;
-                               *p = '\0';
-                       }
-               }
-               addstr("extern", &decls);
-               addstr(line1 + 6, &decls);
-               if (q != NULL)
-                       addstr(q, &decls);
-               amiddecls = 1;
-       }
-}
-
-
-
-/*
- * Write the output to the file OUTTEMP.
- */
-
-void
-output(void)
-{
-       FILE *fp;
-       const char * const *pp;
-       struct event *ep;
-
-       fp = ckfopen(OUTTEMP, "w");
-       fputs(writer, fp);
-       for (pp = header_files ; *pp ; pp++)
-               fprintf(fp, "#include %s\n", *pp);
-       fputs("\n\n\n", fp);
-       writetext(&defines, fp);
-       fputs("\n\n", fp);
-       writetext(&decls, fp);
-       for (ep = event ; ep->name ; ep++) {
-               fputs("\n\n\n", fp);
-               fputs(ep->comment, fp);
-               fprintf(fp, "\nvoid\n%s(void)\n{\n", ep->routine);
-               writetext(&ep->code, fp);
-               fprintf(fp, "}\n");
-       }
-       fclose(fp);
-}
-
-
-/*
- * A text structure is simply a block of text that is kept in memory.
- * Addstr appends a string to the text struct, and addchar appends a single
- * character.
- */
-
-void
-addstr(const char *s, struct text *text)
-{
-       while (*s) {
-               if (--text->nleft < 0)
-                       addchar(*s++, text);
-               else
-                       *text->nextc++ = *s++;
-       }
-}
-
-
-void
-addchar(int c, struct text *text)
-{
-       struct block *bp;
-
-       if (--text->nleft < 0) {
-               bp = ckmalloc(sizeof *bp);
-               if (text->start == NULL)
-                       text->start = bp;
-               else
-                       text->last->next = bp;
-               text->last = bp;
-               text->nextc = bp->text;
-               text->nleft = BLOCKSIZE - 1;
-       }
-       *text->nextc++ = c;
-}
-
-/*
- * Write the contents of a text structure to a file.
- */
-void
-writetext(struct text *text, FILE *fp)
-{
-       struct block *bp;
-
-       if (text->start != NULL) {
-               for (bp = text->start ; bp != text->last ; bp = bp->next)
-                       fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
-               fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
-       }
-}
-
-FILE *
-ckfopen(const char *file, const char *mode)
-{
-       FILE *fp;
-
-       if ((fp = fopen(file, mode)) == NULL) {
-               fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
-               exit(2);
-       }
-       return fp;
-}
-
-void *
-ckmalloc(size_t nbytes)
-{
-       char *p;
-
-       if ((p = malloc(nbytes)) == NULL)
-               error("Out of space");
-       return p;
-}
-
-char *
-savestr(const char *s)
-{
-       char *p;
-
-       p = ckmalloc(strlen(s) + 1);
-       strcpy(p, s);
-       return p;
-}
-
-void
-error(const char *msg)
-{
-       if (curfile != NULL)
-               fprintf(stderr, "%s:%d: ", curfile, linno);
-       fprintf(stderr, "%s\n", msg);
-       exit(2);
-}
index 61fc65a..cfc3ffd 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/nodes.c.pat 213811 2010-10-13 22:18:03Z obrien $
+ * $FreeBSD: head/bin/sh/nodes.c.pat 249235 2013-04-07 16:28:36Z jilles $
  */
 
 #include <sys/param.h>
@@ -62,7 +62,7 @@ static void calcsize(union node *);
 static void sizenodelist(struct nodelist *);
 static union node *copynode(union node *);
 static struct nodelist *copynodelist(struct nodelist *);
-static char *nodesavestr(char *);
+static char *nodesavestr(const char *);
 
 
 struct funcdef {
@@ -151,9 +151,9 @@ copynodelist(struct nodelist *lp)
 
 
 static char *
-nodesavestr(char *s)
+nodesavestr(const char *s)
 {
-       char *p = s;
+       const char *p = s;
        char *q = funcstring;
        char   *rtn = funcstring;
 
index 212d8b9..25b9501 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)output.c        8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/output.c 244162 2012-12-12 22:01:10Z jilles $
+ * $FreeBSD: head/bin/sh/output.c 253649 2013-07-25 13:09:17Z jilles $
  */
 
 /*
@@ -70,25 +70,6 @@ struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
 struct output *out1 = &output;
 struct output *out2 = &errout;
 
-
-
-#ifdef mkinit
-
-INCLUDE "output.h"
-INCLUDE "memalloc.h"
-
-RESET {
-       out1 = &output;
-       out2 = &errout;
-       if (memout.buf != NULL) {
-               ckfree(memout.buf);
-               memout.buf = NULL;
-       }
-}
-
-#endif
-
-
 void
 outcslow(int c, struct output *file)
 {
index 9f05ec5..202023f 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)parser.c        8.7 (Berkeley) 5/16/95
- * $FreeBSD: head/bin/sh/parser.c 245382 2013-01-13 19:26:33Z jilles $
+ * $FreeBSD: head/bin/sh/parser.c 253659 2013-07-25 20:50:35Z jilles $
  */
 
 #include <stdio.h>
@@ -91,9 +91,9 @@ 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 */
-MKINIT int tokpushback;                /* last token pushed back */
+int tokpushback;               /* last token pushed back */
 static char *wordtext;         /* text of last word returned by readtoken */
-MKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
+static int checkkwd;
 static struct nodelist *backquotelist;
 static union node *redirnode;
 static struct heredoc *heredoc;
@@ -114,7 +114,7 @@ static void parseheredoc(void);
 static int peektoken(void);
 static int readtoken(void);
 static int xxreadtoken(void);
-static int readtoken1(int, char const *, char *, int);
+static int readtoken1(int, const char *, const char *, int);
 static int noexpand(char *);
 static void synexpect(int) __dead2;
 static void synerror(const char *) __dead2;
@@ -978,7 +978,7 @@ parsebackq(char *out, struct nodelist **pbqlist,
        char *volatile str;
        struct jmploc jmploc;
        struct jmploc *const savehandler = handler;
-       int savelen;
+       size_t savelen;
        int saveprompt;
        const int bq_startlinno = plinno;
        char *volatile ostr = NULL;
@@ -1295,7 +1295,8 @@ readcstyleesc(char *out)
 #define        PARSEARITH()    {goto parsearith; parsearith_return:;}
 
 static int
-readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
+readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
+    int striptabs)
 {
        int c = firstc;
        char * volatile out;
@@ -1516,7 +1517,7 @@ checkend: {
                }
                if (c == *eofmark) {
                        if (pfgets(line, sizeof line) != NULL) {
-                               char *p, *q;
+                               const char *p, *q;
 
                                p = line;
                                for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
@@ -1813,13 +1814,13 @@ parsearith: {
 } /* end of readtoken */
 
 
-
-#ifdef mkinit
-RESET {
+void
+resetparser(void)
+{
        tokpushback = 0;
        checkkwd = 0;
 }
-#endif
+
 
 /*
  * Returns true if the text contains nothing to expand (no dollar signs
@@ -2032,7 +2033,7 @@ getprompt(void *unused __unused)
 
 
 const char *
-expandstr(char *ps)
+expandstr(const char *ps)
 {
        union node n;
        struct jmploc jmploc;
index bd2fa90..9457eb0 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)parser.h    8.3 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/parser.h 246507 2013-02-07 21:24:10Z jilles $
+ * $FreeBSD: head/bin/sh/parser.h 253650 2013-07-25 15:08:41Z jilles $
  */
 
 /* control characters in argument strings */
@@ -83,7 +83,8 @@ extern const char *const parsekwd[];
 
 union node *parsecmd(int);
 void fixredir(union node *, const char *, int);
+void resetparser(void);
 int goodname(const char *);
 int isassignment(const char *);
 const char *getprompt(void *);
-const char *expandstr(char *);
+const char *expandstr(const char *);
index ed7ccf0..04b5477 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)redir.c 8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/redir.c 246288 2013-02-03 15:54:57Z jilles $
+ * $FreeBSD: head/bin/sh/redir.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #include <sys/types.h>
 
 #define EMPTY -2               /* marks an unused slot in redirtab */
 #define CLOSED -1              /* fd was not open before redir */
-#define PIPESIZE 4096          /* amount of buffering in a pipe */
 
 
-MKINIT
 struct redirtab {
        struct redirtab *next;
        int renamed[10];
 };
 
 
-MKINIT struct redirtab *redirlist;
+static struct redirtab *redirlist;
 
 /*
  * We keep track of whether or not fd0 has been redirected.  This is for
@@ -117,7 +115,7 @@ redirect(union node *redir, int flags)
 
                if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
                        INTOFF;
-                       if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
+                       if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) {
                                switch (errno) {
                                case EBADF:
                                        i = CLOSED;
@@ -127,8 +125,7 @@ redirect(union node *redir, int flags)
                                        error("%d: %s", fd, strerror(errno));
                                        break;
                                }
-                       } else
-                               (void)fcntl(i, F_SETFD, FD_CLOEXEC);
+                       }
                        sv->renamed[fd] = i;
                        INTON;
                }
@@ -248,7 +245,9 @@ openhere(union node *redir)
 {
        char *p;
        int pip[2];
-       int len = 0;
+       size_t len = 0;
+       int flags;
+       ssize_t written = 0;
 
        if (pipe(pip) < 0)
                error("Pipe call failed: %s", strerror(errno));
@@ -258,9 +257,16 @@ openhere(union node *redir)
        else
                p = redir->nhere.doc->narg.text;
        len = strlen(p);
-       if (len <= PIPESIZE) {
-               xwrite(pip[1], p, len);
+       if (len == 0)
                goto out;
+       flags = fcntl(pip[1], F_GETFL, 0);
+       if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) {
+               written = write(pip[1], p, len);
+               if (written < 0)
+                       written = 0;
+               if ((size_t)written == len)
+                       goto out;
+               fcntl(pip[1], F_SETFL, flags);
        }
 
        if (forkshell(NULL, NULL, FORK_NOJOB) == 0) {
@@ -270,7 +276,7 @@ openhere(union node *redir)
                signal(SIGHUP, SIG_IGN);
                signal(SIGTSTP, SIG_IGN);
                signal(SIGPIPE, SIG_DFL);
-               xwrite(pip[1], p, len);
+               xwrite(pip[1], p + written, len - written);
                _exit(0);
        }
 out:
@@ -312,16 +318,13 @@ popredir(void)
  * Undo all redirections.  Called on error or interrupt.
  */
 
-#ifdef mkinit
-
-INCLUDE "redir.h"
-
-RESET {
+void
+resetredir(void)
+{
        while (redirlist)
                popredir();
 }
 
-#endif
 
 /* Return true if fd 0 has already been redirected at least once.  */
 int
index 47a79a8..7689df1 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)redir.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/redir.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/redir.h 253650 2013-07-25 15:08:41Z jilles $
  */
 
 /* flags passed to redirect */
@@ -44,5 +44,6 @@
 union node;
 void redirect(union node *, int);
 void popredir(void);
+void resetredir(void);
 int fd0_redirected_p(void);
 void clearredir(void);
index 02a8e4f..088fa66 100644 (file)
@@ -30,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    from: @(#)sh.1  8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: head/bin/sh/sh.1 245805 2013-01-22 18:02:58Z joel $
+.\" $FreeBSD: head/bin/sh/sh.1 251763 2013-06-14 22:06:18Z jilles $
 .\"
-.Dd January 22, 2013
+.Dd June 14, 2013
 .Dt SH 1
 .Os
 .Sh NAME
@@ -1043,6 +1043,9 @@ The current working directory as set by
 The file creation mask as set by
 .Ic umask .
 .It
+Resource limits as set by
+.Ic ulimit .
+.It
 References to open files.
 .It
 Traps as set by
@@ -1068,6 +1071,9 @@ A subshell environment may be implemented as a child process or differently.
 If job control is enabled in an interactive shell,
 commands grouped in parentheses can be suspended and continued as a unit.
 .Pp
+For compatibility with other shells,
+two open parentheses in sequence should be separated by whitespace.
+.Pp
 The second form never forks another shell,
 so it is slightly more efficient.
 Grouping commands together this way allows the user to
@@ -1344,9 +1350,33 @@ The primary prompt string, which defaults to
 .Dq Li "$ " ,
 unless you are the superuser, in which case it defaults to
 .Dq Li "# " .
+.Va PS1
+may include any of the following formatting sequences,
+which are replaced by the given information:
+.Bl -tag -width indent
+.It Li \eH
+The local hostname.
+.It Li \eh
+The fully-qualified hostname.
+.It Li \eW
+The final component of the current working directory.
+.It Li \ew
+The entire path of the current working directory.
+.It Li \e$
+Superuser status.
+.Dq Li "$ "
+for normal users and
+.Dq Li "# "
+for superusers.
+.It Li \e\e
+A literal backslash.
+.El
 .It Va PS2
 The secondary prompt string, which defaults to
 .Dq Li "> " .
+.Va PS2
+may include any of the formatting sequences from
+.Va PS1 .
 .It Va PS4
 The prefix for the trace output (if
 .Fl x
@@ -1625,6 +1655,16 @@ and
 .Ic times
 returns information about the same process
 if they are the only command in a command substitution.
+.Pp
+If a command substitution of the
+.Li $(
+form begins with a subshell,
+the
+.Li $(
+and
+.Li (\&
+must be separated by whitespace
+to avoid ambiguity with arithmetic expansion.
 .Ss Arithmetic Expansion
 Arithmetic expansion provides a mechanism for evaluating an arithmetic
 expression and substituting its value.
@@ -2342,7 +2382,9 @@ option is specified and the
 elapses before a complete line of input is supplied,
 the
 .Ic read
-command will return an exit status of 1 without assigning any values.
+command will return an exit status as if terminated by
+.Dv SIGALRM
+without assigning any values.
 The
 .Ar timeout
 value may optionally be followed by one of
@@ -2358,6 +2400,11 @@ is assumed.
 The
 .Fl e
 option exists only for backward compatibility with older scripts.
+.Pp
+The exit status is 0 on success, 1 on end of file,
+between 2 and 128 if an error occurs
+and greater than 128 if a trapped signal interrupts
+.Ic read .
 .It Ic readonly Oo Fl p Oc Op Ar name ...
 Each specified
 .Ar name
@@ -2600,12 +2647,17 @@ If the
 option is specified, the
 .Ar name
 arguments are treated as function names.
-.It Ic wait Op Ar job
-Wait for the specified
+.It Ic wait Op Ar job ...
+Wait for each specified
 .Ar job
 to complete and return the exit status of the last process in the
+last specified
 .Ar job .
-If the argument is omitted, wait for all jobs to complete
+If any
+.Ar job
+specified is unknown to the shell, it is treated as if it
+were a known job that exited with exit status 127.
+If no operands are given, wait for all jobs to complete
 and return an exit status of zero.
 .El
 .Ss Commandline Editing
index 9776d59..c47eae8 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)shell.h     8.2 (Berkeley) 5/4/95
- * $FreeBSD: head/bin/sh/shell.h 218626 2011-02-12 23:44:05Z jilles $
+ * $FreeBSD: head/bin/sh/shell.h 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #ifndef SHELL_H_
@@ -67,7 +67,6 @@ typedef intmax_t arith_t;
 #define        ARITH_MAX INTMAX_MAX
 
 typedef void *pointer;
-#define MKINIT  /* empty */
 
 #include <sys/cdefs.h>
 
index 9ab3ba9..6e7570c 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * @(#)trap.c  8.5 (Berkeley) 6/5/95
- * $FreeBSD: head/bin/sh/trap.c 247720 2013-03-03 17:33:59Z jilles $
+ * $FreeBSD: head/bin/sh/trap.c 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #include <signal.h>
@@ -67,7 +67,7 @@
 #define S_RESET 5              /* temporary - to reset a hard ignored sig */
 
 
-MKINIT char sigmode[NSIG];     /* current value of signal */
+static char sigmode[NSIG];     /* current value of signal */
 volatile sig_atomic_t pendingsig;      /* indicates some signal received */
 int in_dotrap;                 /* do we execute in a trap handler? */
 static char *volatile trap[NSIG];      /* trap handler commands */
diff --git a/tools/regression/bin/sh/builtins/break4.4 b/tools/regression/bin/sh/builtins/break4.4
new file mode 100644 (file)
index 0000000..5833150
--- /dev/null
@@ -0,0 +1,7 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/break4.4 251180 2013-05-31 14:45:25Z jilles $
+
+# Although this is not specified by POSIX, some configure scripts (gawk 4.1.0)
+# appear to depend on it.
+
+break
+exit 4
diff --git a/tools/regression/bin/sh/builtins/break5.4 b/tools/regression/bin/sh/builtins/break5.4
new file mode 100644 (file)
index 0000000..d6fc06e
--- /dev/null
@@ -0,0 +1,12 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/break5.4 251180 2013-05-31 14:45:25Z jilles $
+
+# Although this is not specified by POSIX, some configure scripts (gawk 4.1.0)
+# appear to depend on it.
+# In some uncommitted code, the subshell environment corrupted the outer
+# shell environment's state.
+
+(for i in a b c; do
+       exit 3
+done)
+break
+exit 4
diff --git a/tools/regression/bin/sh/builtins/eval6.0 b/tools/regression/bin/sh/builtins/eval6.0
new file mode 100644 (file)
index 0000000..0aeee71
--- /dev/null
@@ -0,0 +1,5 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/eval6.0 249220 2013-04-06 22:30:46Z jilles $
+
+# eval should preserve $? from command substitutions when starting
+# the parsed command.
+[ $(false; eval 'echo $?' $(:)) = 0 ]
diff --git a/tools/regression/bin/sh/builtins/local2.0 b/tools/regression/bin/sh/builtins/local2.0
new file mode 100644 (file)
index 0000000..458f6fa
--- /dev/null
@@ -0,0 +1,17 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/local2.0 251797 2013-06-15 22:22:03Z jilles $
+
+f() {
+       local -
+       set -a
+       case $- in
+       *a*) : ;;
+       *) echo In-function \$- bad
+       esac
+}
+case $- in
+*a*) echo Initial \$- bad
+esac
+f
+case $- in
+*a*) echo Final \$- bad
+esac
diff --git a/tools/regression/bin/sh/builtins/local3.0 b/tools/regression/bin/sh/builtins/local3.0
new file mode 100644 (file)
index 0000000..ab32df3
--- /dev/null
@@ -0,0 +1,26 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/local3.0 251797 2013-06-15 22:22:03Z jilles $
+
+f() {
+       local "$@"
+       set -a
+       x=7
+       case $- in
+       *a*) : ;;
+       *) echo In-function \$- bad
+       esac
+       [ "$x" = 7 ] || echo In-function \$x bad
+}
+x=1
+case $- in
+*a*) echo Initial \$- bad
+esac
+f x -
+case $- in
+*a*) echo Intermediate \$- bad
+esac
+[ "$x" = 1 ] || echo Intermediate \$x bad
+f - x
+case $- in
+*a*) echo Final \$- bad
+esac
+[ "$x" = 1 ] || echo Final \$x bad
diff --git a/tools/regression/bin/sh/builtins/read7.0 b/tools/regression/bin/sh/builtins/read7.0
new file mode 100644 (file)
index 0000000..c5568d7
--- /dev/null
@@ -0,0 +1,5 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/read7.0 250214 2013-05-03 15:28:31Z jilles $
+
+{ errmsg=`read x <&- 2>&1 >&3`; } 3>&1
+r=$?
+[ "$r" -ge 2 ] && [ "$r" -le 128 ] && [ -n "$errmsg" ]
diff --git a/tools/regression/bin/sh/builtins/wait10.0 b/tools/regression/bin/sh/builtins/wait10.0
new file mode 100644 (file)
index 0000000..8a53acb
--- /dev/null
@@ -0,0 +1,5 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/wait10.0 251430 2013-06-05 19:40:52Z jilles $
+# Init cannot be a child of the shell.
+exit 49 & p49=$!
+wait 1 "$p49"
+[ "$?" = 49 ]
diff --git a/tools/regression/bin/sh/builtins/wait8.0 b/tools/regression/bin/sh/builtins/wait8.0
new file mode 100644 (file)
index 0000000..5c0c676
--- /dev/null
@@ -0,0 +1,7 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/wait8.0 251429 2013-06-05 19:08:22Z jilles $
+
+exit 44 & p44=$!
+exit 45 & p45=$!
+exit 7 & p7=$!
+wait "$p44" "$p7" "$p45"
+[ "$?" = 45 ]
diff --git a/tools/regression/bin/sh/builtins/wait9.127 b/tools/regression/bin/sh/builtins/wait9.127
new file mode 100644 (file)
index 0000000..b8315c4
--- /dev/null
@@ -0,0 +1,3 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/wait9.127 251430 2013-06-05 19:40:52Z jilles $
+# Init cannot be a child of the shell.
+wait 1
diff --git a/tools/regression/bin/sh/execution/int-cmd1.0 b/tools/regression/bin/sh/execution/int-cmd1.0
new file mode 100644 (file)
index 0000000..7d06cef
--- /dev/null
@@ -0,0 +1,3 @@
+# $FreeBSD: head/tools/regression/bin/sh/execution/int-cmd1.0 253271 2013-07-12 15:29:41Z jilles $
+
+! echo echo bad | $SH -ic 'fi' 2>/dev/null
diff --git a/tools/regression/bin/sh/execution/not1.0 b/tools/regression/bin/sh/execution/not1.0
new file mode 100644 (file)
index 0000000..008a030
--- /dev/null
@@ -0,0 +1,4 @@
+# $FreeBSD: head/tools/regression/bin/sh/execution/not1.0 249407 2013-04-12 15:19:35Z jilles $
+
+f() { ! return $1; }
+f 0 && ! f 1
diff --git a/tools/regression/bin/sh/execution/not2.0 b/tools/regression/bin/sh/execution/not2.0
new file mode 100644 (file)
index 0000000..1ac105b
--- /dev/null
@@ -0,0 +1,6 @@
+# $FreeBSD: head/tools/regression/bin/sh/execution/not2.0 249407 2013-04-12 15:19:35Z jilles $
+
+while :; do
+       ! break
+       exit 3
+done