Some updates to ash from vodz.  Makes ash smaller.  I made a few
changes, esp describing all the current ash configuration options.
Now ash adds 66k in the default configuration.
diff --git a/shell/ash.c b/shell/ash.c
index 7d394b6..489ccaa 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3,7 +3,7 @@
  * ash shell port for busybox
  *
  * Copyright (c) 1989, 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
@@ -22,20 +22,74 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * This version of ash is adapted from the source in Debian's ash 0.3.8-5 
- * package.  
+ * This version of ash is adapted from the source in Debian's ash 0.3.8-5
+ * package.
  *
- * Modified by Erik Andersen <andersee@debian.org> to be used in busybox.
+ * Modified by Erik Andersen <andersee@debian.org> and
+ * Vladimir Oleynik <vodz@usa.net> to be used in busybox
+ *
  *
  * Original copyright notice is retained at the end of this file.
  */
 
-#undef _GNU_SOURCE
-#undef ASH_TYPE
-#undef ASH_GETOPTS
+
+/* These defines allow you to adjust the feature set to be compiled
+ * into the ash shell.   As a rule, enabling these options will make
+ * ash get bigger...   With all of these options off, ash adds about
+ * 62k to busybox on an x86 system.*/
+
+
+
+/* Enable job control.  This allows you to run jobs in the background,
+ * which is great when ash is being  used as an interactive shell, but
+ * it completely useless for is all you are doing is running scripts.  
+ * This adds about 2.5k on an x86 system. */
+#define JOBS
+
+/* This enables alias support in ash.  If you want to support things
+ * like "alias ls='ls -l'" with ash, enable this.  This is only useful
+ * when ash is used as an intractive shell.   This adds about 1.5k */
+#define ASH_ALIAS
+
+/* If you need ash to act as a full Posix shell, with full math
+ * support, enable this.   This option needs some work, since it
+ * doesn't compile right now... */
 #undef ASH_MATH_SUPPORT
+
+/* This shell builtin is used to indicate how the shell would interpret
+ * what you give it.  This command is only useful when debugging, and
+ * is obsolete anyways.  Adds about 670 bytes... You probably want to
+ * leave this disabled. */
+#undef ASH_TYPE
+
+/* Getopts is used by shell procedures to parse positional parameters.
+ * You probably want to leave this disabled, and use the busybox getopt
+ * applet if you want to do this sort of thing.  There are some scripts
+ * out there that use it, so it you need it, enable.  Most people will
+ * leave this disabled.  This adds 1k on an x86 system. */
+#undef ASH_GETOPTS
+
+/* This allows you to override shell builtins and use whatever is on
+ * the filesystem.  This is most useful when ash is acting as a
+ * standalone shell.   Adds about 320 bytes. */
+#undef ASH_CMDCMD
+
+/* This makes a few common apps that are usually part of busybox
+ * anyways to be used as builtins.  This may cause these builtins to be
+ * a little bit faster, but leaving this disabled will save you 2k. */
+#undef ASH_BBAPPS_AS_BUILTINS
+
+/* Enable this to compile in extra debugging noise.  When debugging is
+ * on, debugging info will be written to $HOME/trace and a quit signal
+ * will generate a core dump. */
+#undef DEBUG
+
+
+
+/* These are here to work with glibc -- Don't change these... */
 #undef FNMATCH_BROKEN
 #undef GLOB_BROKEN
+#undef _GNU_SOURCE
 
 #include <assert.h>
 #include <ctype.h>
@@ -72,39 +126,1282 @@
 #include <glob.h>
 #endif
 
-#if JOBS
+#ifdef JOBS
 #include <termios.h>
-#undef CEOF			/* syntax.h redefines this */
 #endif
 
-#include "cmdedit.h"
 #include "busybox.h"
-#include "ash.h"
+#include "cmdedit.h"
+
+/* if BB_PWD is defined, then disable ASH_PWD to save space */
+#ifdef BB_PWD
+#undef ASH_PWD
+#endif
+
+
+/*
+ * This file was generated by the mksyntax program.
+ */
+
+/* Syntax classes */
+#define CWORD 0                 /* character is nothing special */
+#define CNL 1                   /* newline character */
+#define CBACK 2                 /* a backslash character */
+#define CSQUOTE 3               /* single quote */
+#define CDQUOTE 4               /* double quote */
+#define CENDQUOTE 5             /* a terminating quote */
+#define CBQUOTE 6               /* backwards single quote */
+#define CVAR 7                  /* a dollar sign */
+#define CENDVAR 8               /* a '}' character */
+#define CLP 9                   /* a left paren in arithmetic */
+#define CRP 10                  /* a right paren in arithmetic */
+#define CENDFILE 11             /* end of file */
+#define CCTL 12                 /* like CWORD, except it must be escaped */
+#define CSPCL 13                /* these terminate a word */
+#define CIGN 14                 /* character should be ignored */
+
+/* Syntax classes for is_ functions */
+#define ISDIGIT 01              /* a digit */
+#define ISUPPER 02              /* an upper case letter */
+#define ISLOWER 04              /* a lower case letter */
+#define ISUNDER 010             /* an underscore */
+#define ISSPECL 020             /* the name of a special parameter */
+
+#define SYNBASE 130
+#define PEOF -130
+
+#define PEOA -129
+
+#define TEOF 0
+#define TNL 1
+#define TSEMI 2
+#define TBACKGND 3
+#define TAND 4
+#define TOR 5
+#define TPIPE 6
+#define TLP 7
+#define TRP 8
+#define TENDCASE 9
+#define TENDBQUOTE 10
+#define TREDIR 11
+#define TWORD 12
+#define TASSIGN 13
+#define TNOT 14
+#define TCASE 15
+#define TDO 16
+#define TDONE 17
+#define TELIF 18
+#define TELSE 19
+#define TESAC 20
+#define TFI 21
+#define TFOR 22
+#define TIF 23
+#define TIN 24
+#define TTHEN 25
+#define TUNTIL 26
+#define TWHILE 27
+#define TBEGIN 28
+#define TEND 29
+
+
+#define BASESYNTAX (basesyntax + SYNBASE)
+#define DQSYNTAX (dqsyntax + SYNBASE)
+#define SQSYNTAX (sqsyntax + SYNBASE)
+#define ARISYNTAX (arisyntax + SYNBASE)
+
+/* control characters in argument strings */
+#define CTLESC '\201'
+#define CTLVAR '\202'
+#define CTLENDVAR '\203'
+#define CTLBACKQ '\204'
+#define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
+/*      CTLBACKQ | CTLQUOTE == '\205' */
+#define CTLARI  '\206'
+#define CTLENDARI '\207'
+#define CTLQUOTEMARK '\210'
+
+#define is_digit(c)     ((((unsigned char)(c)) - '0') <= 9)
+#define is_alpha(c)     (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
+#define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
+#define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
+#define is_special(c)   ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
+#define digit_val(c)    ((c) - '0')
 
 
 #define _DIAGASSERT(x)
 
 #define ATABSIZE 39
 
-#define S_DFL 1			/* default signal handling (SIG_DFL) */
-#define S_CATCH 2		/* signal is caught */
-#define S_IGN 3			/* signal is ignored (SIG_IGN) */
-#define S_HARD_IGN 4		/* signal is ignored permenantly */
-#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+#define S_DFL 1                 /* default signal handling (SIG_DFL) */
+#define S_CATCH 2               /* signal is caught */
+#define S_IGN 3                 /* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4            /* signal is ignored permenantly */
+#define S_RESET 5               /* temporary - to reset a hard ignored sig */
 
 
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE  0x0f            /* type of variable substitution */
+#define VSNUL   0x10            /* colon--treat the empty string as unset */
+#define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
 
-struct alias *atab[ATABSIZE];
+/* values of VSTYPE field */
+#define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
+#define VSMINUS         0x2             /* ${var-text} */
+#define VSPLUS          0x3             /* ${var+text} */
+#define VSQUESTION      0x4             /* ${var?message} */
+#define VSASSIGN        0x5             /* ${var=text} */
+#define VSTRIMLEFT      0x6             /* ${var#pattern} */
+#define VSTRIMLEFTMAX   0x7             /* ${var##pattern} */
+#define VSTRIMRIGHT     0x8             /* ${var%pattern} */
+#define VSTRIMRIGHTMAX  0x9             /* ${var%%pattern} */
+#define VSLENGTH        0xa             /* ${#var} */
 
-static void setalias __P((char *, char *));
-static struct alias **hashalias __P((const char *));
-static struct alias *freealias __P((struct alias *));
-static struct alias **__lookupalias __P((const char *));
-static char *trap[NSIG];		/* trap handler commands */
-static char sigmode[NSIG - 1];	/* current value of signal */
-static char gotsig[NSIG - 1];		/* indicates specified signal received */
-static int pendingsigs;			/* indicates some signal received */
+/* flags passed to redirect */
+#define REDIR_PUSH 01           /* save previous values of file descriptors */
+#define REDIR_BACKQ 02          /* save the command output in memory */
 
+/*
+ * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
+ * so we use _setjmp instead.
+ */
+
+#if !defined(__GLIBC__)
+#define setjmp(jmploc)  _setjmp(jmploc)
+#define longjmp(jmploc, val)    _longjmp(jmploc, val)
+#endif
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#ifndef ALIGN
+union align {
+	int i;
+	char *cp;
+};
+
+#define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
+#endif
+
+#ifdef BB_LOCALE_SUPPORT
+#include <locale.h>
+static void change_lc_all(const char *value);
+static void change_lc_ctype(const char *value);
+#endif
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+static void onint (void);
+static volatile int suppressint;
+static volatile int intpending;
+
+#define INTOFF suppressint++
+#ifdef ASH_BBAPPS_AS_BUILTINS
+#define INTON { if (--suppressint == 0 && intpending) onint(); }
+#else
+static void __inton (void);
+#define INTON __inton()
+#endif
+#define FORCEINTON {suppressint = 0; if (intpending) onint();}
+#define CLEAR_PENDING_INT intpending = 0
+#define int_pending() intpending
+
+
+typedef void *pointer;
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+static inline pointer  ckmalloc (int sz)          { return xmalloc(sz);     }
+static inline pointer  ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
+static inline char *   savestr  (const char *s)   { return xstrdup(s);      }
+
+static pointer stalloc (int);
+static void stunalloc (pointer);
+static void ungrabstackstr (char *, char *);
+static char * growstackstr(void);
+static char *sstrdup (const char *);
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+#define MINSIZE 504             /* minimum size of a block */
+
+
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+static struct stack_block stackbase;
+static struct stack_block *stackp = &stackbase;
+static struct stackmark *markp;
+static char *stacknxt = stackbase.space;
+static int stacknleft = MINSIZE;
+
+
+#define equal(s1, s2)   (strcmp(s1, s2) == 0)
+
+#define stackblock() stacknxt
+#define stackblocksize() stacknleft
+#define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
+#define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
+#define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
+#define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
+#define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)     (++sstrnleft, --p)
+#define STTOPC(p)       p[-1]
+#define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
+#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
+
+#define ckfree(p)       free((pointer)(p))
+
+static char * makestrspace(size_t newlen);
+
+#ifdef DEBUG
+#define TRACE(param)    trace param
+static void trace (const char *, ...);
+static void trargs (char **);
+static void showtree (union node *);
+static void trputc (int);
+static void trputs (const char *);
+static void opentrace (void);
+#else
+#define TRACE(param)
+#endif
+
+#define NSEMI 0
+#define NCMD 1
+#define NPIPE 2
+#define NREDIR 3
+#define NBACKGND 4
+#define NSUBSHELL 5
+#define NAND 6
+#define NOR 7
+#define NIF 8
+#define NWHILE 9
+#define NUNTIL 10
+#define NFOR 11
+#define NCASE 12
+#define NCLIST 13
+#define NDEFUN 14
+#define NARG 15
+#define NTO 16
+#define NFROM 17
+#define NFROMTO 18
+#define NAPPEND 19
+#define NTOOV 20
+#define NTOFD 21
+#define NFROMFD 22
+#define NHERE 23
+#define NXHERE 24
+#define NNOT 25
+
+/*
+ * expandarg() flags
+ */
+#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_RECORD      0x20    /* need to record arguments for ifs breakup */
+
+
+#define NOPTS   16
+
+static char optet_vals[NOPTS];
+
+static const char * const optlist[NOPTS] = {
+	"e" "errexit",
+	"f" "noglob",
+	"I" "ignoreeof",
+	"i" "interactive",
+	"m" "monitor",
+	"n" "noexec",
+	"s" "stdin",
+	"x" "xtrace",
+	"v" "verbose",
+	"V" "vi",
+	"E" "emacs",
+	"C" "noclobber",
+	"a" "allexport",
+	"b" "notify",
+	"u" "nounset",
+	"q" "quietprofile"
+};
+
+#define optent_name(optent) (optent+1)
+#define optent_letter(optent) optent[0]
+#define optent_val(optent) optet_vals[optent]
+
+#define eflag optent_val(0)
+#define fflag optent_val(1)
+#define Iflag optent_val(2)
+#define iflag optent_val(3)
+#define mflag optent_val(4)
+#define nflag optent_val(5)
+#define sflag optent_val(6)
+#define xflag optent_val(7)
+#define vflag optent_val(8)
+#define Vflag optent_val(9)
+#define Eflag optent_val(10)
+#define Cflag optent_val(11)
+#define aflag optent_val(12)
+#define bflag optent_val(13)
+#define uflag optent_val(14)
+#define qflag optent_val(15)
+
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+
+struct nbinary {
+      int type;
+      union node *ch1;
+      union node *ch2;
+};
+
+
+struct ncmd {
+      int type;
+      int backgnd;
+      union node *assign;
+      union node *args;
+      union node *redirect;
+};
+
+
+struct npipe {
+      int type;
+      int backgnd;
+      struct nodelist *cmdlist;
+};
+
+
+struct nredir {
+      int type;
+      union node *n;
+      union node *redirect;
+};
+
+
+struct nif {
+      int type;
+      union node *test;
+      union node *ifpart;
+      union node *elsepart;
+};
+
+
+struct nfor {
+      int type;
+      union node *args;
+      union node *body;
+      char *var;
+};
+
+
+struct ncase {
+      int type;
+      union node *expr;
+      union node *cases;
+};
+
+
+struct nclist {
+      int type;
+      union node *next;
+      union node *pattern;
+      union node *body;
+};
+
+
+struct narg {
+      int type;
+      union node *next;
+      char *text;
+      struct nodelist *backquote;
+};
+
+
+struct nfile {
+      int type;
+      union node *next;
+      int fd;
+      union node *fname;
+      char *expfname;
+};
+
+
+struct ndup {
+      int type;
+      union node *next;
+      int fd;
+      int dupfd;
+      union node *vname;
+};
+
+
+struct nhere {
+      int type;
+      union node *next;
+      int fd;
+      union node *doc;
+};
+
+
+struct nnot {
+      int type;
+      union node *com;
+};
+
+
+union node {
+      int type;
+      struct nbinary nbinary;
+      struct ncmd ncmd;
+      struct npipe npipe;
+      struct nredir nredir;
+      struct nif nif;
+      struct nfor nfor;
+      struct ncase ncase;
+      struct nclist nclist;
+      struct narg narg;
+      struct nfile nfile;
+      struct ndup ndup;
+      struct nhere nhere;
+      struct nnot nnot;
+};
+
+
+struct nodelist {
+	struct nodelist *next;
+	union node *n;
+};
+
+struct backcmd {                /* result of evalbackcmd */
+	int fd;                 /* file descriptor to read from */
+	char *buf;              /* buffer */
+	int nleft;              /* number of chars in buffer */
+	struct job *jp;         /* job structure for command */
+};
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		union node *func;
+		const struct builtincmd *cmd;
+	} u;
+};
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+struct strpush {
+	struct strpush *prev;   /* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+#ifdef ASH_ALIAS
+	struct alias *ap;       /* if push was associated with an alias */
+#endif
+	char *string;           /* remember the string since it may change */
+};
+
+struct parsefile {
+	struct parsefile *prev; /* preceding file on stack */
+	int linno;              /* current line */
+	int fd;                 /* file descriptor (or -1 if string) */
+	int nleft;              /* number of chars left in this line */
+	int lleft;              /* number of chars left in this buffer */
+	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 */
+};
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	int stacknleft;
+	struct stackmark *marknext;
+};
+
+struct shparam {
+	int nparam;             /* # of positional parameters (without $0) */
+	unsigned char malloc;   /* if parameter list dynamically allocated */
+	char **p;               /* parameter list */
+	int optind;             /* next parameter to be processed by getopts */
+	int optoff;             /* used by getopts */
+};
+
+struct output {
+#ifdef USE_GLIBC_STDIO
+	FILE *stream;
+#endif
+	char *nextc;
+	int nleft;
+	char *buf;
+	int bufsize;
+	int fd;
+	short flags;
+};
+
+#define OUTBUFSIZ BUFSIZ
+#define MEM_OUT -3              /* output to dynamically allocated memory */
+
+
+#ifdef USE_GLIBC_STDIO
+static struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
+static struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
+static struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
+#else
+static struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
+static struct output errout = {NULL, 0, NULL, 0, 2, 0};
+static struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
+#endif
+static struct output *out1 = &output;
+static struct output *out2 = &errout;
+
+#ifndef USE_GLIBC_STDIO
+static void outcslow (char, struct output *);
+#endif
+static void flushall (void);
+static void flushout (struct output *);
+static void freestdout (void);
+static void outfmt (struct output *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+static void out1fmt (const char *, ...)
+    __attribute__((__format__(__printf__,1,2)));
+static void fmtstr (char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__,3,4)));
+#ifndef USE_GLIBC_STDIO
+static void doformat (struct output *, const char *, va_list);
+#endif
+static int xwrite (int, const char *, int);
+#ifdef USE_GLIBC_STDIO
+static void initstreams (void);
+static void openmemout (void);
+static int __closememout (void);
+#endif
+
+static void outstr(const char *p, struct output *file);
+
+#define OUTPUT_ERR 01           /* error occurred on output */
+
+#ifdef USE_GLIBC_STDIO
+#define outc(c, o)      putc((c), (o)->stream)
+#define doformat(d, f, a)       vfprintf((d)->stream, (f), (a))
+#else
+#define outc(c, file)   (--(file)->nleft < 0? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++))
+#endif
+#define out1c(c)        outc((c), out1)
+#define out2c(c)        outc((c), out2)
+#define out1str(s)      outstr((s), out1)
+#define out2str(s)      outstr((s), out2)
+#define outerr(f)       ((f)->flags & OUTPUT_ERR)
+
+/* syntax table used when not in quotes */
+static const char basesyntax[257] = {
+      CENDFILE,   CSPCL,   CWORD,   CCTL,
+      CCTL,    CCTL,    CCTL,    CCTL,
+      CCTL,    CCTL,    CCTL,    CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CSPCL,
+      CNL,     CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CSPCL,   CWORD,
+      CDQUOTE, CWORD,   CVAR,    CWORD,
+      CSPCL,   CSQUOTE, CSPCL,   CSPCL,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CSPCL,   CSPCL,   CWORD,
+      CSPCL,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CBACK,   CWORD,
+      CWORD,   CWORD,   CBQUOTE, CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CSPCL,   CENDVAR,
+      CWORD
+};
+
+/* syntax table used when in double quotes */
+static const char dqsyntax[257] = {
+      CENDFILE,   CIGN,    CWORD,   CCTL,
+      CCTL,    CCTL,    CCTL,    CCTL,
+      CCTL,    CCTL,    CCTL,    CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CNL,     CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CCTL,
+      CENDQUOTE,CWORD,  CVAR,    CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CCTL,    CWORD,   CWORD,   CCTL,
+      CWORD,   CCTL,    CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CCTL,    CWORD,   CWORD,   CCTL,
+      CWORD,   CCTL,    CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CCTL,    CBACK,   CCTL,
+      CWORD,   CWORD,   CBQUOTE, CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CENDVAR,
+      CCTL
+};
+
+/* syntax table used when in single quotes */
+static const char sqsyntax[257] = {
+      CENDFILE,   CIGN,    CWORD,   CCTL,
+      CCTL,    CCTL,    CCTL,    CCTL,
+      CCTL,    CCTL,    CCTL,    CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CNL,     CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CCTL,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CENDQUOTE,CWORD,  CWORD,
+      CCTL,    CWORD,   CWORD,   CCTL,
+      CWORD,   CCTL,    CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CCTL,    CWORD,   CWORD,   CCTL,
+      CWORD,   CCTL,    CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CCTL,    CCTL,    CCTL,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CCTL
+};
+
+/* syntax table used when in arithmetic */
+static const char arisyntax[257] = {
+      CENDFILE,   CIGN,    CWORD,   CCTL,
+      CCTL,    CCTL,    CCTL,    CCTL,
+      CCTL,    CCTL,    CCTL,    CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CNL,     CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CDQUOTE, CWORD,   CVAR,    CWORD,
+      CWORD,   CSQUOTE, CLP,     CRP,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CBACK,   CWORD,
+      CWORD,   CWORD,   CBQUOTE, CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CWORD,
+      CWORD,   CWORD,   CWORD,   CENDVAR,
+      CWORD
+};
+
+/* character classification table */
+static const char is_type[257] = {
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       0,
+      0,       0,       0,       ISSPECL,
+      0,       ISSPECL, ISSPECL, 0,
+      0,       0,       0,       0,
+      ISSPECL, 0,       0,       ISSPECL,
+      0,       0,       ISDIGIT, ISDIGIT,
+      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
+      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
+      0,       0,       0,       0,
+      0,       ISSPECL, ISSPECL, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+      ISUPPER, 0,       0,       0,
+      0,       ISUNDER, 0,       ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+      ISLOWER, 0,       0,       0,
+      0
+};
+
+/* Array indicating which tokens mark the end of a list */
+static const char tokendlist[] = {
+	1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	1,
+	0,
+	0,
+	0,
+	1,
+};
+
+static const char *const tokname[] = {
+	"end of file",
+	"newline",
+	"\";\"",
+	"\"&\"",
+	"\"&&\"",
+	"\"||\"",
+	"\"|\"",
+	"\"(\"",
+	"\")\"",
+	"\";;\"",
+	"\"`\"",
+	"redirection",
+	"word",
+	"assignment",
+	"\"!\"",
+	"\"case\"",
+	"\"do\"",
+	"\"done\"",
+	"\"elif\"",
+	"\"else\"",
+	"\"esac\"",
+	"\"fi\"",
+	"\"for\"",
+	"\"if\"",
+	"\"in\"",
+	"\"then\"",
+	"\"until\"",
+	"\"while\"",
+	"\"{\"",
+	"\"}\"",
+};
+
+#define KWDOFFSET 14
+
+static const char *const parsekwd[] = {
+	"!",
+	"case",
+	"do",
+	"done",
+	"elif",
+	"else",
+	"esac",
+	"fi",
+	"for",
+	"if",
+	"in",
+	"then",
+	"until",
+	"while",
+	"{",
+	"}"
+};
+
+
+static int plinno = 1;          /* input line number */
+
+static int parselleft;          /* copy of parsefile->lleft */
+
+static struct parsefile basepf; /* top level input file */
+static char basebuf[BUFSIZ];    /* buffer for top level input file */
+static struct parsefile *parsefile = &basepf;  /* current input file */
+
+/*
+ * 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.
+ */
+
+static int tokpushback;         /* last token pushed back */
+#define NEOF ((union node *)&tokpushback)
+static int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
+
+
+static void error (const char *, ...) __attribute__((__noreturn__));
+static void exerror (int, const char *, ...) __attribute__((__noreturn__));
+static void shellexec (char **, char **, const char *, int)
+    __attribute__((noreturn));
+static void exitshell (int) __attribute__((noreturn));
+
+static int  goodname(const char *);
+static void ignoresig (int);
+static void onsig (int);
+static void dotrap (void);
+static int  decode_signal (const char *, int);
+
+static void shprocvar(void);
+static void deletefuncs(void);
+static void setparam (char **);
+static void freeparam (volatile struct shparam *);
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK       1
+#define SKIPCONT        2
+#define SKIPFUNC        3
+#define SKIPFILE        4
+
+/* values of cmdtype */
+#define CMDUNKNOWN -1           /* no entry in table for command */
+#define CMDNORMAL 0             /* command is an executable program */
+#define CMDBUILTIN 1            /* command is a shell builtin */
+#define CMDFUNCTION 2           /* command is a shell function */
+
+#define DO_ERR  1               /* find_command prints errors */
+#define DO_ABS  2               /* find_command checks absolute paths */
+#define DO_NOFUN        4       /* find_command ignores functions */
+#define DO_BRUTE        8       /* find_command ignores hash table */
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT         0x01    /* variable is exported */
+#define VREADONLY       0x02    /* variable cannot be modified */
+#define VSTRFIXED       0x04    /* variable struct is staticly allocated */
+#define VTEXTFIXED      0x08    /* text is staticly allocated */
+#define VSTACK          0x10    /* text is allocated on the stack */
+#define VUNSET          0x20    /* the variable is not set */
+#define VNOFUNC         0x40    /* don't call the callback function */
+
+
+struct var {
+	struct var *next;               /* next entry in hash list */
+	int flags;                      /* flags are defined above */
+	char *text;                     /* name=value */
+	void (*func) (const char *);
+					/* function to be called when  */
+					/* the variable gets set/unset */
+};
+
+struct localvar {
+	struct localvar *next;          /* next local variable in list */
+	struct var *vp;                 /* the variable that was made local */
+	int flags;                      /* saved flags */
+	char *text;                     /* saved text */
+};
+
+
+#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
+#define rmescapes(p) _rmescapes((p), 0)
+static char *_rmescapes (char *, int);
+#else
+static void rmescapes (char *);
+#endif
+
+static int  casematch (union node *, const char *);
+static void clearredir(void);
+static void popstring(void);
+static void readcmdfile (const char *);
+
+static int number (const char *);
+static int is_number (const char *, int *num);
+static char *single_quote (const char *);
+static int nextopt (const char *);
+
+static void redirect (union node *, int);
+static void popredir (void);
+static int dup_as_newfd (int, int);
+
+static void changepath(const char *newval);
+static void getoptsreset(const char *value);
+
+
+static int parsenleft;                  /* copy of parsefile->nleft */
+static char *parsenextc;                /* copy of parsefile->nextc */
+static int rootpid;     /* pid of main shell */
+static int rootshell;   /* true if we aren't a child of the main shell */
+
+static const char spcstr[] = " ";
+static const char snlfmt[] = "%s\n";
+
+static int sstrnleft;
+static int herefd = -1;
+
+static struct localvar *localvars;
+
+static struct var vifs;
+static struct var vmail;
+static struct var vmpath;
+static struct var vpath;
+static struct var vps1;
+static struct var vps2;
+static struct var voptind;
+#ifdef BB_LOCALE_SUPPORT
+static struct var vlc_all;
+static struct var vlc_ctype;
+#endif
+
+struct varinit {
+	struct var *var;
+	int flags;
+	const char *text;
+	void (*func) (const char *);
+};
+
+static const char defpathvar[] =
+	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
+#define defpath (defpathvar + 5)
+
+#ifdef IFS_BROKEN
+static const char defifsvar[] = "IFS= \t\n";
+#define defifs (defifsvar + 4)
+#else
+static const char defifs[] = " \t\n";
+#endif
+
+static const struct varinit varinit[] = {
+#ifdef IFS_BROKEN
+	{ &vifs,        VSTRFIXED|VTEXTFIXED,           defifsvar,
+#else
+	{ &vifs,        VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS=",
+#endif
+	  NULL },
+	{ &vmail,       VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL=",
+	  NULL },
+	{ &vmpath,      VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH=",
+	  NULL },
+	{ &vpath,       VSTRFIXED|VTEXTFIXED,           defpathvar,
+	  changepath },
+	/*
+	 * vps1 depends on uid
+	 */
+	{ &vps2,        VSTRFIXED|VTEXTFIXED,           "PS2=> ",
+	  NULL },
+	{ &voptind,     VSTRFIXED|VTEXTFIXED,           "OPTIND=1",
+	  getoptsreset },
+#ifdef BB_LOCALE_SUPPORT
+	{ &vlc_all,     VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_ALL=",
+	  change_lc_all },
+	{ &vlc_ctype,   VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_CTYPE=",
+	  change_lc_ctype },
+#endif
+	{ NULL, 0,                              NULL,
+	  NULL }
+};
+
+#define VTABSIZE 39
+
+static struct var *vartab[VTABSIZE];
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval()        (vifs.text + 4)
+#define ifsset()        ((vifs.flags & VUNSET) == 0)
+#define mailval()       (vmail.text + 5)
+#define mpathval()      (vmpath.text + 9)
+#define pathval()       (vpath.text + 5)
+#define ps1val()        (vps1.text + 4)
+#define ps2val()        (vps2.text + 4)
+#define optindval()     (voptind.text + 7)
+
+#define mpathset()      ((vmpath.flags & VUNSET) == 0)
+
+static void initvar (void);
+static void setvar (const char *, const char *, int);
+static void setvareq (char *, int);
+static void listsetvar (struct strlist *);
+static char *lookupvar (const char *);
+static char *bltinlookup (const char *);
+static char **environment (void);
+static int showvarscmd (int, char **);
+static void mklocal (char *);
+static void poplocalvars (void);
+static int unsetvar (const char *);
+static int varequal (const char *, const char *);
+
+
+static char *arg0;                      /* value of $0 */
+static struct shparam shellparam;       /* current positional parameters */
+static char **argptr;                   /* argument list for builtin commands */
+static char *optionarg;                 /* set by nextopt (like getopt) */
+static char *optptr;                    /* used by nextopt */
+static char *minusc;                    /* argument to -c option */
+
+
+#ifdef ASH_ALIAS
+
+#define ALIASINUSE      1
+#define ALIASDEAD       2
+
+struct alias {
+	struct alias *next;
+	char *name;
+	char *val;
+	int flag;
+};
+
+static struct alias *atab[ATABSIZE];
+
+static void setalias (char *, char *);
+static struct alias **hashalias (const char *);
+static struct alias *freealias (struct alias *);
+static struct alias **__lookupalias (const char *);
 
 static void
 setalias(name, val)
@@ -119,7 +1416,7 @@
 		if (!(ap->flag & ALIASINUSE)) {
 			ckfree(ap->val);
 		}
-		ap->val	= savestr(val);
+		ap->val = savestr(val);
 		ap->flag &= ~ALIASDEAD;
 	} else {
 		/* not found */
@@ -134,9 +1431,8 @@
 }
 
 static int
-unalias(name)
-	char *name;
-	{
+unalias(char *name)
+{
 	struct alias **app;
 
 	app = __lookupalias(name);
@@ -151,16 +1447,9 @@
 	return (1);
 }
 
-#ifdef mkinit
-static void rmaliases __P((void));
-
-SHELLPROC {
-	rmaliases();
-}
-#endif
-
 static void
-rmaliases() {
+rmaliases(void)
+{
 	struct alias *ap, **app;
 	int i;
 
@@ -177,10 +1466,8 @@
 	INTON;
 }
 
-struct alias *
-lookupalias(name, check)
-	const char *name;
-	int check;
+static struct alias *
+lookupalias(const char *name, int check)
 {
 	struct alias *ap = *__lookupalias(name);
 
@@ -189,14 +1476,21 @@
 	return (ap);
 }
 
+static void
+printalias(const struct alias *ap) {
+	char *p;
+
+	p = single_quote(ap->val);
+	out1fmt("alias %s=%s\n", ap->name, p);
+	stunalloc(p);
+}
+
 
 /*
  * TODO - sort output
  */
 static int
-aliascmd(argc, argv)
-	int argc;
-	char **argv;
+aliascmd(int argc, char **argv)
 {
 	char *n, *v;
 	int ret = 0;
@@ -229,9 +1523,7 @@
 }
 
 static int
-unaliascmd(argc, argv)
-	int argc;
-	char **argv;
+unaliascmd(int argc, char **argv)
 {
 	int i;
 
@@ -279,14 +1571,6 @@
 	return next;
 }
 
-static void
-printalias(const struct alias *ap) {
-	char *p;
-
-	p = single_quote(ap->val);
-	out1fmt("alias %s=%s\n", ap->name, p);
-	stunalloc(p);
-}
 
 static struct alias **
 __lookupalias(const char *name) {
@@ -300,64 +1584,132 @@
 
 	return app;
 }
+#endif
 
 #ifdef ASH_MATH_SUPPORT
 /* The generated file arith.c has been snipped.  If you want this
  * stuff back in, feel free to add it to your own copy.  */
+#define ARITH_NUM 257
+#define ARITH_LPAREN 258
+#define ARITH_RPAREN 259
+#define ARITH_OR 260
+#define ARITH_AND 261
+#define ARITH_BOR 262
+#define ARITH_BXOR 263
+#define ARITH_BAND 264
+#define ARITH_EQ 265
+#define ARITH_NE 266
+#define ARITH_LT 267
+#define ARITH_GT 268
+#define ARITH_GE 269
+#define ARITH_LE 270
+#define ARITH_LSHIFT 271
+#define ARITH_RSHIFT 272
+#define ARITH_ADD 273
+#define ARITH_SUB 274
+#define ARITH_MUL 275
+#define ARITH_DIV 276
+#define ARITH_REM 277
+#define ARITH_UNARYMINUS 278
+#define ARITH_UNARYPLUS 279
+#define ARITH_NOT 280
+#define ARITH_BNOT 281
+
+static void expari (int);
+/* From arith.y */
+static int arith (const char *);
+static int expcmd (int , char **);
+static void arith_lex_reset (void);
+static int yylex (void);
+
 #endif
 
+static char *trap[NSIG];                /* trap handler commands */
+static char sigmode[NSIG - 1];  /* current value of signal */
+static char gotsig[NSIG - 1];           /* indicates specified signal received */
+static int pendingsigs;                 /* indicates some signal received */
+
 /*
  * This file was generated by the mkbuiltins program.
  */
 
-static int bgcmd __P((int, char **));
-static int breakcmd __P((int, char **));
-static int cdcmd __P((int, char **));
-static int commandcmd __P((int, char **));
-static int dotcmd __P((int, char **));
-static int evalcmd __P((int, char **));
-static int execcmd __P((int, char **));
-static int exitcmd __P((int, char **));
-static int exportcmd __P((int, char **));
-static int histcmd __P((int, char **));
-static int fgcmd __P((int, char **));
-static int hashcmd __P((int, char **));
-static int jobscmd __P((int, char **));
-static int killcmd __P((int, char **));
-static int localcmd __P((int, char **));
-static int pwdcmd __P((int, char **));
-static int readcmd __P((int, char **));
-static int returncmd __P((int, char **));
-static int setcmd __P((int, char **));
-static int setvarcmd __P((int, char **));
-static int shiftcmd __P((int, char **));
-static int trapcmd __P((int, char **));
-static int umaskcmd __P((int, char **));
-static int unaliascmd __P((int, char **));
-static int unsetcmd __P((int, char **));
-static int waitcmd __P((int, char **));
-static int aliascmd __P((int, char **));
-static int ulimitcmd __P((int, char **));
-static int timescmd __P((int, char **));
+#ifdef JOBS
+static int bgcmd (int, char **);
+static int fgcmd (int, char **);
+static int killcmd (int, char **);
+#endif
+#ifdef ASH_BBAPPS_AS_BUILTINS
+static int bltincmd (int, char **);
+#endif
+static int cdcmd (int, char **);
+static int breakcmd (int, char **);
+#ifdef ASH_CMDCMD
+static int commandcmd (int, char **);
+#endif
+static int dotcmd (int, char **);
+static int evalcmd (int, char **);
+static int execcmd (int, char **);
+static int exitcmd (int, char **);
+static int exportcmd (int, char **);
+static int histcmd (int, char **);
+static int hashcmd (int, char **);
+static int jobscmd (int, char **);
+static int localcmd (int, char **);
+#ifdef ASH_PWD
+static int pwdcmd (int, char **);
+#endif
+static int readcmd (int, char **);
+static int returncmd (int, char **);
+static int setcmd (int, char **);
+static int setvarcmd (int, char **);
+static int shiftcmd (int, char **);
+static int trapcmd (int, char **);
+static int umaskcmd (int, char **);
+#ifdef ASH_ALIAS
+static int aliascmd (int, char **);
+static int unaliascmd (int, char **);
+#endif
+static int unsetcmd (int, char **);
+static int waitcmd (int, char **);
+static int ulimitcmd (int, char **);
+static int timescmd (int, char **);
 #ifdef ASH_MATH_SUPPORT
-static int expcmd __P((int, char **));
+static int expcmd (int, char **);
 #endif
 #ifdef ASH_TYPE
-static int typecmd __P((int, char **));
+static int typecmd (int, char **);
 #endif
 #ifdef ASH_GETOPTS
-static int getoptscmd __P((int, char **));
-#endif
-#ifndef BB_TRUE_FALSE
-static int true_main __P((int, char **));
-static int false_main __P((int, char **));
+static int getoptscmd (int, char **);
 #endif
 
-static struct builtincmd *DOTCMD;
-static struct builtincmd *BLTINCMD;
-static struct builtincmd *COMMANDCMD;
-static struct builtincmd *EXECCMD;
-static struct builtincmd *EVALCMD;
+#ifndef BB_TRUE_FALSE
+# ifdef ASH_BBAPPS_AS_BUILTINS
+static int true_main (int, char **);
+static int false_main (int, char **);
+# endif
+#endif
+
+static void     setpwd (const char *, int);
+
+
+#define BUILTIN_NOSPEC  "0"
+#define BUILTIN_SPECIAL "1"
+#define BUILTIN_REGULAR "2"
+#define BUILTIN_ASSIGN  "4"
+#define BUILTIN_SPEC_ASSG  "5"
+#define BUILTIN_REG_ASSG   "6"
+
+#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
+#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
+#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
+
+struct builtincmd {
+	const char *name;
+	int (*const builtinfunc) (int, char **);
+	//unsigned flags;
+};
+
 
 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
  * the binary search in find_builtin() will stop working. If you value
@@ -366,75 +1718,149 @@
  * have been warned.
  */
 static const struct builtincmd builtincmds[] = {
-	{ ".", dotcmd, 1 },
-	{ ":", true_main, 1 },
-	{ "alias", aliascmd, 6 },
-	{ "bg", bgcmd, 2 },
-	{ "break", breakcmd, 1 },
-	{ "builtin", bltincmd, 1 },
-	{ "cd", cdcmd, 2 },
-	{ "chdir", cdcmd, 0 },
-	{ "command", commandcmd, 2 },
-	{ "continue", breakcmd, 1 },
-	{ "eval", evalcmd, 1 },
-	{ "exec", execcmd, 1 },
-	{ "exit", exitcmd, 1 },
-#ifdef ASH_MATH_SUPPORT
-	{ "exp", expcmd, 0 },
+	{ BUILTIN_SPECIAL   ".", dotcmd },
+	{ BUILTIN_SPECIAL   ":", true_main },
+#ifdef ASH_ALIAS
+	{ BUILTIN_REG_ASSG  "alias", aliascmd },
 #endif
-	{ "export", exportcmd, 5 },
-	{ "false", false_main, 2 },
-	{ "fc", histcmd, 2 },
-	{ "fg", fgcmd, 2 },
+#ifdef JOBS
+	{ BUILTIN_REGULAR   "bg", bgcmd },
+#endif
+	{ BUILTIN_SPECIAL   "break", breakcmd },
+#ifdef ASH_BBAPPS_AS_BUILTINS
+	{ BUILTIN_SPECIAL   "builtin", bltincmd },
+#endif
+	{ BUILTIN_REGULAR   "cd", cdcmd },
+#ifdef ASH_BBAPPS_AS_BUILTINS
+	{ BUILTIN_NOSPEC    "chdir", cdcmd },
+#endif
+#ifdef ASH_CMDCMD
+	{ BUILTIN_REGULAR   "command", commandcmd },
+#endif
+	{ BUILTIN_SPECIAL   "continue", breakcmd },
+	{ BUILTIN_SPECIAL   "eval", evalcmd },
+	{ BUILTIN_SPECIAL   "exec", execcmd },
+	{ BUILTIN_SPECIAL   "exit", exitcmd },
+#ifdef ASH_MATH_SUPPORT
+	{ BUILTIN_NOSPEC    "exp", expcmd },
+#endif
+	{ BUILTIN_SPEC_ASSG "export", exportcmd },
+#ifdef ASH_BBAPPS_AS_BUILTINS
+	{ BUILTIN_REGULAR   "false", false_main },
+#endif
+	{ BUILTIN_REGULAR   "fc", histcmd },
+#ifdef JOBS
+	{ BUILTIN_REGULAR   "fg", fgcmd },
+#endif
 #ifdef ASH_GETOPTS
-	{ "getopts", getoptscmd, 2 },
-#endif	
-	{ "hash", hashcmd, 0 },
-	{ "jobs", jobscmd, 2 },
-	{ "kill", killcmd, 2 },
+	{ BUILTIN_REGULAR   "getopts", getoptscmd },
+#endif
+	{ BUILTIN_NOSPEC    "hash", hashcmd },
+	{ BUILTIN_REGULAR   "jobs", jobscmd },
+#ifdef JOBS
+	{ BUILTIN_REGULAR   "kill", killcmd },
+#endif
 #ifdef ASH_MATH_SUPPORT
-	{ "let", expcmd, 0 },
+	{ BUILTIN_NOSPEC    "let", expcmd },
 #endif
-	{ "local", localcmd, 4 },
-	{ "pwd", pwdcmd, 0 },
-	{ "read", readcmd, 2 },
-	{ "readonly", exportcmd, 5 },
-	{ "return", returncmd, 1 },
-	{ "set", setcmd, 1 },
-	{ "setvar", setvarcmd, 0 },
-	{ "shift", shiftcmd, 1 },
-	{ "times", timescmd, 1 },
-	{ "trap", trapcmd, 1 },
-	{ "true", true_main, 2 },
+	{ BUILTIN_ASSIGN    "local", localcmd },
+#ifdef ASH_PWD
+	{ BUILTIN_NOSPEC    "pwd", pwdcmd },
+#endif
+	{ BUILTIN_REGULAR   "read", readcmd },
+	{ BUILTIN_SPEC_ASSG "readonly", exportcmd },
+	{ BUILTIN_SPECIAL   "return", returncmd },
+	{ BUILTIN_SPECIAL   "set", setcmd },
+	{ BUILTIN_NOSPEC    "setvar", setvarcmd },
+	{ BUILTIN_SPECIAL   "shift", shiftcmd },
+	{ BUILTIN_SPECIAL   "times", timescmd },
+	{ BUILTIN_SPECIAL   "trap", trapcmd },
+#ifdef ASH_BBAPPS_AS_BUILTINS
+	{ BUILTIN_REGULAR   "true", true_main },
+#endif
 #ifdef ASH_TYPE
-	{ "type", typecmd, 0 },
+	{ BUILTIN_NOSPEC    "type", typecmd },
 #endif
-	{ "ulimit", ulimitcmd, 0 },
-	{ "umask", umaskcmd, 2 },
-	{ "unalias", unaliascmd, 2 },
-	{ "unset", unsetcmd, 1 },
-	{ "wait", waitcmd, 2 },
+	{ BUILTIN_NOSPEC    "ulimit", ulimitcmd },
+	{ BUILTIN_REGULAR   "umask", umaskcmd },
+#ifdef ASH_ALIAS
+	{ BUILTIN_REGULAR   "unalias", unaliascmd },
+#endif
+	{ BUILTIN_SPECIAL   "unset", unsetcmd },
+	{ BUILTIN_REGULAR   "wait", waitcmd },
 };
 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
 
+static const struct builtincmd *DOTCMD = &builtincmds[0];
+static struct builtincmd *BLTINCMD;
+static struct builtincmd *EXECCMD;
+static struct builtincmd *EVALCMD;
 
-/*	$NetBSD: cd.c,v 1.27 1999/07/09 03:05:49 christos Exp $	*/
+/* states */
+#define JOBSTOPPED 1            /* all procs are stopped */
+#define JOBDONE 2               /* all procs are completed */
 
-static int docd __P((char *, int));
-static char *getcomponent __P((void));
-static void updatepwd __P((char *));
-static void getpwd __P((void));
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
 
-static char *curdir = nullstr;		/* current working directory */
-static char *cdcomppath;
+struct procstat {
+	pid_t pid;              /* process id */
+	int status;             /* status flags (defined above) */
+	char *cmd;              /* text of command being run */
+};
 
-#ifdef mkinit
-INCLUDE "cd.h"
-INIT {
-	setpwd(0, 0);
-}
+
+static int job_warning;         /* user was warned about stopped jobs */
+
+#ifdef JOBS
+static void setjobctl(int enable);
+#else
+#define setjobctl(on)   /* do nothing */
 #endif
 
+
+struct job {
+	struct procstat ps0;    /* status of process */
+	struct procstat *ps;    /* status or processes when more than one */
+	short nprocs;           /* number of processes */
+	short pgrp;             /* process group of this job */
+	char state;             /* true if job is finished */
+	char used;              /* true if this entry is in used */
+	char changed;           /* true if status has changed */
+#ifdef JOBS
+	char jobctl;            /* job running under job control */
+#endif
+};
+
+static struct job *jobtab;      /* array of jobs */
+static int njobs;               /* size of array */
+static int backgndpid = -1;     /* pid of last background process */
+#ifdef JOBS
+static int initialpgrp;         /* pgrp of shell on invocation */
+static int curjob;              /* current job */
+static int jobctl;
+#endif
+static int intreceived;
+
+static struct job *makejob (union node *, int);
+static int forkshell (struct job *, union node *, int);
+static int waitforjob (struct job *);
+
+static int docd (char *, int);
+static char *getcomponent (void);
+static void updatepwd (const char *);
+static void getpwd (void);
+
+static char *padvance (const char **, const char *);
+
+static char nullstr[1];         /* zero length string */
+static char *curdir = nullstr;          /* current working directory */
+static char *cdcomppath;
+
 static int
 cdcmd(argc, argv)
 	int argc;
@@ -450,7 +1876,7 @@
 	if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
 		error("HOME not set");
 	if (*dest == '\0')
-	        dest = ".";
+		dest = ".";
 	if (dest[0] == '-' && dest[1] == '\0') {
 		dest = bltinlookup("OLDPWD");
 		if (!dest || !*dest) {
@@ -458,9 +1884,9 @@
 		}
 		print = 1;
 		if (dest)
-		        print = 1;
+			print = 1;
 		else
-		        dest = ".";
+			dest = ".";
 	}
 	if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
 		path = nullstr;
@@ -581,15 +2007,16 @@
  * that the current directory has changed.
  */
 
+static void hashcd (void);
+
 static void
-updatepwd(dir)
-	char *dir;
-	{
+updatepwd(const char *dir)
+{
 	char *new;
 	char *p;
 	size_t len;
 
-	hashcd();				/* update command hash table */
+	hashcd();                               /* update command hash table */
 
 	/*
 	 * If our argument is NULL, we don't know the current directory
@@ -626,7 +2053,7 @@
 }
 
 
-
+#ifdef ASH_PWD
 static int
 pwdcmd(argc, argv)
 	int argc;
@@ -635,89 +2062,18 @@
 	out1fmt(snlfmt, curdir);
 	return 0;
 }
-
-
-
-
-#define MAXPWD 256
+#endif
 
 /*
  * Find out what the current directory is. If we already know the current
  * directory, this routine returns immediately.
  */
 static void
-getpwd()
+getpwd(void)
 {
-	char buf[MAXPWD];
-
-	/*
-	 * Things are a bit complicated here; we could have just used
-	 * getcwd, but traditionally getcwd is implemented using popen
-	 * to /bin/pwd. This creates a problem for us, since we cannot
-	 * keep track of the job if it is being ran behind our backs.
-	 * So we re-implement getcwd(), and we suppress interrupts
-	 * throughout the process. This is not completely safe, since
-	 * the user can still break out of it by killing the pwd program.
-	 * We still try to use getcwd for systems that we know have a
-	 * c implementation of getcwd, that does not open a pipe to
-	 * /bin/pwd.
-	 */
-#if defined(__NetBSD__) || defined(__SVR4) || defined(__GLIBC__)
-		
-	if (getcwd(buf, sizeof(buf)) == NULL) {
-		char *pwd = getenv("PWD");
-		struct stat stdot, stpwd;
-
-		if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
-		    stat(pwd, &stpwd) != -1 &&
-		    stdot.st_dev == stpwd.st_dev &&
-		    stdot.st_ino == stpwd.st_ino) {
-			curdir = savestr(pwd);
-			return;
-		}
-		error("getcwd() failed: %s", strerror(errno));
-	}
-	curdir = savestr(buf);
-#else
-	{
-		char *p;
-		int i;
-		int status;
-		struct job *jp;
-		int pip[2];
-
-		if (pipe(pip) < 0)
-			error("Pipe call failed");
-		jp = makejob((union node *)NULL, 1);
-		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
-			(void) close(pip[0]);
-			if (pip[1] != 1) {
-				close(1);
-				dup_as_newfd(pip[1], 1);
-				close(pip[1]);
-			}
-			(void) execl("/bin/pwd", "pwd", (char *)0);
-			error("Cannot exec /bin/pwd");
-		}
-		(void) close(pip[1]);
-		pip[1] = -1;
-		p = buf;
-		while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
-		     || (i == -1 && errno == EINTR)) {
-			if (i > 0)
-				p += i;
-		}
-		(void) close(pip[0]);
-		pip[0] = -1;
-		status = waitforjob(jp);
-		if (status != 0)
-			error((char *)0);
-		if (i < 0 || p == buf || p[-1] != '\n')
-			error("pwd command failed");
-		p[-1] = '\0';
-	}
-	curdir = savestr(buf);
-#endif
+	curdir = xgetcwd(0);
+	if(curdir==0)
+		curdir = nullstr;
 }
 
 static void
@@ -740,8 +2096,6 @@
 	setvar("PWD", curdir, VEXPORT);
 }
 
-/*	$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $	*/
-
 /*
  * Errors and exceptions.
  */
@@ -750,13 +2104,30 @@
  * Code to handle exceptions in C.
  */
 
-struct jmploc *handler;
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exeception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+/* exceptions */
+#define EXINT 0         /* SIGINT received */
+#define EXERROR 1       /* a generic error */
+#define EXSHELLPROC 2   /* execute a shell procedure */
+#define EXEXEC 3        /* command execution failed */
+
+static struct jmploc *handler;
 static int exception;
-volatile int suppressint;
-volatile int intpending;
 
-
-static void exverror __P((int, const char *, va_list))
+static void exverror (int, const char *, va_list)
     __attribute__((__noreturn__));
 
 /*
@@ -765,9 +2136,10 @@
  * stored in the global variable "exception".
  */
 
+static void exraise (int) __attribute__((__noreturn__));
+
 static void
-exraise(e)
-	int e;
+exraise(int e)
 {
 #ifdef DEBUG
 	if (handler == NULL)
@@ -789,7 +2161,7 @@
  */
 
 static void
-onint() {
+onint(void) {
 	sigset_t mysigset;
 
 	if (suppressint) {
@@ -809,16 +2181,15 @@
 }
 
 
+static char *commandname;       /* currently executing command */
+
 /*
  * Exverror is called to raise the error exception.  If the first argument
  * is not NULL then error prints an error message using printf style
  * formatting.  It then raises the error exception.
  */
 static void
-exverror(cond, msg, ap)
-	int cond;
-	const char *msg;
-	va_list ap;
+exverror(int cond, const char *msg, va_list ap)
 {
 	CLEAR_PENDING_INT;
 	INTOFF;
@@ -903,69 +2274,75 @@
  */
 
 struct errname {
-	short errcode;		/* error number */
-	short action;		/* operation which encountered the error */
-	const char *msg;	/* text describing the error */
+	short errcode;          /* error number */
+	short action;           /* operation which encountered the error */
 };
 
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+#define E_OPEN 01       /* opening a file */
+#define E_CREAT 02      /* creating a file */
+#define E_EXEC 04       /* executing a program */
 
 #define ALL (E_OPEN|E_CREAT|E_EXEC)
 
 static const struct errname errormsg[] = {
-	{ EINTR,	ALL,	"interrupted" },
-	{ EACCES,	ALL,	"permission denied" },
-	{ EIO,		ALL,	"I/O error" },
-	{ ENOENT,	E_OPEN,	"no such file" },
-	{ ENOENT,	E_CREAT,"directory nonexistent" },
-	{ ENOENT,	E_EXEC,	"not found" },
-	{ ENOTDIR,	E_OPEN,	"no such file" },
-	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
-	{ ENOTDIR,	E_EXEC,	"not found" },
-	{ EISDIR,	ALL,	"is a directory" },
-	{ EEXIST,	E_CREAT,"file exists" },
-#ifdef notdef
-	{ EMFILE,	ALL,	"too many open files" },
+	{ EINTR,        ALL     },
+	{ EACCES,       ALL     },
+	{ EIO,          ALL     },
+	{ ENOENT,       E_OPEN  },
+	{ ENOENT,       E_CREAT },
+	{ ENOENT,       E_EXEC  },
+	{ ENOTDIR,      E_OPEN  },
+	{ ENOTDIR,      E_CREAT },
+	{ ENOTDIR,      E_EXEC  },
+	{ EISDIR,       ALL     },
+	{ EEXIST,       E_CREAT },
+#ifdef EMFILE
+	{ EMFILE,       ALL     },
 #endif
-	{ ENFILE,	ALL,	"file table overflow" },
-	{ ENOSPC,	ALL,	"file system full" },
+	{ ENFILE,       ALL     },
+	{ ENOSPC,       ALL     },
 #ifdef EDQUOT
-	{ EDQUOT,	ALL,	"disk quota exceeded" },
+	{ EDQUOT,       ALL     },
 #endif
 #ifdef ENOSR
-	{ ENOSR,	ALL,	"no streams resources" },
+	{ ENOSR,        ALL     },
 #endif
-	{ ENXIO,	ALL,	"no such device or address" },
-	{ EROFS,	ALL,	"read-only file system" },
-	{ ETXTBSY,	ALL,	"text busy" },
-#ifdef SYSV
-	{ EAGAIN,	E_EXEC,	"not enough memory" },
+	{ ENXIO,        ALL     },
+	{ EROFS,        ALL     },
+	{ ETXTBSY,      ALL     },
+#ifdef EAGAIN
+	{ EAGAIN,       E_EXEC  },
 #endif
-	{ ENOMEM,	ALL,	"not enough memory" },
+	{ ENOMEM,       ALL     },
 #ifdef ENOLINK
-	{ ENOLINK,	ALL,	"remote access failed" },
+	{ ENOLINK,      ALL     },
 #endif
 #ifdef EMULTIHOP
-	{ EMULTIHOP,	ALL,	"remote access failed" },
+	{ EMULTIHOP,    ALL     },
 #endif
 #ifdef ECOMM
-	{ ECOMM,	ALL,	"remote access failed" },
+	{ ECOMM,        ALL     },
 #endif
 #ifdef ESTALE
-	{ ESTALE,	ALL,	"remote access failed" },
+	{ ESTALE,       ALL     },
 #endif
 #ifdef ETIMEDOUT
-	{ ETIMEDOUT,	ALL,	"remote access failed" },
+	{ ETIMEDOUT,    ALL     },
 #endif
 #ifdef ELOOP
-	{ ELOOP,	ALL,	"symbolic link loop" },
+	{ ELOOP,        ALL     },
 #endif
-	{ E2BIG,	E_EXEC,	"argument list too long" },
+	{ E2BIG,        E_EXEC  },
 #ifdef ELIBACC
-	{ ELIBACC,	E_EXEC,	"shared library missing" },
+	{ ELIBACC,      E_EXEC  },
 #endif
-	{ 0,		0,	NULL },
 };
 
+#define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
 
 /*
  * Return a string describing an error.  The returned string may be a
@@ -974,23 +2351,22 @@
  */
 
 static const char *
-errmsg(e, action)
-	int e;
-	int action;
+errmsg(int e, int action)
 {
 	struct errname const *ep;
 	static char buf[12];
 
-	for (ep = errormsg ; ep->errcode ; ep++) {
+	for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
 		if (ep->errcode == e && (ep->action & action) != 0)
-			return ep->msg;
+			return strerror(e);
 	}
+
 	fmtstr(buf, sizeof buf, "error %d", e);
 	return buf;
 }
 
 
-#ifdef REALLY_SMALL
+#ifndef ASH_BBAPPS_AS_BUILTINS
 static void
 __inton() {
 	if (--suppressint == 0 && intpending) {
@@ -998,104 +2374,91 @@
 	}
 }
 #endif
-/*	$NetBSD: eval.c,v 1.57 2001/02/04 19:52:06 christos Exp $	*/
-
 
 /* flags in argument to evaltree */
-#define EV_EXIT 01		/* exit after evaluating tree */
-#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
-#define EV_BACKCMD 04		/* command executing within back quotes */
+#define EV_EXIT 01              /* exit after evaluating tree */
+#define EV_TESTED 02            /* exit status is checked; ignore -e flag */
+#define EV_BACKCMD 04           /* command executing within back quotes */
 
-static int evalskip;			/* set if we are skipping commands */
-static int skipcount;		/* number of levels to skip */
-static int loopnest;		/* current loop nesting level */
-static int funcnest;			/* depth of function calls */
+static int evalskip;                    /* set if we are skipping commands */
+static int skipcount;           /* number of levels to skip */
+static int loopnest;            /* current loop nesting level */
+static int funcnest;                    /* depth of function calls */
 
 
-static char *commandname;
-struct strlist *cmdenviron;
-static int exitstatus;			/* exit status of last command */
-static int oexitstatus;		/* saved exit status */
+
+static struct strlist *cmdenviron;      /* environment for builtin command */
+static int exitstatus;                  /* exit status of last command */
+static int oexitstatus;         /* saved exit status */
 
 
-static void evalloop __P((union node *, int));
-static void evalfor __P((union node *, int));
-static void evalcase __P((union node *, int));
-static void evalsubshell __P((union node *, int));
-static void expredir __P((union node *));
-static void evalpipe __P((union node *));
+static void evalloop (union node *, int);
+static void evalfor (union node *, int);
+static void evalcase (union node *, int);
+static void evalsubshell (union node *, int);
+static void expredir (union node *);
+static void evalpipe (union node *);
 #ifdef notyet
-static void evalcommand __P((union node *, int, struct backcmd *));
+static void evalcommand (union node *, int, struct backcmd *);
 #else
-static void evalcommand __P((union node *, int));
+static void evalcommand (union node *, int);
 #endif
-static void prehash __P((union node *));
-static void eprintlist __P((struct strlist *));
+static void prehash (union node *);
+static void eprintlist (struct strlist *);
 
-
+static union node *parsecmd(int);
 /*
  * Called to reset things after an exception.
  */
 
-#ifdef mkinit
-INCLUDE "eval.h"
-
-RESET {
-	evalskip = 0;
-	loopnest = 0;
-	funcnest = 0;
-}
-
-SHELLPROC {
-	exitstatus = 0;
-}
-#endif
-
-
-
 /*
  * The eval commmand.
  */
+static void evalstring (char *, int);
 
 static int
 evalcmd(argc, argv)
 	int argc;
 	char **argv;
 {
-        char *p;
-        char *concat;
-        char **ap;
+	char *p;
+	char *concat;
+	char **ap;
 
-        if (argc > 1) {
-                p = argv[1];
-                if (argc > 2) {
-                        STARTSTACKSTR(concat);
-                        ap = argv + 2;
-                        for (;;) {
-                                while (*p)
-                                        STPUTC(*p++, concat);
-                                if ((p = *ap++) == NULL)
-                                        break;
-                                STPUTC(' ', concat);
-                        }
-                        STPUTC('\0', concat);
-                        p = grabstackstr(concat);
-                }
-                evalstring(p, EV_TESTED);
-        }
-        return exitstatus;
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			STARTSTACKSTR(concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(*p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(' ', concat);
+			}
+			STPUTC('\0', concat);
+			p = grabstackstr(concat);
+		}
+		evalstring(p, EV_TESTED);
+	}
+	return exitstatus;
 }
 
-
 /*
  * Execute a command or commands contained in a string.
  */
 
+static void evaltree (union node *, int);
+static void setinputstring (char *);
+static void popfile (void);
+static void setstackmark(struct stackmark *mark);
+static void popstackmark(struct stackmark *mark);
+
+
 static void
-evalstring(s, flag)
-	char *s;
-	int flag;
-	{
+evalstring(char *s, int flag)
+{
 	union node *n;
 	struct stackmark smark;
 
@@ -1109,12 +2472,12 @@
 	popstackmark(&smark);
 }
 
-
-
 /*
  * Evaluate a parse tree.  The value is left in the global variable
  * exitstatus.
  */
+static struct builtincmd *find_builtin (const char *);
+static void defun (char *, union node *);
 
 static void
 evaltree(n, flags)
@@ -1184,7 +2547,7 @@
 		struct builtincmd *bcmd;
 		if (
 			(bcmd = find_builtin(n->narg.text)) &&
-			bcmd->flags & BUILTIN_SPECIAL
+			IS_BUILTIN_SPECIAL(bcmd)
 		) {
 			outfmt(out2, "%s is a special built-in\n", n->narg.text);
 			exitstatus = 1;
@@ -1243,7 +2606,7 @@
 	for (;;) {
 		evaltree(n->nbinary.ch1, EV_TESTED);
 		if (evalskip) {
-skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
+skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
 				evalskip = 0;
 				continue;
 			}
@@ -1267,7 +2630,8 @@
 	exitstatus = status;
 }
 
-
+static void expandarg (union node *, struct arglist *, int);
+static void fixredir(union node *n, const char *text, int err);
 
 static void
 evalfor(n, flags)
@@ -1310,7 +2674,6 @@
 }
 
 
-
 static void
 evalcase(n, flags)
 	union node *n;
@@ -1339,8 +2702,6 @@
 	popstackmark(&smark);
 }
 
-
-
 /*
  * Kick off a subshell to evaluate a tree.
  */
@@ -1359,7 +2720,7 @@
 		if (backgnd)
 			flags &=~ EV_TESTED;
 		redirect(n->nredir.redirect, 0);
-		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
+		evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
 	}
 	if (! backgnd) {
 		INTOFF;
@@ -1404,8 +2765,6 @@
 	}
 }
 
-
-
 /*
  * Evaluate a pipeline.  All the processes in the pipeline are children
  * of the process creating the pipeline.  (This differs from some versions
@@ -1485,13 +2844,11 @@
  */
 
 static void
-evalbackcmd(n, result)
-	union node *n;
-	struct backcmd *result;
+evalbackcmd(union node *n, struct backcmd *result)
 {
 	int pip[2];
 	struct job *jp;
-	struct stackmark smark;		/* unnecessary */
+	struct stackmark smark;         /* unnecessary */
 
 	setstackmark(&smark);
 	result->fd = -1;
@@ -1546,6 +2903,19 @@
  * Execute a simple command.
  */
 
+static void find_command (const char *, struct cmdentry *, int, const char *);
+
+static int
+isassignment(const char *word) {
+	if (!is_name(*word)) {
+		return 0;
+	}
+	do {
+		word++;
+	} while (is_in_name(*word));
+	return *word == '=';
+}
+
 static void
 #ifdef notyet
 evalcommand(cmd, flags, backcmd)
@@ -1611,7 +2981,7 @@
 		struct builtincmd *bcmd;
 		bool pseudovarflag;
 		bcmd = find_builtin(arglist.list->text);
-		pseudovarflag = bcmd && bcmd->flags & BUILTIN_ASSIGN;
+		pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
 		for (; argp; argp = argp->narg.next) {
 			if (pseudovarflag && isassignment(argp->narg.text)) {
 				expandarg(argp, &arglist, EXP_VARTILDE);
@@ -1678,7 +3048,7 @@
 		firstbltin = 0;
 		for(;;) {
 			find_command(argv[0], &cmdentry, findflag, path);
-			if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
+			if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
 				exitstatus = 127;
 #ifdef FLUSHERR
 				flushout(&errout);
@@ -1712,7 +3082,7 @@
 						break;
 				}
 			}
-			if (cmdentry.u.cmd == COMMANDCMD) {
+			if (cmdentry.u.cmd == find_builtin("command")) {
 				argv++;
 				if (--argc == 0) {
 					goto found;
@@ -1761,7 +3131,7 @@
 		}
 #endif
 		if (forkshell(jp, cmd, mode) != 0)
-			goto parent;	/* at end of routine */
+			goto parent;    /* at end of routine */
 #ifdef notyet
 		if (flags & EV_BACKCMD) {
 			FORCEINTON;
@@ -1849,7 +3219,7 @@
 #endif
 		redirect(cmd->ncmd.redirect, mode);
 		savecmdname = commandname;
-		if (firstbltin->flags & BUILTIN_SPECIAL) {
+		if (IS_BUILTIN_SPECIAL(firstbltin)) {
 			listsetvar(varlist.list);
 		} else {
 			cmdenviron = varlist.list;
@@ -1864,7 +3234,7 @@
 		handler = &jmploc;
 		commandname = argv[0];
 		argptr = argv + 1;
-		optptr = NULL;			/* initialize nextopt */
+		optptr = NULL;                  /* initialize nextopt */
 		exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
 		flushall();
 cmddone:
@@ -1894,12 +3264,8 @@
 		if (flags == EV_BACKCMD) {
 			INTOFF;
 #ifdef USE_GLIBC_STDIO
-			if (__closememout()) {
-				error(
-					"__closememout() failed: %s",
-					strerror(errno)
-				);
-			}
+			if (__closememout())
+				error("__closememout() failed: %m");
 #endif
 			backcmd->buf = memout.buf;
 #ifdef USE_GLIBC_STDIO
@@ -1924,8 +3290,8 @@
 	}
 	goto out;
 
-parent:	/* parent process gets here (if we forked) */
-	if (mode == 0) {	/* argument to fork */
+parent: /* parent process gets here (if we forked) */
+	if (mode == 0) {        /* argument to fork */
 		INTOFF;
 		exitstatus = waitforjob(jp);
 		INTON;
@@ -2043,6 +3409,7 @@
 
 
 #ifndef BB_TRUE_FALSE
+#ifdef ASH_BBAPPS_AS_BUILTINS
 static int
 false_main(argc, argv)
 	int argc;
@@ -2060,6 +3427,37 @@
 	return 0;
 }
 #endif
+#endif
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+static void setsignal(int signo);
+static void chkmail(int silent);
+
+
+static void
+setinteractive(int on)
+{
+	static int is_interactive;
+
+	if (on == is_interactive)
+		return;
+	setsignal(SIGINT);
+	setsignal(SIGQUIT);
+	setsignal(SIGTERM);
+	chkmail(1);
+	is_interactive = on;
+}
+
+static void
+optschanged(void)
+{
+	setinteractive(iflag);
+	setjobctl(mflag);
+}
+
 
 static int
 execcmd(argc, argv)
@@ -2069,7 +3467,7 @@
 	if (argc > 1) {
 		struct strlist *sp;
 
-		iflag = 0;		/* exit on error */
+		iflag = 0;              /* exit on error */
 		mflag = 0;
 		optschanged();
 		for (sp = cmdenviron; sp ; sp = sp->next)
@@ -2086,8 +3484,6 @@
 		outfmt(&errout, " %s",sp->text);
 	}
 }
-/*	$NetBSD: exec.c,v 1.32 2001/02/04 19:52:06 christos Exp $	*/
-
 /*
  * When commands are first encountered, they are entered in a hash table.
  * This ensures that a full path search will not have to be done for them
@@ -2096,37 +3492,34 @@
  * We should investigate converting to a linear search, even though that
  * would make the command name "hash" a misnomer.
  */
-#define CMDTABLESIZE 31		/* should be prime */
-#define ARB 1			/* actual size determined at run time */
+#define CMDTABLESIZE 31         /* should be prime */
+#define ARB 1                   /* actual size determined at run time */
 
 
 
 struct tblentry {
-	struct tblentry *next;	/* next entry in hash chain */
-	union param param;	/* definition of builtin function */
-	short cmdtype;		/* index identifying command */
-	char rehash;		/* if set, cd done since entry created */
-	char cmdname[ARB];	/* name of command */
+	struct tblentry *next;  /* next entry in hash chain */
+	union param param;      /* definition of builtin function */
+	short cmdtype;          /* index identifying command */
+	char rehash;            /* if set, cd done since entry created */
+	char cmdname[ARB];      /* name of command */
 };
 
 
 static struct tblentry *cmdtable[CMDTABLESIZE];
-static int builtinloc = -1;		/* index in path of %builtin, or -1 */
-static int exerrno = 0;			/* Last exec error */
+static int builtinloc = -1;             /* index in path of %builtin, or -1 */
+static int exerrno = 0;                 /* Last exec error */
 
 
-static void tryexec __P((char *, char **, char **));
-#if !defined(BSD) && !defined(linux)
-static void execinterp __P((char **, char **));
-#endif
-static void printentry __P((struct tblentry *, int));
-static void clearcmdentry __P((int));
-static struct tblentry *cmdlookup __P((char *, int));
-static void delete_cmd_entry __P((void));
+static void tryexec (char *, char **, char **);
+static void printentry (struct tblentry *, int);
+static void clearcmdentry (int);
+static struct tblentry *cmdlookup (const char *, int);
+static void delete_cmd_entry (void);
 #ifdef ASH_TYPE
-static int describe_command __P((char *, int));
+static int describe_command (char *, int);
 #endif
-static int path_change __P((const char *, int *));
+static int path_change (const char *, int *);
 
 
 /*
@@ -2134,6 +3527,8 @@
  * have to change the find_command routine as well.
  */
 
+static const char *pathopt;     /* set by padvance */
+
 static void
 shellexec(argv, envp, path, idx)
 	char **argv, **envp;
@@ -2174,6 +3569,225 @@
 	/* NOTREACHED */
 }
 
+/*
+ * Clear traps on a fork.
+ */
+static void
+clear_traps(void) {
+	char **tp;
+
+	for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+		if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
+			INTOFF;
+			ckfree(*tp);
+			*tp = NULL;
+			if (tp != &trap[0])
+				setsignal(tp - trap);
+			INTON;
+		}
+	}
+}
+
+
+static void
+initshellproc(void) {
+
+#ifdef ASH_ALIAS
+      /* from alias.c: */
+      {
+	      rmaliases();
+      }
+#endif
+      /* from eval.c: */
+      {
+	      exitstatus = 0;
+      }
+
+      /* from exec.c: */
+      {
+	      deletefuncs();
+      }
+
+      /* from jobs.c: */
+      {
+	      backgndpid = -1;
+#ifdef JOBS
+	      jobctl = 0;
+#endif
+      }
+
+      /* from options.c: */
+      {
+	      int i;
+
+	      for (i = 0; i < NOPTS; i++)
+		      optent_val(i) = 0;
+	      optschanged();
+
+      }
+
+      /* from redir.c: */
+      {
+	      clearredir();
+      }
+
+      /* from trap.c: */
+      {
+	      char *sm;
+
+	      clear_traps();
+	      for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
+		      if (*sm == S_IGN)
+			      *sm = S_HARD_IGN;
+	      }
+      }
+
+      /* from var.c: */
+      {
+	      shprocvar();
+      }
+}
+
+static int preadbuffer(void);
+static void pushfile (void);
+static int preadfd (void);
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+#ifdef ASH_BBAPPS_AS_BUILTINS
+#define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
+static int
+pgetc(void)
+{
+	return pgetc_macro();
+}
+#else
+static int
+pgetc_macro(void)
+{
+	return --parsenleft >= 0? *parsenextc++ : preadbuffer();
+}
+
+static inline int
+pgetc(void)
+{
+	return pgetc_macro();
+}
+#endif
+
+
+/*
+ * Undo the last call to pgetc.  Only one character may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+static void
+pungetc() {
+	parsenleft++;
+	parsenextc--;
+}
+
+
+static void
+popfile(void) {
+	struct parsefile *pf = parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		close(pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	while (pf->strpush)
+		popstring();
+	parsefile = pf->prev;
+	ckfree(pf);
+	parsenleft = parsefile->nleft;
+	parselleft = parsefile->lleft;
+	parsenextc = parsefile->nextc;
+	plinno = parsefile->linno;
+	INTON;
+}
+
+
+/*
+ * Return to top level.
+ */
+
+static void
+popallfiles(void) {
+	while (parsefile != &basepf)
+		popfile();
+}
+
+/*
+ * Close the file(s) that the shell is reading commands from.  Called
+ * after a fork is done.
+ */
+
+static void
+closescript() {
+	popallfiles();
+	if (parsefile->fd > 0) {
+		close(parsefile->fd);
+		parsefile->fd = 0;
+	}
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+static void
+setinputfd(fd, push)
+	int fd, push;
+{
+	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+	if (push) {
+		pushfile();
+		parsefile->buf = 0;
+	} else {
+		closescript();
+		while (parsefile->strpush)
+			popstring();
+	}
+	parsefile->fd = fd;
+	if (parsefile->buf == NULL)
+		parsefile->buf = ckmalloc(BUFSIZ);
+	parselleft = parsenleft = 0;
+	plinno = 1;
+}
+
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+static void
+setinputfile(const char *fname, int push)
+{
+	int fd;
+	int myfileno2;
+
+	INTOFF;
+	if ((fd = open(fname, O_RDONLY)) < 0)
+		error("Can't open %s", fname);
+	if (fd < 10) {
+		myfileno2 = dup_as_newfd(fd, 10);
+		close(fd);
+		if (myfileno2 < 0)
+			error("Out of file descriptors");
+		fd = myfileno2;
+	}
+	setinputfd(fd, push);
+	INTON;
+}
+
 
 static void
 tryexec(cmd, argv, envp)
@@ -2182,119 +3796,21 @@
 	char **envp;
 	{
 	int e;
-#if !defined(BSD) && !defined(linux)
-	char *p;
-#endif
 
-#ifdef SYSV
-	do {
-		execve(cmd, argv, envp);
-	} while (errno == EINTR);
-#else
 	execve(cmd, argv, envp);
-#endif
 	e = errno;
 	if (e == ENOEXEC) {
 		INTOFF;
 		initshellproc();
 		setinputfile(cmd, 0);
 		commandname = arg0 = savestr(argv[0]);
-#if !defined(BSD) && !defined(linux)
-		INTON;
-		pgetc(); pungetc();		/* fill up input buffer */
-		p = parsenextc;
-		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
-			argv[0] = cmd;
-			execinterp(argv, envp);
-		}
-		INTOFF;
-#endif
 		setparam(argv + 1);
 		exraise(EXSHELLPROC);
 	}
 	errno = e;
 }
 
-
-#if !defined(BSD) && !defined(linux)
-/*
- * Execute an interpreter introduced by "#!", for systems where this
- * feature has not been built into the kernel.  If the interpreter is
- * the shell, return (effectively ignoring the "#!").  If the execution
- * of the interpreter fails, exit.
- *
- * This code peeks inside the input buffer in order to avoid actually
- * reading any input.  It would benefit from a rewrite.
- */
-
-#define NEWARGS 5
-
-static void
-execinterp(argv, envp)
-	char **argv, **envp;
-	{
-	int n;
-	char *inp;
-	char *outp;
-	char c;
-	char *p;
-	char **ap;
-	char *newargs[NEWARGS];
-	int i;
-	char **ap2;
-	char **new;
-
-	n = parsenleft - 2;
-	inp = parsenextc + 2;
-	ap = newargs;
-	for (;;) {
-		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
-			inp++;
-		if (n < 0)
-			goto bad;
-		if ((c = *inp++) == '\n')
-			break;
-		if (ap == &newargs[NEWARGS])
-bad:		  error("Bad #! line");
-		STARTSTACKSTR(outp);
-		do {
-			STPUTC(c, outp);
-		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
-		STPUTC('\0', outp);
-		n++, inp--;
-		*ap++ = grabstackstr(outp);
-	}
-	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
-		p = newargs[0];
-		for (;;) {
-			if (equal(p, "sh") || equal(p, "ash")) {
-				return;
-			}
-			while (*p != '/') {
-				if (*p == '\0')
-					goto break2;
-				p++;
-			}
-			p++;
-		}
-break2:;
-	}
-	i = (char *)ap - (char *)newargs;		/* size in bytes */
-	if (i == 0)
-		error("Bad #! line");
-	for (ap2 = argv ; *ap2++ != NULL ; );
-	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
-	ap = newargs, ap2 = new;
-	while ((i -= sizeof (char **)) >= 0)
-		*ap2++ = *ap++;
-	ap = argv;
-	while (*ap2++ = *ap++);
-	shellexec(new, envp, pathval(), 0);
-	/* NOTREACHED */
-}
-#endif
-
-
+static char *commandtext (const union node *);
 
 /*
  * Do a path search.  The variable path (passed by reference) should be
@@ -2308,11 +3824,12 @@
 
 static const char *pathopt;
 
+static void growstackblock(void);
+
+
 static char *
-padvance(path, name)
-	const char **path;
-	const char *name;
-	{
+padvance(const char **path, const char *name)
+{
 	const char *p;
 	char *q;
 	const char *start;
@@ -2322,7 +3839,7 @@
 		return NULL;
 	start = *path;
 	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
-	len = p - start + strlen(name) + 2;	/* "2" is for '/' and '\0' */
+	len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
 	while (stackblocksize() < len)
 		growstackblock();
 	q = stackblock();
@@ -2442,12 +3959,10 @@
  * change the shellexec routine as well.
  */
 
+static int prefix (const char *, const char *);
+
 static void
-find_command(name, entry, act, path)
-	char *name;
-	struct cmdentry *entry;
-	int act;
-	const char *path;
+find_command(const char *name, struct cmdentry *entry, int act, const char *path)
 {
 	struct tblentry *cmdp;
 	int idx;
@@ -2465,10 +3980,6 @@
 	if (strchr(name, '/') != NULL) {
 		if (act & DO_ABS) {
 			while (stat(name, &statb) < 0) {
-	#ifdef SYSV
-				if (errno == EINTR)
-					continue;
-	#endif
 				if (errno != ENOENT && errno != ENOTDIR)
 					e = errno;
 				entry->cmdtype = CMDUNKNOWN;
@@ -2516,11 +4027,11 @@
 	}
 
 	bcmd = find_builtin(name);
-	regular = bcmd && bcmd->flags & BUILTIN_REGULAR;
+	regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
 
 	if (regular) {
 		if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
-		    	goto success;
+			goto success;
 		}
 	} else if (act & DO_BRUTE) {
 		if (firstchange == 0) {
@@ -2545,8 +4056,8 @@
 	}
 
 	/* We have to search path. */
-	prev = -1;		/* where to start */
-	if (cmdp && cmdp->rehash) {	/* doing a rehash */
+	prev = -1;              /* where to start */
+	if (cmdp && cmdp->rehash) {     /* doing a rehash */
 		if (cmdp->cmdtype == CMDBUILTIN)
 			prev = builtinloc;
 		else
@@ -2572,7 +4083,7 @@
 				   prefix("func", pathopt)) {
 				/* handled below */
 			} else {
-				continue;	/* ignore unimplemented options */
+				continue;       /* ignore unimplemented options */
 			}
 		}
 		/* if rehash, don't redo absolute path names */
@@ -2584,18 +4095,14 @@
 			goto success;
 		}
 		while (stat(fullname, &statb) < 0) {
-#ifdef SYSV
-			if (errno == EINTR)
-				continue;
-#endif
 			if (errno != ENOENT && errno != ENOTDIR)
 				e = errno;
 			goto loop;
 		}
-		e = EACCES;	/* if we fail, this will be the error */
+		e = EACCES;     /* if we fail, this will be the error */
 		if (!S_ISREG(statb.st_mode))
 			continue;
-		if (pathopt) {		/* this is a %func directory */
+		if (pathopt) {          /* this is a %func directory */
 			stalloc(strlen(fullname) + 1);
 			readcmdfile(fullname);
 			if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
@@ -2603,18 +4110,6 @@
 			stunalloc(fullname);
 			goto success;
 		}
-#ifdef notdef
-		if (statb.st_uid == geteuid()) {
-			if ((statb.st_mode & 0100) == 0)
-				goto loop;
-		} else if (statb.st_gid == getegid()) {
-			if ((statb.st_mode & 010) == 0)
-				goto loop;
-		} else {
-			if ((statb.st_mode & 01) == 0)
-				goto loop;
-		}
-#endif
 		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
 		/* If we aren't called with DO_BRUTE and cmdp is set, it must
 		   be a function and we're being called with DO_NOFUN */
@@ -2651,14 +4146,19 @@
  * Search the table of builtin commands.
  */
 
-struct builtincmd *
-find_builtin(name)
-	char *name;
+static int
+bstrcmp(const void *name, const void *b)
+{
+	return strcmp((const char *)name, (*(const char *const *) b)+1);
+}
+
+static struct builtincmd *
+find_builtin(const char *name)
 {
 	struct builtincmd *bp;
 
-	bp = bsearch( &name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
-		pstrcmp
+	bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
+		bstrcmp
 	);
 	return bp;
 }
@@ -2670,7 +4170,7 @@
  */
 
 static void
-hashcd() {
+hashcd(void) {
 	struct tblentry **pp;
 	struct tblentry *cmdp;
 
@@ -2692,15 +4192,14 @@
  */
 
 static void
-changepath(newval)
-	const char *newval;
+changepath(const char *newval)
 {
 	int firstchange;
 	int bltin;
 
 	firstchange = path_change(newval, &bltin);
 	if (builtinloc < 0 && bltin >= 0)
-		builtinloc = bltin;		/* zap builtins */
+		builtinloc = bltin;             /* zap builtins */
 	clearcmdentry(firstchange);
 	builtinloc = bltin;
 }
@@ -2737,21 +4236,24 @@
 	INTON;
 }
 
+/*
+ * Free a parse tree.
+ */
+
+static void
+freefunc(union node *n)
+{
+	if (n)
+		ckfree(n);
+}
+
 
 /*
  * Delete all functions.
  */
 
-#ifdef mkinit
-static void deletefuncs __P((void));
-
-SHELLPROC {
-	deletefuncs();
-}
-#endif
-
 static void
-deletefuncs() {
+deletefuncs(void) {
 	struct tblentry **tblp;
 	struct tblentry **pp;
 	struct tblentry *cmdp;
@@ -2782,16 +4284,13 @@
  * entry.
  */
 
-struct tblentry **lastcmdentry;
-
+static struct tblentry **lastcmdentry;
 
 static struct tblentry *
-cmdlookup(name, add)
-	char *name;
-	int add;
+cmdlookup(const char *name, int add)
 {
 	int hashval;
-	char *p;
+	const char *p;
 	struct tblentry *cmdp;
 	struct tblentry **pp;
 
@@ -2837,35 +4336,14 @@
 
 
 
-#ifdef notdef
-static void
-getcmdentry(name, entry)
-	char *name;
-	struct cmdentry *entry;
-	{
-	struct tblentry *cmdp = cmdlookup(name, 0);
-
-	if (cmdp) {
-		entry->u = cmdp->param;
-		entry->cmdtype = cmdp->cmdtype;
-	} else {
-		entry->cmdtype = CMDUNKNOWN;
-		entry->u.index = 0;
-	}
-}
-#endif
-
-
 /*
  * Add a new command entry, replacing any existing command entry for
  * the same name.
  */
 
 static void
-addcmdentry(name, entry)
-	char *name;
-	struct cmdentry *entry;
-	{
+addcmdentry(char *name, struct cmdentry *entry)
+{
 	struct tblentry *cmdp;
 
 	INTOFF;
@@ -2883,11 +4361,11 @@
  * Define a shell function.
  */
 
+static union node *copyfunc(union node *);
+
 static void
-defun(name, func)
-	char *name;
-	union node *func;
-	{
+defun(char *name, union node *func)
+{
 	struct cmdentry entry;
 
 	entry.cmdtype = CMDFUNCTION;
@@ -2901,9 +4379,8 @@
  */
 
 static void
-unsetfunc(name)
-	char *name;
-	{
+unsetfunc(char *name)
+{
 	struct tblentry *cmdp;
 
 	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
@@ -2912,6 +4389,26 @@
 	}
 }
 
+/*
+ * Wrapper around strcmp for qsort/bsearch/...
+ */
+static int
+pstrcmp(const void *a, const void *b)
+{
+	return strcmp((const char *) a, *(const char *const *) b);
+}
+
+/*
+ * Find a keyword is in a sorted array.
+ */
+
+static const char *const *
+findkwd(const char *s)
+{
+	return  bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
+			sizeof(const char *), pstrcmp);
+}
+
 #ifdef ASH_TYPE
 /*
  * Locate and print what a word is...
@@ -2932,13 +4429,13 @@
 }
 
 static int
-describe_command(command, verbose)
-	char *command;
-	int verbose;
+describe_command(char *command, int verbose)
 {
 	struct cmdentry entry;
 	struct tblentry *cmdp;
+#ifdef ASH_ALIAS
 	const struct alias *ap;
+#endif
 	const char *path = pathval();
 
 	if (verbose) {
@@ -2951,6 +4448,7 @@
 		goto out;
 	}
 
+#ifdef ASH_ALIAS
 	/* Then look at the aliases */
 	if ((ap = lookupalias(command, 0)) != NULL) {
 		if (verbose) {
@@ -2960,7 +4458,7 @@
 		}
 		goto out;
 	}
-
+#endif
 	/* Then check if it is a tracked alias */
 	if ((cmdp = cmdlookup(command, 0)) != NULL) {
 		entry.cmdtype = cmdp->cmdtype;
@@ -3005,7 +4503,7 @@
 		if (verbose) {
 			out1fmt(
 				" is a %sshell builtin",
-				entry.u.cmd->flags & BUILTIN_SPECIAL ?
+				IS_BUILTIN_SPECIAL(entry.u.cmd) ?
 					"special " : nullstr
 			);
 		} else {
@@ -3024,8 +4522,9 @@
 	out1c('\n');
 	return 0;
 }
-#endif	
+#endif
 
+#ifdef ASH_CMDCMD
 static int
 commandcmd(argc, argv)
 	int argc;
@@ -3066,10 +4565,11 @@
 	if (verify_only || verbose_verify_only) {
 		return describe_command(*argptr, verbose_verify_only);
 	}
-#endif	
+#endif
 
 	return 0;
 }
+#endif
 
 static int
 path_change(newval, bltin)
@@ -3082,7 +4582,7 @@
 
 	old = pathval();
 	new = newval;
-	firstchange = 9999;	/* assume no change */
+	firstchange = 9999;     /* assume no change */
 	idx = 0;
 	*bltin = -1;
 	for (;;) {
@@ -3091,7 +4591,7 @@
 			if ((*old == '\0' && *new == ':')
 			 || (*old == ':' && *new == '\0'))
 				firstchange++;
-			old = new;	/* ignore subsequent differences */
+			old = new;      /* ignore subsequent differences */
 		}
 		if (*new == '\0')
 			break;
@@ -3106,8 +4606,6 @@
 		firstchange = 0;
 	return firstchange;
 }
-/*	$NetBSD: expand.c,v 1.50 2001/02/04 19:52:06 christos Exp $	*/
-
 /*
  * Routines to expand arguments to commands.  We have to deal with
  * backquotes, shell variables, and file metacharacters.
@@ -3115,8 +4613,8 @@
 /*
  * _rmescape() flags
  */
-#define RMESCAPE_ALLOC	0x1	/* Allocate a new string */
-#define RMESCAPE_GLOB	0x2	/* Add backslashes for glob */
+#define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
+#define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
 
 /*
  * Structure specifying which parts of the string should be searched
@@ -3124,66 +4622,62 @@
  */
 
 struct ifsregion {
-	struct ifsregion *next;	/* next region in list */
-	int begoff;		/* offset of start of region */
-	int endoff;		/* offset of end of region */
-	int nulonly;		/* search for nul bytes only */
+	struct ifsregion *next; /* next region in list */
+	int begoff;             /* offset of start of region */
+	int endoff;             /* offset of end of region */
+	int nulonly;            /* search for nul bytes only */
 };
 
 
-static char *expdest;			/* output of current string */
-struct nodelist *argbackq;	/* list of back quote expressions */
-struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
-struct ifsregion *ifslastp;	/* last struct in list */
-struct arglist exparg;		/* holds expanded arg list */
+static char *expdest;                   /* output of current string */
+static struct nodelist *argbackq;      /* list of back quote expressions */
+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 __P((char *, int));
-static char *exptilde __P((char *, int));
-static void expbackq __P((union node *, int, int));
-static int subevalvar __P((char *, char *, int, int, int, int, int));
-static char *evalvar __P((char *, int));
-static int varisset __P((char *, int));
-static void strtodest __P((const char *, const char *, int));
-static void varvalue __P((char *, int, int));
-static void recordregion __P((int, int, int));
-static void removerecordregions __P((int)); 
-static void ifsbreakup __P((char *, struct arglist *));
-static void ifsfree __P((void));
-static void expandmeta __P((struct strlist *, int));
+static void argstr (char *, int);
+static char *exptilde (char *, int);
+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 strtodest (const char *, const char *, int);
+static void varvalue (char *, int, int);
+static void recordregion (int, int, int);
+static void removerecordregions (int);
+static void ifsbreakup (char *, struct arglist *);
+static void ifsfree (void);
+static void expandmeta (struct strlist *, int);
 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
 #if !defined(GLOB_BROKEN)
-static void addglob __P((const glob_t *));
+static void addglob (const glob_t *);
 #endif
 #endif
 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
-static void expmeta __P((char *, char *));
+static void expmeta (char *, char *);
 #endif
-static void addfname __P((char *));
 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
-static struct strlist *expsort __P((struct strlist *));
-static struct strlist *msort __P((struct strlist *, int));
+static struct strlist *expsort (struct strlist *);
+static struct strlist *msort (struct strlist *, int);
 #endif
 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
-static int patmatch __P((char *, char *, int));
-static int patmatch2 __P((char *, char *, int));
+static int patmatch (char *, char *, int);
+static int patmatch2 (char *, char *, int);
 #else
-static int pmatch __P((char *, char *, int));
+static int pmatch (char *, char *, int);
 #define patmatch2 patmatch
 #endif
-static char *cvtnum __P((int, char *));
-
-extern int oexitstatus;
+static char *cvtnum (int, char *);
 
 /*
  * Expand shell variables and backquotes inside a here document.
  */
 
+/* arg: the document, fd: where to write the expanded version */
 static void
-expandhere(arg, fd)
-	union node *arg;	/* the document */
-	int fd;			/* where to write the expanded version */
-	{
+expandhere(union node *arg, int fd)
+{
 	herefd = fd;
 	expandarg(arg, (struct arglist *)NULL, 0);
 	xwrite(fd, stackblock(), expdest - stackblock());
@@ -3212,7 +4706,7 @@
 	ifslastp = NULL;
 	argstr(arg->narg.text, flag);
 	if (arglist == NULL) {
-		return;			/* here document expanded */
+		return;                 /* here document expanded */
 	}
 	STPUTC('\0', expdest);
 	p = grabstackstr(expdest);
@@ -3255,7 +4749,7 @@
 	int flag;
 {
 	char c;
-	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
+	int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
 	int firsteq = 1;
 
 	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
@@ -3290,7 +4784,7 @@
 		case CTLENDARI:
 			expari(flag);
 			break;
-#endif	
+#endif
 		case ':':
 		case '=':
 			/*
@@ -3362,9 +4856,8 @@
 }
 
 
-static void 
-removerecordregions(endoff)
-	int endoff;
+static void
+removerecordregions(int endoff)
 {
 	if (ifslastp == NULL)
 		return;
@@ -3386,7 +4879,7 @@
 		}
 		return;
 	}
-	
+
 	ifslastp = &ifsfirst;
 	while (ifslastp->next && ifslastp->next->begoff < endoff)
 		ifslastp=ifslastp->next;
@@ -3409,8 +4902,7 @@
  * evaluate, place result in (backed up) result, adjust string position.
  */
 static void
-expari(flag)
-	int flag;
+expari(int flag)
 {
 	char *p, *start;
 	int result;
@@ -3418,7 +4910,7 @@
 	int quotes = flag & (EXP_FULL | EXP_CASE);
 	int quoted;
 
-	/*	ifsfree(); */
+	/*      ifsfree(); */
 
 	/*
 	 * This routine is slightly over-complicated for
@@ -3462,8 +4954,7 @@
 	result = expdest - p + 1;
 	STADJUST(-result, expdest);
 }
-#endif	
-
+#endif
 
 /*
  * Expand stuff in backwards quotes.
@@ -3573,8 +5064,6 @@
 	INTON;
 }
 
-
-
 static int
 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
 	char *p;
@@ -3630,7 +5119,7 @@
 				goto recordleft;
 			*loc = c;
 			if (quotes && *loc == CTLESC)
-			        loc++;
+				loc++;
 		}
 		return 0;
 
@@ -3653,11 +5142,11 @@
 		return 0;
 
 	case VSTRIMRIGHT:
-	        for (loc = str - 1; loc >= startp;) {
+		for (loc = str - 1; loc >= startp;) {
 			if (patmatch2(str, loc, quotes))
 				goto recordright;
 			loc--;
-			if (quotes && loc > startp && *(loc - 1) == CTLESC) { 
+			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
 				for (q = startp; q < loc; q++)
 					if (*q == CTLESC)
 						q++;
@@ -3672,7 +5161,7 @@
 			if (patmatch2(str, loc, quotes))
 				goto recordright;
 			if (quotes && *loc == CTLESC)
-			        loc++;
+				loc++;
 		}
 		return 0;
 
@@ -3788,7 +5277,7 @@
 	case VSPLUS:
 	case VSMINUS:
 		if (!set) {
-		        argstr(p, flag);
+			argstr(p, flag);
 			break;
 		}
 		if (easy)
@@ -3822,9 +5311,9 @@
 			if (subevalvar(p, var, 0, subtype, startloc,
 				       varflags, quotes)) {
 				varflags &= ~VSNUL;
-				/* 
-				 * Remove any recorded regions beyond 
-				 * start of variable 
+				/*
+				 * Remove any recorded regions beyond
+				 * start of variable
 				 */
 				removerecordregions(startloc);
 				goto again;
@@ -3841,7 +5330,7 @@
 #endif
 	}
 
-	if (subtype != VSNORMAL) {	/* skip to end of alternative */
+	if (subtype != VSNORMAL) {      /* skip to end of alternative */
 		int nesting = 1;
 		for (;;) {
 			if ((c = *p++) == CTLESC)
@@ -3861,8 +5350,6 @@
 	return p;
 }
 
-
-
 /*
  * Test whether a specialized variable is set.
  */
@@ -3904,8 +5391,6 @@
 	return 1;
 }
 
-
-
 /*
  * Put a string on the stack.
  */
@@ -3923,8 +5408,6 @@
 	}
 }
 
-
-
 /*
  * Add the value of a specialized variable to the stack string.
  */
@@ -3963,8 +5446,8 @@
 		break;
 	case '-':
 		for (i = 0 ; i < NOPTS ; i++) {
-			if (optlist[i].val)
-				STPUTC(optlist[i].letter, expdest);
+			if (optent_val(i))
+				STPUTC(optent_letter(optlist[i]), expdest);
 		}
 		break;
 	case '@':
@@ -4001,7 +5484,6 @@
 }
 
 
-
 /*
  * Record the fact that we have to scan this region of the
  * string for IFS characters.
@@ -4136,7 +5618,22 @@
 	ifsfirst.next = NULL;
 }
 
+/*
+ * Add a file name to the list.
+ */
 
+static void
+addfname(const char *name)
+{
+	char *p;
+	struct strlist *sp;
+
+	p = sstrdup(name);
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = p;
+	*exparg.lastp = sp;
+	exparg.lastp = &sp->next;
+}
 
 /*
  * Expand shell metacharacters.  At this point, the only control characters
@@ -4175,7 +5672,7 @@
 			rmescapes(str->text);
 			exparg.lastp = &str->next;
 			break;
-		default:	/* GLOB_NOSPACE */
+		default:        /* GLOB_NOSPACE */
 			error("Out of space");
 		}
 		str = str->next;
@@ -4199,7 +5696,7 @@
 }
 
 
-#else	/* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
+#else   /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
 static char *expdir;
 
 
@@ -4218,7 +5715,7 @@
 		if (fflag)
 			goto nometa;
 		p = str->text;
-		for (;;) {			/* fast check for meta chars */
+		for (;;) {                      /* fast check for meta chars */
 			if ((c = *p++) == '\0')
 				goto nometa;
 			if (c == '*' || c == '?' || c == '[' || c == '!')
@@ -4297,7 +5794,7 @@
 					break;
 				}
 			}
-		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
+		} else if (*p == '!' && p[1] == '!'     && (p == name || p[-1] == '/')) {
 			metaflag = 1;
 		} else if (*p == '\0')
 			break;
@@ -4311,7 +5808,7 @@
 			start = p + 1;
 		}
 	}
-	if (metaflag == 0) {	/* we've reached the end of the file name */
+	if (metaflag == 0) {    /* we've reached the end of the file name */
 		if (enddir != expdir)
 			metaflag++;
 		for (p = name ; ; p++) {
@@ -4369,7 +5866,7 @@
 			continue;
 		if (patmatch(start, dp->d_name, 0)) {
 			if (atend) {
-				scopy(dp->d_name, enddir);
+				strcpy(enddir, dp->d_name);
 				addfname(expdir);
 			} else {
 				for (p = enddir, cp = dp->d_name;
@@ -4384,27 +5881,9 @@
 	if (! atend)
 		endname[-1] = '/';
 }
-#endif	/* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
+#endif  /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
 
 
-/*
- * Add a file name to the list.
- */
-
-static void
-addfname(name)
-	char *name;
-	{
-	char *p;
-	struct strlist *sp;
-
-	p = sstrdup(name);
-	sp = (struct strlist *)stalloc(sizeof *sp);
-	sp->text = p;
-	*exparg.lastp = sp;
-	exparg.lastp = &sp->next;
-}
-
 
 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
 /*
@@ -4445,9 +5924,9 @@
 		q = p;
 		p = p->next;
 	}
-	q->next = NULL;			/* terminate first half of list */
-	q = msort(list, half);		/* sort first half of list */
-	p = msort(p, len - half);		/* sort second half */
+	q->next = NULL;                 /* terminate first half of list */
+	q = msort(list, half);          /* sort first half of list */
+	p = msort(p, len - half);               /* sort second half */
 	lpp = &list;
 	for (;;) {
 		if (strcmp(p->text, q->text) < 0) {
@@ -4477,12 +5956,10 @@
  */
 
 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
+/* squoted: string might have quote chars */
 static int
-patmatch(pattern, string, squoted)
-	char *pattern;
-	char *string;
-	int squoted;	/* string might have quote chars */
-	{
+patmatch(char *pattern, char *string, int squoted)
+{
 	const char *p;
 	char *q;
 
@@ -4494,11 +5971,8 @@
 
 
 static int
-patmatch2(pattern, string, squoted)
-	char *pattern;
-	char *string;
-	int squoted;	/* string might have quote chars */
-	{
+patmatch2(char *pattern, char *string, int squoted)
+{
 	char *p;
 	int res;
 
@@ -4510,26 +5984,14 @@
 }
 #else
 static int
-patmatch(pattern, string, squoted)
-	char *pattern;
-	char *string;
-	int squoted;	/* string might have quote chars */
-	{
-#ifdef notdef
-	if (pattern[0] == '!' && pattern[1] == '!')
-		return 1 - pmatch(pattern + 2, string);
-	else
-#endif
-		return pmatch(pattern, string, squoted);
+patmatch(char *pattern, char *string, int squoted) {
+	return pmatch(pattern, string, squoted);
 }
 
 
 static int
-pmatch(pattern, string, squoted)
-	char *pattern;
-	char *string;
-	int squoted;
-	{
+pmatch(char *pattern, char *string, int squoted)
+{
 	char *p, *q;
 	char c;
 
@@ -4589,7 +6051,7 @@
 				while (*endp == CTLQUOTEMARK)
 					endp++;
 				if (*endp == '\0')
-					goto dft;		/* no matching ] */
+					goto dft;               /* no matching ] */
 				if (*endp == CTLESC)
 					endp++;
 				if (*++endp == ']')
@@ -4630,7 +6092,7 @@
 				return 0;
 			break;
 		}
-dft:	        default:
+dft:            default:
 			if (squoted && *q == CTLESC)
 				q++;
 			if (*q++ != c)
@@ -4653,9 +6115,7 @@
 
 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
 static char *
-_rmescapes(str, flag)
-	char *str;
-	int flag;
+_rmescapes(char *str, int flag)
 {
 	char *p, *q, *r;
 	static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
@@ -4727,10 +6187,8 @@
  */
 
 static int
-casematch(pattern, val)
-	union node *pattern;
-	char *val;
-	{
+casematch(union node *pattern, const char *val)
+{
 	struct stackmark smark;
 	int result;
 	char *p;
@@ -4742,7 +6200,7 @@
 	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
 	STPUTC('\0', expdest);
 	p = grabstackstr(expdest);
-	result = patmatch(p, val, 0);
+	result = patmatch(p, (char *)val, 0);
 	popstackmark(&smark);
 	return result;
 }
@@ -4763,8 +6221,6 @@
 	STADJUST(len, buf);
 	return buf;
 }
-/*	$NetBSD: histedit.c,v 1.25 2001/02/04 19:52:06 christos Exp $	*/
-
 /*
  * Editline and history functions (and glue).
  */
@@ -4777,54 +6233,15 @@
 }
 
 
-/*
- * This file was generated by the mkinit program.
- */
+static int whichprompt;         /* 1 == PS1, 2 == PS2 */
 
-extern void rmaliases __P((void));
-
-extern int loopnest;		/* current loop nesting level */
-
-extern void deletefuncs __P((void));
-
-struct strpush {
-	struct strpush *prev;	/* preceding string on stack */
-	char *prevstring;
-	int prevnleft;
-	struct alias *ap;	/* if push was associated with an alias */
-	char *string;		/* remember the string since it may change */
-};
-
-struct parsefile {
-	struct parsefile *prev;	/* preceding file on stack */
-	int linno;		/* current line */
-	int fd;			/* file descriptor (or -1 if string) */
-	int nleft;		/* number of chars left in this line */
-	int lleft;		/* number of chars left in this buffer */
-	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 */
-};
-
-extern int parselleft;		/* copy of parsefile->lleft */
-extern struct parsefile basepf;	/* top level input file */
-extern char basebuf[BUFSIZ];	/* buffer for top level input file */
-
-extern short backgndpid;	/* pid of last background process */
-extern int jobctl;
-
-extern int tokpushback;		/* last token pushed back */
-extern int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
 
 struct redirtab {
 	struct redirtab *next;
 	short renamed[10];
 };
 
-extern struct redirtab *redirlist;
-
-extern char sigmode[NSIG - 1];	/* current value of signal */
+static struct redirtab *redirlist;
 
 extern char **environ;
 
@@ -4835,7 +6252,7 @@
  */
 
 static void
-init() {
+init(void) {
 
       /* from cd.c: */
       {
@@ -4878,8 +6295,13 @@
  * interactive shell and control is returned to the main command loop.
  */
 
+#ifdef ASH_ALIAS
+/* 1 == check for aliases, 2 == also check for assignments */
+static int checkalias;
+#endif
+
 static void
-reset() {
+reset(void) {
 
       /* from eval.c: */
       {
@@ -4891,7 +6313,7 @@
       /* from input.c: */
       {
 	      if (exception != EXSHELLPROC)
-		      parselleft = parsenleft = 0;	/* clear input buffer */
+		      parselleft = parsenleft = 0;      /* clear input buffer */
 	      popallfiles();
       }
 
@@ -4899,7 +6321,9 @@
       {
 	      tokpushback = 0;
 	      checkkwd = 0;
+#ifdef ASH_ALIAS
 	      checkalias = 0;
+#endif
       }
 
       /* from redir.c: */
@@ -4926,69 +6350,6 @@
 
 
 /*
- * This routine is called to initialize the shell to run a shell procedure.
- */
-
-static void
-initshellproc() {
-
-      /* from alias.c: */
-      {
-	      rmaliases();
-      }
-
-      /* from eval.c: */
-      {
-	      exitstatus = 0;
-      }
-
-      /* from exec.c: */
-      {
-	      deletefuncs();
-      }
-
-      /* from jobs.c: */
-      {
-	      backgndpid = -1;
-#if JOBS
-	      jobctl = 0;
-#endif
-      }
-
-      /* from options.c: */
-      {
-	      int i;
-
-	      for (i = 0; i < NOPTS; i++)
-		      optlist[i].val = 0;
-	      optschanged();
-
-      }
-
-      /* from redir.c: */
-      {
-	      clearredir();
-      }
-
-      /* from trap.c: */
-      {
-	      char *sm;
-
-	      clear_traps();
-	      for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
-		      if (*sm == S_IGN)
-			      *sm = S_HARD_IGN;
-	      }
-      }
-
-      /* from var.c: */
-      {
-	      shprocvar();
-      }
-}
-/*	$NetBSD: input.c,v 1.35 2001/02/04 19:52:06 christos Exp $	*/
-
-/*
  * This file implements the input routines used by the parser.
  */
 
@@ -5004,45 +6365,34 @@
 }
 #endif
 
-#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+#define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
 
-static int plinno = 1;			/* input line number */
-static int parsenleft;			/* copy of parsefile->nleft */
-static int parselleft;		/* copy of parsefile->lleft */
-static char *parsenextc;		/* copy of parsefile->nextc */
-struct parsefile basepf;	/* top level input file */
-static char basebuf[BUFSIZ];	/* buffer for top level input file */
-struct parsefile *parsefile = &basepf;	/* current input file */
-static int whichprompt;		/* 1 == PS1, 2 == PS2 */
 
-static void pushfile __P((void));
-static int preadfd __P((void));
 
-#ifdef mkinit
-INCLUDE <stdio.h>
-INCLUDE "input.h"
-INCLUDE "error.h"
+/*
+ * Same as pgetc(), but ignores PEOA.
+ */
 
-INIT {
-	basepf.nextc = basepf.buf = basebuf;
+#ifdef ASH_ALIAS
+static int
+pgetc2()
+{
+	int c;
+	do {
+		c = pgetc_macro();
+	} while (c == PEOA);
+	return c;
 }
-
-RESET {
-	if (exception != EXSHELLPROC)
-		parselleft = parsenleft = 0;	/* clear input buffer */
-	popallfiles();
-}
+#else
+static inline int pgetc2() { return pgetc_macro(); }
 #endif
 
-
 /*
  * Read a line from the script.
  */
 
 static char *
-pfgets(line, len)
-	char *line;
-	int len;
+pfgets(char *line, int len)
 {
 	char *p = line;
 	int nleft = len;
@@ -5063,36 +6413,8 @@
 	return line;
 }
 
-
-/*
- * Read a character from the script, returning PEOF on end of file.
- * Nul characters in the input are silently discarded.
- */
-
 static int
-pgetc()
-{
-	return pgetc_macro();
-}
-
-
-/*
- * Same as pgetc(), but ignores PEOA.
- */
-
-static int
-pgetc2()
-{
-	int c;
-	do {
-		c = pgetc_macro();
-	} while (c == PEOA);
-	return c;
-}
-
-
-static int
-preadfd()
+preadfd(void)
 {
     int nr;
     char *buf =  parsefile->buf;
@@ -5103,7 +6425,7 @@
 	{
 	    if (parsefile->fd)
 		nr = read(parsefile->fd, buf, BUFSIZ - 1);
-	    else { 
+	    else {
 		do {
 		    cmdedit_read_input((char*)cmdedit_prompt, buf);
 		    nr = strlen(buf);
@@ -5132,6 +6454,39 @@
 	return nr;
 }
 
+static void
+popstring(void)
+{
+	struct strpush *sp = parsefile->strpush;
+
+	INTOFF;
+#ifdef ASH_ALIAS
+	if (sp->ap) {
+		if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
+			if (!checkalias) {
+				checkalias = 1;
+			}
+		}
+		if (sp->string != sp->ap->val) {
+			ckfree(sp->string);
+		}
+
+		sp->ap->flag &= ~ALIASINUSE;
+		if (sp->ap->flag & ALIASDEAD) {
+			unalias(sp->ap->name);
+		}
+	}
+#endif
+	parsenextc = sp->prevstring;
+	parsenleft = sp->prevnleft;
+/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+	parsefile->strpush = sp->prev;
+	if (sp != &(parsefile->basestrpush))
+		ckfree(sp);
+	INTON;
+}
+
+
 /*
  * Refill the input buffer and return the next input character:
  *
@@ -5143,19 +6498,19 @@
  */
 
 static int
-preadbuffer()
+preadbuffer(void)
 {
 	char *p, *q;
 	int more;
 	char savec;
 
 	while (parsefile->strpush) {
-		if (
-			parsenleft == -1 && parsefile->strpush->ap &&
-			parsenextc[-1] != ' ' && parsenextc[-1] != '\t'
-		) {
+#ifdef ASH_ALIAS
+		if (parsenleft == -1 && parsefile->strpush->ap &&
+			parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
 			return PEOA;
 		}
+#endif
 		popstring();
 		if (--parsenleft >= 0)
 			return (*parsenextc++);
@@ -5181,7 +6536,7 @@
 	for (more = 1; more;) {
 		switch (*p) {
 		case '\0':
-			p++;	/* Skip nul */
+			p++;    /* Skip nul */
 			goto check;
 
 
@@ -5216,27 +6571,14 @@
 	return *parsenextc++;
 }
 
-/*
- * Undo the last call to pgetc.  Only one character may be pushed back.
- * PEOF may be pushed back.
- */
-
-static void
-pungetc() {
-	parsenleft++;
-	parsenextc--;
-}
 
 /*
  * Push a string back onto the input at this current parsefile level.
  * We handle aliases this way.
  */
 static void
-pushstring(s, len, ap)
-	char *s;
-	int len;
-	void *ap;
-	{
+pushstring(char *s, int len, void *ap)
+{
 	struct strpush *sp;
 
 	INTOFF;
@@ -5249,97 +6591,19 @@
 		sp = parsefile->strpush = &(parsefile->basestrpush);
 	sp->prevstring = parsenextc;
 	sp->prevnleft = parsenleft;
+#ifdef ASH_ALIAS
 	sp->ap = (struct alias *)ap;
 	if (ap) {
 		((struct alias *)ap)->flag |= ALIASINUSE;
 		sp->string = s;
 	}
+#endif
 	parsenextc = s;
 	parsenleft = len;
 	INTON;
 }
 
-static void
-popstring()
-{
-	struct strpush *sp = parsefile->strpush;
 
-	INTOFF;
-	if (sp->ap) {
-		if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
-			if (!checkalias) {
-				checkalias = 1;
-			}
-		}
-		if (sp->string != sp->ap->val) {
-			ckfree(sp->string);
-		}
-		sp->ap->flag &= ~ALIASINUSE;
-		if (sp->ap->flag & ALIASDEAD) {
-			unalias(sp->ap->name);
-		}
-	}
-	parsenextc = sp->prevstring;
-	parsenleft = sp->prevnleft;
-/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
-	parsefile->strpush = sp->prev;
-	if (sp != &(parsefile->basestrpush))
-		ckfree(sp);
-	INTON;
-}
-
-/*
- * Set the input to take input from a file.  If push is set, push the
- * old input onto the stack first.
- */
-
-static void
-setinputfile(fname, push)
-	const char *fname;
-	int push;
-{
-	int fd;
-	int myfileno2;
-
-	INTOFF;
-	if ((fd = open(fname, O_RDONLY)) < 0)
-		error("Can't open %s", fname);
-	if (fd < 10) {
-		myfileno2 = dup_as_newfd(fd, 10);
-		close(fd);
-		if (myfileno2 < 0)
-			error("Out of file descriptors");
-		fd = myfileno2;
-	}
-	setinputfd(fd, push);
-	INTON;
-}
-
-
-/*
- * Like setinputfile, but takes an open file descriptor.  Call this with
- * interrupts off.
- */
-
-static void
-setinputfd(fd, push)
-	int fd, push;
-{
-	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
-	if (push) {
-		pushfile();
-		parsefile->buf = 0;
-	} else {
-		closescript();
-		while (parsefile->strpush)
-			popstring();
-	}
-	parsefile->fd = fd;
-	if (parsefile->buf == NULL)
-		parsefile->buf = ckmalloc(BUFSIZ);
-	parselleft = parsenleft = 0;
-	plinno = 1;
-}
 
 
 /*
@@ -5367,7 +6631,7 @@
  */
 
 static void
-pushfile() {
+pushfile(void) {
 	struct parsefile *pf;
 
 	parsefile->nleft = parsenleft;
@@ -5382,79 +6646,42 @@
 	parsefile = pf;
 }
 
-
-static void
-popfile() {
-	struct parsefile *pf = parsefile;
-
-	INTOFF;
-	if (pf->fd >= 0)
-		close(pf->fd);
-	if (pf->buf)
-		ckfree(pf->buf);
-	while (pf->strpush)
-		popstring();
-	parsefile = pf->prev;
-	ckfree(pf);
-	parsenleft = parsefile->nleft;
-	parselleft = parsefile->lleft;
-	parsenextc = parsefile->nextc;
-	plinno = parsefile->linno;
-	INTON;
-}
-
-
-/*
- * Return to top level.
- */
-
-static void
-popallfiles() {
-	while (parsefile != &basepf)
-		popfile();
-}
-
-
-
-/*
- * Close the file(s) that the shell is reading commands from.  Called
- * after a fork is done.
- */
-
-static void
-closescript() {
-	popallfiles();
-	if (parsefile->fd > 0) {
-		close(parsefile->fd);
-		parsefile->fd = 0;
-	}
-}
-/*	$NetBSD: jobs.c,v 1.36 2000/05/22 10:18:47 elric Exp $	*/
-
-
-struct job *jobtab;		/* array of jobs */
-static int njobs;			/* size of array */
-short backgndpid = -1;	/* pid of last background process */
-#if JOBS
-static int initialpgrp;		/* pgrp of shell on invocation */
-short curjob;			/* current job */
+#ifdef JOBS
+static void restartjob (struct job *);
 #endif
-static int intreceived;
-
-static void restartjob __P((struct job *));
-static void freejob __P((struct job *));
-static struct job *getjob __P((char *));
-static int dowait __P((int, struct job *));
-#ifdef SYSV
-static int onsigchild __P((void));
-#endif
-static int waitproc __P((int, int *));
-static void cmdtxt __P((union node *));
-static void cmdputs __P((const char *));
+static void freejob (struct job *);
+static struct job *getjob (const char *);
+static int dowait (int, struct job *);
+static int waitproc (int, int *);
 static void waitonint(int);
 
 
-#if JOBS
+/*
+ * We keep track of whether or not fd0 has been redirected.  This is for
+ * background commands, where we want to redirect fd0 to /dev/null only
+ * if it hasn't already been redirected.
+*/
+static int fd0_redirected = 0;
+
+/* Return true if fd 0 has already been redirected at least once.  */
+static inline int
+fd0_redirected_p () {
+	return fd0_redirected != 0;
+}
+
+/*
+ * We also keep track of where fileno2 goes.
+ */
+static int fileno2 = 2;
+
+static int openredirect (union node *);
+static void dupredirect (union node *, int, char[10 ]);
+static int openhere (union node *);
+static int noclobberopen (const char *);
+
+
+
+#ifdef JOBS
 /*
  * Turn job control on and off.
  *
@@ -5463,7 +6690,7 @@
  * System V doesn't have job control yet, this isn't a problem now.
  */
 
-static int jobctl;
+
 
 static void setjobctl(int enable)
 {
@@ -5524,22 +6751,6 @@
 #endif
 
 
-#ifdef mkinit
-INCLUDE <stdlib.h>
-
-SHELLPROC {
-	backgndpid = -1;
-#if JOBS
-	jobctl = 0;
-#endif
-}
-
-#endif
-
-
-/* This file was automatically created by ./mksignames.
-   Do not edit.  Edit support/mksignames.c instead. */
-
 /* A translation list so we can be polite to our users. */
 static char *signal_names[NSIG + 2] = {
     "EXIT",
@@ -5612,7 +6823,7 @@
 
 
 
-#if JOBS
+#ifdef JOBS
 static int
 killcmd(argc, argv)
 	int argc;
@@ -5650,7 +6861,7 @@
 							optionarg
 						);
 					}
-		                        break;
+					break;
 #ifdef DEBUG
 				default:
 					error(
@@ -5697,7 +6908,7 @@
 		} else
 			pid = atoi(*argptr);
 		if (kill(pid, signo) != 0)
-			error("%s: %s", *argptr, strerror(errno));
+			error("%s: %m", *argptr);
 	} while (*++argptr);
 
 	return 0;
@@ -5767,6 +6978,8 @@
 }
 #endif
 
+static void showjobs(int change);
+
 
 static int
 jobscmd(argc, argv)
@@ -5811,12 +7024,12 @@
 		if (change && ! jp->changed)
 			continue;
 		procno = jp->nprocs;
-		for (ps = jp->ps ; ; ps++) {	/* for each process */
+		for (ps = jp->ps ; ; ps++) {    /* for each process */
 			if (ps == jp->ps)
-				fmtstr(s, 64, "[%d] %ld ", jobno, 
+				fmtstr(s, 64, "[%d] %ld ", jobno,
 				    (long)ps->pid);
 			else
-				fmtstr(s, 64, "    %ld ", 
+				fmtstr(s, 64, "    %ld ",
 				    (long)ps->pid);
 			out1str(s);
 			col = strlen(s);
@@ -5824,17 +7037,17 @@
 			if (ps->status == -1) {
 				/* don't print anything */
 			} else if (WIFEXITED(ps->status)) {
-				fmtstr(s, 64, "Exit %d", 
+				fmtstr(s, 64, "Exit %d",
 				       WEXITSTATUS(ps->status));
 			} else {
-#if JOBS
-				if (WIFSTOPPED(ps->status)) 
+#ifdef JOBS
+				if (WIFSTOPPED(ps->status))
 					i = WSTOPSIG(ps->status);
 				else /* WIFSIGNALED(ps->status) */
 #endif
 					i = WTERMSIG(ps->status);
 				if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
-					scopy(sys_siglist[i & 0x7F], s);
+					strcpy(s, sys_siglist[i & 0x7F]);
 				else
 					fmtstr(s, 64, "Signal %d", i & 0x7F);
 				if (WCOREDUMP(ps->status))
@@ -5876,7 +7089,7 @@
 	if (jp->ps != &jp->ps0)
 		ckfree(jp->ps);
 	jp->used = 0;
-#if JOBS
+#ifdef JOBS
 	if (curjob == jp - jobtab + 1)
 		curjob = 0;
 #endif
@@ -5900,7 +7113,7 @@
 	} else {
 		job = NULL;
 	}
-	for (;;) {	/* loop until process terminated or stopped */
+	for (;;) {      /* loop until process terminated or stopped */
 		if (job != NULL) {
 			if (job->state) {
 				status = job->ps[job->nprocs - 1].status;
@@ -5911,7 +7124,7 @@
 				}
 				if (WIFEXITED(status))
 					retval = WEXITSTATUS(status);
-#if JOBS
+#ifdef JOBS
 				else if (WIFSTOPPED(status))
 					retval = WSTOPSIG(status) + 128;
 #endif
@@ -5923,7 +7136,7 @@
 			}
 		} else {
 			for (jp = jobtab ; ; jp++) {
-				if (jp >= jobtab + njobs) {	/* no running procs */
+				if (jp >= jobtab + njobs) {     /* no running procs */
 					return 0;
 				}
 				if (jp->used && jp->state == 0)
@@ -5943,16 +7156,15 @@
  */
 
 static struct job *
-getjob(name)
-	char *name;
-	{
+getjob(const char *name)
+{
 	int jobno;
 	struct job *jp;
 	int pid;
 	int i;
 
 	if (name == NULL) {
-#if JOBS
+#ifdef JOBS
 currentjob:
 		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
 			error("No current job");
@@ -5966,7 +7178,7 @@
 			if (jobno > 0 && jobno <= njobs
 			 && jobtab[jobno - 1].used != 0)
 				return &jobtab[jobno - 1];
-#if JOBS
+#ifdef JOBS
 		} else if (name[1] == '%' && name[2] == '\0') {
 			goto currentjob;
 #endif
@@ -5983,8 +7195,7 @@
 			if (found)
 				return found;
 		}
-	} else if (is_number(name)) {
-		pid = number(name);
+	} else if (is_number(name, &pid)) {
 		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
 			if (jp->used && jp->nprocs > 0
 			 && jp->ps[jp->nprocs - 1].pid == pid)
@@ -6001,7 +7212,7 @@
  * Return a new job structure,
  */
 
-struct job *
+static struct job *
 makejob(node, nprocs)
 	union node *node;
 	int nprocs;
@@ -6037,7 +7248,7 @@
 	jp->used = 1;
 	jp->changed = 0;
 	jp->nprocs = 0;
-#if JOBS
+#ifdef JOBS
 	jp->jobctl = jobctl;
 #endif
 	if (nprocs > 1) {
@@ -6057,21 +7268,20 @@
  * own process group.  Jp is a job structure that the job is to be added to.
  * N is the command that will be evaluated by the child.  Both jp and n may
  * be NULL.  The mode parameter can be one of the following:
- *	FORK_FG - Fork off a foreground process.
- *	FORK_BG - Fork off a background process.
- *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
- *		     process group even if job control is on.
+ *      FORK_FG - Fork off a foreground process.
+ *      FORK_BG - Fork off a background process.
+ *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *                   process group even if job control is on.
  *
  * When job control is turned off, background processes have their standard
  * input redirected to /dev/null (except for the second and later processes
  * in a pipeline).
  */
 
+
+
 static int
-forkshell(jp, n, mode)
-	union node *n;
-	struct job *jp;
-	int mode;
+forkshell(struct job *jp, union node *n, int mode)
 {
 	int pid;
 	int pgrp;
@@ -6098,8 +7308,8 @@
 		closescript();
 		INTON;
 		clear_traps();
-#if JOBS
-		jobctl = 0;		/* do job control only in root shell */
+#ifdef JOBS
+		jobctl = 0;             /* do job control only in root shell */
 		if (wasroot && mode != FORK_NOJOB && mflag) {
 			if (jp == NULL || jp->nprocs == 0)
 				pgrp = getpid();
@@ -6158,7 +7368,7 @@
 		setpgid(pid, pgrp);
 	}
 	if (mode == FORK_BG)
-		backgndpid = pid;		/* set $! */
+		backgndpid = pid;               /* set $! */
 	if (jp) {
 		struct procstat *ps = &jp->ps[jp->nprocs++];
 		ps->pid = pid;
@@ -6197,7 +7407,7 @@
 waitforjob(jp)
 	struct job *jp;
 	{
-#if JOBS
+#ifdef JOBS
 	int mypgrp = getpgrp();
 #endif
 	int status;
@@ -6206,7 +7416,7 @@
 
 	INTOFF;
 	intreceived = 0;
-#if JOBS
+#ifdef JOBS
 	if (!jobctl) {
 #else
 	if (!iflag) {
@@ -6219,7 +7429,7 @@
 	while (jp->state == 0) {
 		dowait(1, jp);
 	}
-#if JOBS
+#ifdef JOBS
 	if (!jobctl) {
 #else
 	if (!iflag) {
@@ -6227,7 +7437,7 @@
 		sigaction(SIGINT, &oact, 0);
 		if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
 	}
-#if JOBS
+#ifdef JOBS
 	if (jp->jobctl) {
 #ifdef OLD_TTY_DRIVER
 		if (ioctl(fileno2, TIOCSPGRP, (char *)&mypgrp) < 0)
@@ -6244,13 +7454,13 @@
 	/* convert to 8 bits */
 	if (WIFEXITED(status))
 		st = WEXITSTATUS(status);
-#if JOBS
+#ifdef JOBS
 	else if (WIFSTOPPED(status))
 		st = WSTOPSIG(status) + 128;
 #endif
 	else
 		st = WTERMSIG(status) + 128;
-#if JOBS
+#ifdef JOBS
 	if (jp->jobctl) {
 		/*
 		 * This is truly gross.
@@ -6263,8 +7473,9 @@
 		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
 			raise(SIGINT);
 	}
+	if (jp->state == JOBDONE)
+
 #endif
-	if (! JOBS || jp->state == JOBDONE)
 		freejob(jp);
 	INTON;
 	return st;
@@ -6317,14 +7528,14 @@
 				else if (WIFSTOPPED(sp->status))
 					done = 0;
 			}
-			if (stopped) {		/* stopped or done */
+			if (stopped) {          /* stopped or done */
 				int state = done? JOBDONE : JOBSTOPPED;
 				if (jp->state != state) {
 					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
 					jp->state = state;
-#if JOBS
+#ifdef JOBS
 					if (done && curjob == jp - jobtab + 1)
-						curjob = 0;		/* no current job */
+						curjob = 0;             /* no current job */
 #endif
 				}
 			}
@@ -6333,7 +7544,7 @@
 	INTON;
 	if (! rootshell || ! iflag || (job && thisjob == job)) {
 		core = WCOREDUMP(status);
-#if JOBS
+#ifdef JOBS
 		if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
 		else
 #endif
@@ -6343,7 +7554,7 @@
 		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
 			if (thisjob != job)
 				outfmt(out2, "%d: ", pid);
-#if JOBS
+#ifdef JOBS
 			if (sig == SIGTSTP && rootshell && iflag)
 				outfmt(out2, "%%%ld ",
 				    (long)(job - jobtab + 1));
@@ -6359,7 +7570,7 @@
 			flushout(&errout);
 #endif
 		} else {
-			TRACE(("Not printing status: status=%d, sig=%d\n", 
+			TRACE(("Not printing status: status=%d, sig=%d\n",
 			       status, sig));
 		}
 	} else {
@@ -6394,64 +7605,30 @@
  * then checking to see whether it was called.  If there are any
  * children to be waited for, it will be.
  *
- * If neither SYSV nor BSD is defined, we don't implement nonblocking
- * waits at all.  In this case, the user will not be informed when
- * a background process until the next time she runs a real program
- * (as opposed to running a builtin command or just typing return),
- * and the jobs command may give out of date information.
  */
 
-#ifdef SYSV
-static int gotsigchild;
-
-static int onsigchild() {
-	gotsigchild = 1;
-}
-#endif
-
-
 static int
 waitproc(block, status)
 	int block;
 	int *status;
 {
-#ifdef BSD
 	int flags;
 
 	flags = 0;
-#if JOBS
+#ifdef JOBS
 	if (jobctl)
 		flags |= WUNTRACED;
 #endif
 	if (block == 0)
 		flags |= WNOHANG;
 	return wait3(status, flags, (struct rusage *)NULL);
-#else
-#ifdef SYSV
-	int (*save)();
-
-	if (block == 0) {
-		gotsigchild = 0;
-		save = signal(SIGCLD, onsigchild);
-		signal(SIGCLD, save);
-		if (gotsigchild == 0)
-			return 0;
-	}
-	return wait(status);
-#else
-	if (block == 0)
-		return 0;
-	return wait(status);
-#endif
-#endif
 }
 
 /*
  * return 1 if there are stopped jobs, otherwise 0
  */
-static int job_warning = 0;
 static int
-stoppedjobs()
+stoppedjobs(void)
 {
 	int jobno;
 	struct job *jp;
@@ -6478,26 +7655,51 @@
 
 static char *cmdnextc;
 static int cmdnleft;
-#define MAXCMDTEXT	200
+#define MAXCMDTEXT      200
 
-static char *
-commandtext(n)
-	union node *n;
-	{
-	char *name;
+static void
+cmdputs(const char *s)
+{
+	const char *p;
+	char *q;
+	char c;
+	int subtype = 0;
 
-	cmdnextc = name = ckmalloc(MAXCMDTEXT);
-	cmdnleft = MAXCMDTEXT - 4;
-	cmdtxt(n);
-	*cmdnextc = '\0';
-	return name;
+	if (cmdnleft <= 0)
+		return;
+	p = s;
+	q = cmdnextc;
+	while ((c = *p++) != '\0') {
+		if (c == CTLESC)
+			*q++ = *p++;
+		else if (c == CTLVAR) {
+			*q++ = '$';
+			if (--cmdnleft > 0)
+				*q++ = '{';
+			subtype = *p++;
+		} else if (c == '=' && subtype != 0) {
+			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
+			subtype = 0;
+		} else if (c == CTLENDVAR) {
+			*q++ = '}';
+		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
+			cmdnleft++;             /* ignore it */
+		else
+			*q++ = c;
+		if (--cmdnleft <= 0) {
+			*q++ = '.';
+			*q++ = '.';
+			*q++ = '.';
+			break;
+		}
+	}
+	cmdnextc = q;
 }
 
 
 static void
-cmdtxt(n)
-	union node *n;
-	{
+cmdtxt(const union node *n)
+{
 	union node *np;
 	struct nodelist *lp;
 	const char *p;
@@ -6624,53 +7826,23 @@
 }
 
 
+static char *
+commandtext(const union node *n)
+{
+	char *name;
 
-static void
-cmdputs(s)
-	const char *s;
-	{
-	const char *p;
-	char *q;
-	char c;
-	int subtype = 0;
-
-	if (cmdnleft <= 0)
-		return;
-	p = s;
-	q = cmdnextc;
-	while ((c = *p++) != '\0') {
-		if (c == CTLESC)
-			*q++ = *p++;
-		else if (c == CTLVAR) {
-			*q++ = '$';
-			if (--cmdnleft > 0)
-				*q++ = '{';
-			subtype = *p++;
-		} else if (c == '=' && subtype != 0) {
-			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
-			subtype = 0;
-		} else if (c == CTLENDVAR) {
-			*q++ = '}';
-		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
-			cmdnleft++;		/* ignore it */
-		else
-			*q++ = c;
-		if (--cmdnleft <= 0) {
-			*q++ = '.';
-			*q++ = '.';
-			*q++ = '.';
-			break;
-		}
-	}
-	cmdnextc = q;
+	cmdnextc = name = ckmalloc(MAXCMDTEXT);
+	cmdnleft = MAXCMDTEXT - 4;
+	cmdtxt(n);
+	*cmdnextc = '\0';
+	return name;
 }
 
+
 static void waitonint(int sig) {
 	intreceived = 1;
 	return;
 }
-/*	$NetBSD: mail.c,v 1.14 2000/07/03 03:26:19 matt Exp $	*/
-
 /*
  * Routines to check for mail.  (Perhaps make part of main.c?)
  */
@@ -6679,8 +7851,8 @@
 #define MAXMBOXES 10
 
 
-static int nmboxes;			/* number of mailboxes */
-static time_t mailtime[MAXMBOXES];	/* times of mailboxes */
+static int nmboxes;                     /* number of mailboxes */
+static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
 
 
 
@@ -6691,8 +7863,7 @@
  */
 
 static void
-chkmail(silent)
-	int silent;
+chkmail(int silent)
 {
 	int i;
 	const char *mpath;
@@ -6718,18 +7889,7 @@
 		if (q[-1] != '/')
 			abort();
 #endif
-		q[-1] = '\0';			/* delete trailing '/' */
-#ifdef notdef /* this is what the System V shell claims to do (it lies) */
-		if (stat(p, &statb) < 0)
-			statb.st_mtime = 0;
-		if (statb.st_mtime > mailtime[i] && ! silent) {
-			outfmt(
-				&errout, snlfmt,
-				pathopt? pathopt : "you have mail"
-			);
-		}
-		mailtime[i] = statb.st_mtime;
-#else /* this is what it should do */
+		q[-1] = '\0';                   /* delete trailing '/' */
 		if (stat(p, &statb) < 0)
 			statb.st_size = 0;
 		if (statb.st_size > mailtime[i] && ! silent) {
@@ -6739,28 +7899,27 @@
 			);
 		}
 		mailtime[i] = statb.st_size;
-#endif
 	}
 	nmboxes = i;
 	popstackmark(&smark);
 }
-/*	$NetBSD: main.c,v 1.40 2001/02/04 19:52:06 christos Exp $	*/
-
 
 #define PROFILE 0
 
-static int rootpid;
-static int rootshell;
 #if PROFILE
-short profile_buf[16384];
+static short profile_buf[16384];
 extern int etext();
 #endif
 
-static void read_profile __P((const char *));
-static char *find_dot_file __P((char *));
-int shell_main __P((int, char **));
+static void read_profile (const char *);
+static char *find_dot_file (char *);
+static void cmdloop (int);
+static void options (int);
+static void minus_o (char *, int);
+static void setoption (int, int);
+static void procargs (int, char **);
 
-extern int oexitstatus;
+
 /*
  * Main routine.  We initialize things, parse the arguments, execute
  * profiles if we're a login shell, and then call cmdloop to execute
@@ -6781,7 +7940,6 @@
 
 	DOTCMD = find_builtin(".");
 	BLTINCMD = find_builtin("builtin");
-	COMMANDCMD = find_builtin("command");
 	EXECCMD = find_builtin("exec");
 	EVALCMD = find_builtin("eval");
 
@@ -6824,18 +7982,14 @@
 			    exitshell(exitstatus);
 		}
 		reset();
-		if (exception == EXINT
-#if ATTY
-		 && (! attyset() || equal(termval(), "emacs"))
-#endif
-		 ) {
+		if (exception == EXINT) {
 			out2c('\n');
 #ifdef FLUSHERR
 			flushout(out2);
 #endif
 		}
 		popstackmark(&smark);
-		FORCEINTON;				/* enable interrupts */
+		FORCEINTON;                             /* enable interrupts */
 		if (state == 1)
 			goto state1;
 		else if (state == 2)
@@ -6878,7 +8032,7 @@
 	state = 4;
 	if (sflag == 0 || minusc) {
 		static int sigs[] =  {
-		    SIGINT, SIGQUIT, SIGHUP, 
+		    SIGINT, SIGQUIT, SIGHUP,
 #ifdef SIGTSTP
 		    SIGTSTP,
 #endif
@@ -6895,7 +8049,7 @@
 		evalstring(minusc, 0);
 
 	if (sflag || minusc == NULL) {
-state4:	/* XXX ??? - why isn't this before the "if" statement */
+state4: /* XXX ??? - why isn't this before the "if" statement */
 		cmdloop(1);
 	}
 #if PROFILE
@@ -6912,8 +8066,7 @@
  */
 
 static void
-cmdloop(top)
-	int top;
+cmdloop(int top)
 {
 	union node *n;
 	struct stackmark smark;
@@ -7002,8 +8155,7 @@
  */
 
 static void
-readcmdfile(name)
-	char *name;
+readcmdfile(const char *name)
 {
 	int fd;
 
@@ -7064,7 +8216,7 @@
 	for (sp = cmdenviron; sp ; sp = sp->next)
 		setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
 
-	if (argc >= 2) {		/* That's what SVR2 does */
+	if (argc >= 2) {                /* That's what SVR2 does */
 		char *fullname;
 		struct stackmark smark;
 
@@ -7094,38 +8246,8 @@
 	exitshell(exitstatus);
 	/* NOTREACHED */
 }
-/*	$NetBSD: memalloc.c,v 1.23 2000/11/01 19:56:01 christos Exp $	*/
-
-/*
- * Parse trees for commands are allocated in lifo order, so we use a stack
- * to make this more efficient, and also to avoid all sorts of exception
- * handling code to handle interrupts in the middle of a parse.
- *
- * The size 504 was chosen because the Ultrix malloc handles that size
- * well.
- */
-
-#define MINSIZE 504		/* minimum size of a block */
-
-
-struct stack_block {
-	struct stack_block *prev;
-	char space[MINSIZE];
-};
-
-struct stack_block stackbase;
-struct stack_block *stackp = &stackbase;
-struct stackmark *markp;
-static char *stacknxt = stackbase.space;
-static int stacknleft = MINSIZE;
-static int sstrnleft;
-static int herefd = -1;
-
-
-
-pointer
-stalloc(nbytes)
-	int nbytes;
+static pointer
+stalloc(int nbytes)
 {
 	char *p;
 
@@ -7153,11 +8275,10 @@
 
 
 static void
-stunalloc(p)
-	pointer p;
-	{
+stunalloc(pointer p)
+{
 #ifdef DEBUG
-	if (p == NULL) {		/*DEBUG */
+	if (p == NULL) {                /*DEBUG */
 		write(2, "stunalloc\n", 10);
 		abort();
 	}
@@ -7170,11 +8291,9 @@
 }
 
 
-
 static void
-setstackmark(mark)
-	struct stackmark *mark;
-	{
+setstackmark(struct stackmark *mark)
+{
 	mark->stackp = stackp;
 	mark->stacknxt = stacknxt;
 	mark->stacknleft = stacknleft;
@@ -7184,9 +8303,8 @@
 
 
 static void
-popstackmark(mark)
-	struct stackmark *mark;
-	{
+popstackmark(struct stackmark *mark)
+{
 	struct stack_block *sp;
 
 	INTOFF;
@@ -7213,7 +8331,7 @@
  */
 
 static void
-growstackblock() {
+growstackblock(void) {
 	char *p;
 	int newlen = ALIGN(stacknleft * 2 + 100);
 	char *oldspace = stacknxt;
@@ -7233,7 +8351,7 @@
 		stacknleft = newlen;
 		{
 		  /* Stack marks pointing to the start of the old block
-		   * must be relocated to point to the new block 
+		   * must be relocated to point to the new block
 		   */
 		  struct stackmark *xmark;
 		  xmark = markp;
@@ -7248,16 +8366,15 @@
 	} else {
 		p = stalloc(newlen);
 		memcpy(p, oldspace, oldlen);
-		stacknxt = p;			/* free the space */
-		stacknleft += newlen;		/* we just allocated */
+		stacknxt = p;                   /* free the space */
+		stacknleft += newlen;           /* we just allocated */
 	}
 }
 
 
 
-static void
-grabstackblock(len)
-	int len;
+static inline void
+grabstackblock(int len)
 {
 	len = ALIGN(len);
 	stacknxt += len;
@@ -7286,7 +8403,7 @@
 
 
 static char *
-growstackstr() {
+growstackstr(void) {
 	int len = stackblocksize();
 	if (herefd >= 0 && len >= 1024) {
 		xwrite(herefd, stackblock(), len);
@@ -7316,16 +8433,12 @@
 
 
 static void
-ungrabstackstr(s, p)
-	char *s;
-	char *p;
-	{
+ungrabstackstr(char *s, char *p)
+{
 	stacknleft += stacknxt - s;
 	stacknxt = s;
 	sstrnleft = stacknleft - (p - s);
 }
-/*	$NetBSD: miscbltin.c,v 1.30 2001/02/04 19:52:06 christos Exp $	*/
-
 /*
  * Miscelaneous builtins.
  */
@@ -7334,7 +8447,7 @@
 #undef rflag
 
 #ifdef __GLIBC__
-mode_t getmode(const void *, mode_t);
+static mode_t getmode(const void *, mode_t);
 static void *setmode(const char *);
 
 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
@@ -7531,46 +8644,46 @@
 
 struct limits {
 	const char *name;
-	int	cmd;
-	int	factor;	/* multiply by to get rlim_{cur,max} values */
-	char	option;
+	int     cmd;
+	int     factor; /* multiply by to get rlim_{cur,max} values */
+	char    option;
 };
 
 static const struct limits limits[] = {
 #ifdef RLIMIT_CPU
-	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
+	{ "time(seconds)",              RLIMIT_CPU,        1, 't' },
 #endif
 #ifdef RLIMIT_FSIZE
-	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
+	{ "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
 #endif
 #ifdef RLIMIT_DATA
-	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
+	{ "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
 #endif
 #ifdef RLIMIT_STACK
-	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
+	{ "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
 #endif
 #ifdef  RLIMIT_CORE
-	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
+	{ "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
 #endif
 #ifdef RLIMIT_RSS
-	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
+	{ "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
 #endif
 #ifdef RLIMIT_MEMLOCK
-	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
+	{ "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
 #endif
 #ifdef RLIMIT_NPROC
-	{ "process(processes)",		RLIMIT_NPROC,      1, 'p' },
+	{ "process(processes)",         RLIMIT_NPROC,      1, 'p' },
 #endif
 #ifdef RLIMIT_NOFILE
-	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
+	{ "nofiles(descriptors)",       RLIMIT_NOFILE,     1, 'n' },
 #endif
 #ifdef RLIMIT_VMEM
-	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
+	{ "vmemory(kbytes)",            RLIMIT_VMEM,    1024, 'v' },
 #endif
 #ifdef RLIMIT_SWAP
-	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
+	{ "swap(kbytes)",               RLIMIT_SWAP,    1024, 'w' },
 #endif
-	{ (char *) 0,			0,		   0,  '\0' }
+	{ (char *) 0,                   0,                 0,  '\0' }
 };
 
 static int
@@ -7578,14 +8691,14 @@
 	int argc;
 	char **argv;
 {
-	int	c;
+	int     c;
 	rlim_t val = 0;
 	enum { SOFT = 0x1, HARD = 0x2 }
 			how = SOFT | HARD;
-	const struct limits	*l;
-	int		set, all = 0;
-	int		optc, what;
-	struct rlimit	limit;
+	const struct limits     *l;
+	int             set, all = 0;
+	int             optc, what;
+	struct rlimit   limit;
 
 	what = 'f';
 	while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
@@ -7644,11 +8757,7 @@
 			else
 			{
 				val /= l->factor;
-#ifdef BSD4_4
 				out1fmt("%lld\n", (long long) val);
-#else
-				out1fmt("%ld\n", (long) val);
-#endif
 			}
 		}
 		return 0;
@@ -7661,7 +8770,7 @@
 		if (how & SOFT)
 			limit.rlim_cur = val;
 		if (setrlimit(l->cmd, &limit) < 0)
-			error("error setting limit (%s)", strerror(errno));
+			error("error setting limit (%m)");
 	} else {
 		if (how & SOFT)
 			val = limit.rlim_cur;
@@ -7673,63 +8782,11 @@
 		else
 		{
 			val /= l->factor;
-#ifdef BSD4_4
 			out1fmt("%lld\n", (long long) val);
-#else
-			out1fmt("%ld\n", (long) val);
-#endif
 		}
 	}
 	return 0;
 }
-/*	$NetBSD: mystring.c,v 1.14 1999/07/09 03:05:50 christos Exp $	*/
-
-/*
- * String functions.
- *
- *	equal(s1, s2)		Return true if strings are equal.
- *	scopy(from, to)		Copy a string.
- *	scopyn(from, to, n)	Like scopy, but checks for overflow.
- *	number(s)		Convert a string of digits to an integer.
- *	is_number(s)		Return true if s is a string of digits.
- */
-
-static char nullstr[1];		/* zero length string */
-static const char spcstr[] = " ";
-static const char snlfmt[] = "%s\n";
-
-/*
- * equal - #defined in mystring.h
- */
-
-/*
- * scopy - #defined in mystring.h
- */
-
-
-#if 0
-/*
- * scopyn - copy a string from "from" to "to", truncating the string
- *		if necessary.  "To" is always nul terminated, even if
- *		truncation is performed.  "Size" is the size of "to".
- */
-
-static void
-scopyn(from, to, size)
-	char const *from;
-	char *to;
-	int size;
-	{
-
-	while (--size > 0) {
-		if ((*to++ = *from++) == '\0')
-			return;
-	}
-	*to = '\0';
-}
-#endif
-
-
 /*
  * prefix -- see if pfx is a prefix of string.
  */
@@ -7746,6 +8803,27 @@
 	return 1;
 }
 
+/*
+ * Return true if s is a string of digits, and save munber in intptr
+ * nagative is bad
+ */
+
+static int
+is_number(const char *p, int *intptr)
+{
+	int ret = 0;
+
+	do {
+		if (! is_digit(*p))
+			return 0;
+		ret *= 10;
+		ret += digit_val(*p);
+		p++;
+	} while (*p != '\0');
+
+	*intptr = ret;
+	return 1;
+}
 
 /*
  * Convert a string of digits to an integer, printing an error message on
@@ -7753,33 +8831,14 @@
  */
 
 static int
-number(s)
-	const char *s;
-	{
-
-	if (! is_number(s))
+number(const char *s)
+{
+	int i;
+	if (! is_number(s, &i))
 		error("Illegal number: %s", s);
-	return atoi(s);
+	return i;
 }
 
-
-
-/*
- * Check for a valid number.  This should be elsewhere.
- */
-
-static int
-is_number(p)
-	const char *p;
-	{
-	do {
-		if (! is_digit(*p))
-			return 0;
-	} while (*++p != '\0');
-	return 1;
-}
-
-
 /*
  * Produce a possibly single quoted string suitable as input to the shell.
  * The return string is allocated on the stack.
@@ -7863,38 +8922,20 @@
 	return memcpy(stalloc(len), p, len);
 }
 
-/*
- * Wrapper around strcmp for qsort/bsearch/...
- */
-static int
-pstrcmp(const void *a, const void *b)
-{
-	return strcmp(*(const char *const *) a, *(const char *const *) b);
-}
 
 /*
- * Find a string is in a sorted array.
- */
-static const char *const *
-findstring(const char *s, const char *const *array, size_t nmemb)
-{
-	return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp);
-}
-/*
  * This file was generated by the mknodes program.
  */
 
-/*	$NetBSD: nodes.c.pat,v 1.8 1997/04/11 23:03:09 christos Exp $	*/
-
 /*
  * Routine for dealing with parsed shell commands.
  */
 
 
-static int     funcblocksize;		/* size of structures in function */
-static int     funcstringsize;		/* size of strings in node */
-pointer funcblock;		/* block to allocate function from */
-static char   *funcstring;		/* block to allocate strings from */
+static int     funcblocksize;           /* size of structures in function */
+static int     funcstringsize;          /* size of strings in node */
+static pointer funcblock;              /* block to allocate function from */
+static char   *funcstring;              /* block to allocate strings from */
 
 static const short nodesize[26] = {
       ALIGN(sizeof (struct nbinary)),
@@ -7926,11 +8967,11 @@
 };
 
 
-static void calcsize __P((union node *));
-static void sizenodelist __P((struct nodelist *));
-static union node *copynode __P((union node *));
-static struct nodelist *copynodelist __P((struct nodelist *));
-static char *nodesavestr __P((char *));
+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 *);
 
 
 
@@ -7938,9 +8979,8 @@
  * Make a copy of a parse tree.
  */
 
-union node *
-copyfunc(n)
-	union node *n;
+static union node *
+copyfunc(union node *n)
 {
 	if (n == NULL)
 		return NULL;
@@ -8181,54 +9221,8 @@
 #endif
 }
 
-
-
-/*
- * Free a parse tree.
- */
-
-static void
-freefunc(n)
-	union node *n;
-{
-	if (n)
-		ckfree(n);
-}
-/*	$NetBSD: options.c,v 1.31 2001/02/26 13:06:43 wiz Exp $	*/
-
-
-struct optent optlist[NOPTS] = {
-	{ "errexit",	'e',	0 },
-	{ "noglob",	'f',	0 },
-	{ "ignoreeof",	'I',	0 },
-	{ "interactive",'i',	0 },
-	{ "monitor",	'm',	0 },
-	{ "noexec",	'n',	0 },
-	{ "stdin",	's',	0 },
-	{ "xtrace",	'x',	0 },
-	{ "verbose",	'v',	0 },
-	{ "vi",		'V',	0 },
-	{ "emacs",	'E',	0 },
-	{ "noclobber",	'C',	0 },
-	{ "allexport",	'a',	0 },
-	{ "notify",	'b',	0 },
-	{ "nounset",	'u',	0 },
-	{ "quietprofile", 'q',	0 },
-};
-static char *arg0;			/* value of $0 */
-struct shparam shellparam;	/* current positional parameters */
-static char **argptr;			/* argument list for builtin commands */
-static char *optionarg;		/* set by nextopt (like getopt) */
-static char *optptr;			/* used by nextopt */
-
-static char *minusc;			/* argument to -c option */
-
-
-static void options __P((int));
-static void minus_o __P((char *, int));
-static void setoption __P((int, int));
 #ifdef ASH_GETOPTS
-static int getopts __P((char *, char *, char **, int *, int *));
+static int getopts (char *, char *, char **, int *, int *);
 #endif
 
 
@@ -8247,7 +9241,7 @@
 	if (argc > 0)
 		argptr++;
 	for (i = 0; i < NOPTS; i++)
-		optlist[i].val = 2;
+		optent_val(i) = 2;
 	options(1);
 	if (*argptr == NULL && minusc == NULL)
 		sflag = 1;
@@ -8256,8 +9250,8 @@
 	if (mflag == 2)
 		mflag = iflag;
 	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].val == 2)
-			optlist[i].val = 0;
+		if (optent_val(i) == 2)
+			optent_val(i) = 0;
 	arg0 = argv[0];
 	if (sflag == 0 && minusc == NULL) {
 		commandname = argv[0];
@@ -8267,7 +9261,7 @@
 	}
 	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
 	if (argptr && minusc && *argptr)
-	        arg0 = *argptr++;
+		arg0 = *argptr++;
 
 	shellparam.p = argptr;
 	shellparam.optind = 1;
@@ -8281,12 +9275,6 @@
 }
 
 
-static void
-optschanged()
-{
-	setinteractive(iflag);
-	setjobctl(mflag);
-}
 
 /*
  * Process shell options.  The global variable argptr contains a pointer
@@ -8307,16 +9295,16 @@
 		argptr++;
 		if ((c = *p++) == '-') {
 			val = 1;
-                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
-                                if (!cmdline) {
-                                        /* "-" means turn off -x and -v */
-                                        if (p[0] == '\0')
-                                                xflag = vflag = 0;
-                                        /* "--" means reset params */
-                                        else if (*argptr == NULL)
+			if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
+				if (!cmdline) {
+					/* "-" means turn off -x and -v */
+					if (p[0] == '\0')
+						xflag = vflag = 0;
+					/* "--" means reset params */
+					else if (*argptr == NULL)
 						setparam(argptr);
-                                }
-				break;	  /* "-" or  "--" terminates options */
+				}
+				break;    /* "-" or  "--" terminates options */
 			}
 		} else if (c == '+') {
 			val = 0;
@@ -8327,7 +9315,7 @@
 		while ((c = *p++) != '\0') {
 			if (c == 'c' && cmdline) {
 				char *q;
-#ifdef NOHACK	/* removing this code allows sh -ce 'foo' for compat */
+#ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
 				if (*p == '\0')
 #endif
 					q = *argptr++;
@@ -8358,12 +9346,12 @@
 	if (name == NULL) {
 		out1str("Current option settings\n");
 		for (i = 0; i < NOPTS; i++)
-			out1fmt("%-16s%s\n", optlist[i].name,
-				optlist[i].val ? "on" : "off");
+			out1fmt("%-16s%s\n", optent_name(optlist[i]),
+				optent_val(i) ? "on" : "off");
 	} else {
 		for (i = 0; i < NOPTS; i++)
-			if (equal(name, optlist[i].name)) {
-				setoption(optlist[i].letter, val);
+			if (equal(name, optent_name(optlist[i]))) {
+				setoption(optent_letter(optlist[i]), val);
 				return;
 			}
 		error("Illegal option -o %s", name);
@@ -8372,15 +9360,13 @@
 
 
 static void
-setoption(flag, val)
-	char flag;
-	int val;
-	{
+setoption(int flag, int val)
+{
 	int i;
 
 	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].letter == flag) {
-			optlist[i].val = val;
+		if (optent_letter(optlist[i]) == flag) {
+			optent_val(i) = val;
 			if (val) {
 				/* #%$ hack for ksh semantics */
 				if (flag == 'V')
@@ -8396,26 +9382,13 @@
 
 
 
-#ifdef mkinit
-SHELLPROC {
-	int i;
-
-	for (i = 0; i < NOPTS; i++)
-		optlist[i].val = 0;
-	optschanged();
-
-}
-#endif
-
-
 /*
  * Set the shell parameters.
  */
 
 static void
-setparam(argv)
-	char **argv;
-	{
+setparam(char **argv)
+{
 	char **newparam;
 	char **ap;
 	int nparam;
@@ -8440,9 +9413,8 @@
  */
 
 static void
-freeparam(param)
-	volatile struct shparam *param;
-	{
+freeparam(volatile struct shparam *param)
+{
 	char **ap;
 
 	if (param->malloc) {
@@ -8510,13 +9482,27 @@
 
 
 static void
-getoptsreset(value)
-	const char *value;
+getoptsreset(const char *value)
 {
 	shellparam.optind = number(value);
 	shellparam.optoff = -1;
 }
 
+#ifdef BB_LOCALE_SUPPORT
+static void change_lc_all(const char *value)
+{
+	if(value != 0 && *value != 0)
+		setlocale(LC_ALL, value);
+}
+
+static void change_lc_ctype(const char *value)
+{
+	if(value != 0 && *value != 0)
+		setlocale(LC_CTYPE, value);
+}
+
+#endif
+
 #ifdef ASH_GETOPTS
 /*
  * The getopts builtin.  Shellparam.optnext points to the next argument
@@ -8612,7 +9598,7 @@
 			goto out;
 		}
 		optnext++;
-		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+		if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
 			goto atend;
 	}
 
@@ -8679,7 +9665,7 @@
 	}
 	return done;
 }
-#endif	
+#endif
 
 /*
  * XXX - should get rid of.  have all builtins use getopt(3).  the
@@ -8705,7 +9691,7 @@
 		if (p == NULL || *p != '-' || *++p == '\0')
 			return '\0';
 		argptr++;
-		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+		if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
 			return '\0';
 	}
 	c = *p++;
@@ -8726,66 +9712,21 @@
 }
 
 
-/*	$NetBSD: output.c,v 1.23 2001/01/07 23:39:07 lukem Exp $	*/
-
 /*
  * Shell output routines.  We use our own output routines because:
- *	When a builtin command is interrupted we have to discard
- *		any pending output.
- *	When a builtin command appears in back quotes, we want to
- *		save the output of the command in a region obtained
- *		via malloc, rather than doing a fork and reading the
- *		output of the command via a pipe.
- *	Our output routines may be smaller than the stdio routines.
+ *      When a builtin command is interrupted we have to discard
+ *              any pending output.
+ *      When a builtin command appears in back quotes, we want to
+ *              save the output of the command in a region obtained
+ *              via malloc, rather than doing a fork and reading the
+ *              output of the command via a pipe.
+ *      Our output routines may be smaller than the stdio routines.
  */
 
 
-#define OUTBUFSIZ BUFSIZ
-#define MEM_OUT -3		/* output to dynamically allocated memory */
-
-
-#ifdef USE_GLIBC_STDIO
-struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
-struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
-struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
-#else
-struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
-struct output errout = {NULL, 0, NULL, 0, 2, 0};
-struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
-#endif
-struct output *out1 = &output;
-struct output *out2 = &errout;
-
 
 #ifndef USE_GLIBC_STDIO
-static void __outstr __P((const char *, size_t, struct output*));
-#endif
-
-
-#ifdef mkinit
-
-INCLUDE "output.h"
-INCLUDE "memalloc.h"
-
-INIT {
-#ifdef USE_GLIBC_STDIO
-	initstreams();
-#endif
-}
-
-RESET {
-	out1 = &output;
-	out2 = &errout;
-#ifdef USE_GLIBC_STDIO
-	if (memout.stream != NULL)
-		__closememout();
-#endif
-	if (memout.buf != NULL) {
-		ckfree(memout.buf);
-		memout.buf = NULL;
-	}
-}
-
+static void __outstr (const char *, size_t, struct output*);
 #endif
 
 
@@ -8835,10 +9776,8 @@
 
 
 static void
-outstr(p, file)
-	const char *p;
-	struct output *file;
-	{
+outstr(const char *p, struct output *file)
+{
 #ifdef USE_GLIBC_STDIO
 	INTOFF;
 	fputs(p, file->stream);
@@ -8990,232 +9929,26 @@
 }
 
 #ifndef USE_GLIBC_STDIO
-/*
- * Formatted output.  This routine handles a subset of the printf formats:
- * - Formats supported: d, u, o, p, X, s, and c.
- * - The x format is also accepted but is treated like X.
- * - The l, ll and q modifiers are accepted.
- * - The - and # flags are accepted; # only works with the o format.
- * - Width and precision may be specified with any format except c.
- * - An * may be given for the width or precision.
- * - The obsolete practice of preceding the width with a zero to get
- *   zero padding is not supported; use the precision field.
- * - A % may be printed by writing %% in the format string.
- */
-
-#define TEMPSIZE 24
-
-#ifdef BSD4_4
-#define HAVE_VASPRINTF 1
-#endif
-
-#if	!HAVE_VASPRINTF
-static const char digit[] = "0123456789ABCDEF";
-#endif
-
 
 static void
-doformat(dest, f, ap)
-	struct output *dest;
-	const char *f;		/* format string */
-	va_list ap;
+doformat(struct output *dest, const char *f, va_list ap)
 {
-#if	HAVE_VASPRINTF
-	char *s, *t;
-	int len;
+	char *pm;
+	int size = BUFSIZ;
 
-	INTOFF;
-	len = vasprintf(&t, f, ap);
-	if (len < 0) {
-		return;
-	}
-	s = stalloc(++len);
-	memcpy(s, t, len);
-	free(t);
-	INTON;
-	outstr(s, dest);
-	stunalloc(s);
-#else	/* !HAVE_VASPRINTF */
-	char c;
-	char temp[TEMPSIZE];
-	int flushleft;
-	int sharp;
-	int width;
-	int prec;
-	int islong;
-	int isquad;
-	char *p;
-	int sign;
-#ifdef BSD4_4
-	quad_t l;
-	u_quad_t num;
-#else
-	long l;
-	u_long num;
-#endif
-	unsigned base;
-	int len;
-	int size;
-	int pad;
+	while(size) {
+		int nchars;
 
-	while ((c = *f++) != '\0') {
-		if (c != '%') {
-			outc(c, dest);
-			continue;
-		}
-		flushleft = 0;
-		sharp = 0;
-		width = 0;
-		prec = -1;
-		islong = 0;
-		isquad = 0;
-		for (;;) {
-			if (*f == '-')
-				flushleft++;
-			else if (*f == '#')
-				sharp++;
-			else
-				break;
-			f++;
-		}
-		if (*f == '*') {
-			width = va_arg(ap, int);
-			f++;
-		} else {
-			while (is_digit(*f)) {
-				width = 10 * width + digit_val(*f++);
+		pm = xmalloc(size);
+		nchars = vsnprintf(pm, size, f, ap);
+		if(nchars > -1) {
+			outstr(pm, dest);
+			size = 0;
 			}
-		}
-		if (*f == '.') {
-			if (*++f == '*') {
-				prec = va_arg(ap, int);
-				f++;
-			} else {
-				prec = 0;
-				while (is_digit(*f)) {
-					prec = 10 * prec + digit_val(*f++);
-				}
-			}
-		}
-		if (*f == 'l') {
-			f++;
-			if (*f == 'l') {
-				isquad++;
-				f++;
-			} else
-				islong++;
-		} else if (*f == 'q') {
-			isquad++;
-			f++;
-		}
-		switch (*f) {
-		case 'd':
-#ifdef BSD4_4
-			if (isquad)
-				l = va_arg(ap, quad_t);
-			else
-#endif
-			if (islong)
-				l = va_arg(ap, long);
-			else
-				l = va_arg(ap, int);
-			sign = 0;
-			num = l;
-			if (l < 0) {
-				num = -l;
-				sign = 1;
-			}
-			base = 10;
-			goto number;
-		case 'u':
-			base = 10;
-			goto uns_number;
-		case 'o':
-			base = 8;
-			goto uns_number;
-		case 'p':
-			outc('0', dest);
-			outc('x', dest);
-			/*FALLTHROUGH*/
-		case 'x':
-			/* we don't implement 'x'; treat like 'X' */
-		case 'X':
-			base = 16;
-uns_number:	  /* an unsigned number */
-			sign = 0;
-#ifdef BSD4_4
-			if (isquad)
-				num = va_arg(ap, u_quad_t);
-			else
-#endif
-			if (islong)
-				num = va_arg(ap, unsigned long);
-			else
-				num = va_arg(ap, unsigned int);
-number:		  /* process a number */
-			p = temp + TEMPSIZE - 1;
-			*p = '\0';
-			while (num) {
-				*--p = digit[num % base];
-				num /= base;
-			}
-			len = (temp + TEMPSIZE - 1) - p;
-			if (prec < 0)
-				prec = 1;
-			if (sharp && *f == 'o' && prec <= len)
-				prec = len + 1;
-			pad = 0;
-			if (width) {
-				size = len;
-				if (size < prec)
-					size = prec;
-				size += sign;
-				pad = width - size;
-				if (flushleft == 0) {
-					while (--pad >= 0)
-						outc(' ', dest);
-				}
-			}
-			if (sign)
-				outc('-', dest);
-			prec -= len;
-			while (--prec >= 0)
-				outc('0', dest);
-			while (*p)
-				outc(*p++, dest);
-			while (--pad >= 0)
-				outc(' ', dest);
-			break;
-		case 's':
-			p = va_arg(ap, char *);
-			pad = 0;
-			if (width) {
-				len = strlen(p);
-				if (prec >= 0 && len > prec)
-					len = prec;
-				pad = width - len;
-				if (flushleft == 0) {
-					while (--pad >= 0)
-						outc(' ', dest);
-				}
-			}
-			prec++;
-			while (--prec != 0 && *p)
-				outc(*p++, dest);
-			while (--pad >= 0)
-				outc(' ', dest);
-			break;
-		case 'c':
-			c = va_arg(ap, int);
-			outc(c, dest);
-			break;
-		default:
-			outc(*f, dest);
-			break;
-		}
-		f++;
+		else
+			size *= 2;
+		free(pm);
 	}
-#endif	/* !HAVE_VASPRINTF */
 }
 #endif
 
@@ -9226,11 +9959,8 @@
  */
 
 static int
-xwrite(fd, buf, nbytes)
-	int fd;
-	const char *buf;
-	int nbytes;
-	{
+xwrite(int fd, const char *buf, int nbytes)
+{
 	int ntry;
 	int i;
 	int n;
@@ -9254,26 +9984,6 @@
 }
 
 
-#ifdef notdef
-/*
- * Version of ioctl that retries after a signal is caught.
- * XXX unused function
- */
-
-static int
-xioctl(fd, request, arg)
-	int fd;
-	unsigned long request;
-	char * arg;
-{
-	int i;
-
-	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
-	return i;
-}
-#endif
-
-
 #ifdef USE_GLIBC_STDIO
 static void initstreams() {
 	output.stream = stdout;
@@ -9297,8 +10007,6 @@
 	return error;
 }
 #endif
-/*	$NetBSD: parser.c,v 1.46 2001/02/04 19:52:06 christos Exp $	*/
-
 /*
  * Shell command parser.
  */
@@ -9308,47 +10016,42 @@
 
 
 struct heredoc {
-	struct heredoc *next;	/* next here document in list */
-	union node *here;		/* redirection node */
-	char *eofmark;		/* string indicating end of input */
-	int striptabs;		/* if set, strip leading tabs */
+	struct heredoc *next;   /* next here document in list */
+	union node *here;               /* redirection node */
+	char *eofmark;          /* string indicating end of input */
+	int striptabs;          /* if set, strip leading tabs */
 };
 
+static struct heredoc *heredoclist;     /* list of here documents to read */
+static int parsebackquote;              /* nonzero if we are inside backquotes */
+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 */
 
+static char *wordtext;                  /* text of last word returned by readtoken */
 
-struct heredoc *heredoclist;	/* list of here documents to read */
-static int parsebackquote;		/* nonzero if we are inside backquotes */
-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 */
-static int tokpushback;		/* last token pushed back */
-static char *wordtext;			/* text of last word returned by readtoken */
-static int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
-/* 1 == check for aliases, 2 == also check for assignments */
-static int checkalias;
-struct nodelist *backquotelist;
-union node *redirnode;
+static struct nodelist *backquotelist;
+static union node *redirnode;
 struct heredoc *heredoc;
-static int quoteflag;			/* set if (part of) last token was quoted */
-static int startlinno;			/* line # where last token started */
+static int quoteflag;                   /* set if (part of) last token was quoted */
+static int startlinno;                  /* line # where last token started */
 
 
-static union node *list __P((int));
-static union node *andor __P((void));
-static union node *pipeline __P((void));
-static union node *command __P((void));
-static union node *simplecmd __P((void));
-static union node *makename __P((void));
-static void parsefname __P((void));
-static void parseheredoc __P((void));
-static int peektoken __P((void));
-static int readtoken __P((void));
-static int xxreadtoken __P((void));
-static int readtoken1 __P((int, char const *, char *, int));
-static int noexpand __P((char *));
-static void synexpect __P((int)) __attribute__((noreturn));
-static void synerror __P((const char *)) __attribute__((noreturn));
-static void setprompt __P((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 (void);
+static void parsefname (void);
+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 noexpand (char *);
+static void synexpect (int) __attribute__((noreturn));
+static void synerror (const char *) __attribute__((noreturn));
+static void setprompt (int);
 
 
 /*
@@ -9356,7 +10059,7 @@
  * valid parse tree indicating a blank line.)
  */
 
-union node *
+static union node *
 parsecmd(int interact)
 {
 	int t;
@@ -9436,7 +10139,7 @@
 			if (heredoclist)
 				parseheredoc();
 			else
-				pungetc();		/* push back EOF on input */
+				pungetc();              /* push back EOF on input */
 			return n1;
 		default:
 			if (nlflag)
@@ -9746,7 +10449,9 @@
 	redir = NULL;
 	rpp = &redir;
 
+#ifdef ASH_ALIAS
 	checkalias = 2;
+#endif
 	for (;;) {
 		switch (readtoken()) {
 		case TWORD:
@@ -9766,7 +10471,7 @@
 		case TREDIR:
 			*rpp = n = redirnode;
 			rpp = &n->nfile.next;
-			parsefname();	/* read name of redirection file */
+			parsefname();   /* read name of redirection file */
 			break;
 		case TLP:
 			if (
@@ -9776,10 +10481,6 @@
 				/* We have a function */
 				if (readtoken() != TRP)
 					synexpect(TRP);
-#ifdef notdef
-				if (! goodname(n->narg.text))
-					synerror("Bad function name");
-#endif
 				n->type = NDEFUN;
 				checkkwd = 2;
 				n->narg.next = command();
@@ -9805,7 +10506,7 @@
 }
 
 static union node *
-makename() {
+makename(void) {
 	union node *n;
 
 	n = (union node *)stalloc(sizeof (struct narg));
@@ -9817,7 +10518,7 @@
 }
 
 static void fixredir(union node *n, const char *text, int err)
-	{
+{
 	TRACE(("Fix redir %s %d\n", text, err));
 	if (!err)
 		n->ndup.vname = NULL;
@@ -9837,7 +10538,7 @@
 
 
 static void
-parsefname() {
+parsefname(void) {
 	union node *n = redirnode;
 
 	if (readtoken() != TWORD)
@@ -9912,16 +10613,25 @@
 static int
 readtoken() {
 	int t;
+#ifdef ASH_ALIAS
 	int savecheckkwd = checkkwd;
 	int savecheckalias = checkalias;
 	struct alias *ap;
+#endif
+
 #ifdef DEBUG
 	int alreadyseen = tokpushback;
 #endif
 
+#ifdef ASH_ALIAS
 top:
+#endif
+
 	t = xxreadtoken();
+
+#ifdef ASH_ALIAS
 	checkalias = savecheckalias;
+#endif
 
 	if (checkkwd) {
 		/*
@@ -9950,6 +10660,7 @@
 		}
 	}
 
+#ifdef ASH_ALIAS
 	if (t != TWORD) {
 		if (t != TREDIR) {
 			checkalias = 0;
@@ -9966,6 +10677,7 @@
 		}
 		checkalias = 0;
 	}
+#endif
 out:
 #ifdef DEBUG
 	if (!alreadyseen)
@@ -9980,12 +10692,12 @@
 /*
  * Read the next input token.
  * If the token is a word, we set backquotelist to the list of cmds in
- *	backquotes.  We set quoteflag to true if any part of the word was
- *	quoted.
+ *      backquotes.  We set quoteflag to true if any part of the word was
+ *      quoted.
  * If the token is TREDIR, then we set redirnode to a structure containing
- *	the redirection.
+ *      the redirection.
  * In all cases, the variable startlinno is set to the number of the line
- *	on which the token starts.
+ *      on which the token starts.
  *
  * [Change comment:  here documents and internal procedures]
  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
@@ -9995,7 +10707,7 @@
  *  have parseword (readtoken1?) handle both words and redirection.]
  */
 
-#define RETURN(token)	return lasttoken = token
+#define RETURN(token)   return lasttoken = token
 
 static int
 xxreadtoken() {
@@ -10010,7 +10722,7 @@
 		needprompt = 0;
 	}
 	startlinno = plinno;
-	for (;;) {	/* until token or start of word found */
+	for (;;) {      /* until token or start of word found */
 		c = pgetc_macro();
 		switch (c) {
 		case ' ': case '\t':
@@ -10079,12 +10791,12 @@
  * 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 PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
-#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
-#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
+#define CHECKEND()      {goto checkend; checkend_return:;}
+#define PARSEREDIR()    {goto parseredir; parseredir_return:;}
+#define PARSESUB()      {goto parsesub; parsesub_return:;}
+#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
+#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
+#define PARSEARITH()    {goto parsearith; parsearith_return:;}
 
 static int
 readtoken1(firstc, syntax, eofmark, striptabs)
@@ -10100,12 +10812,12 @@
 	struct nodelist *bqlist;
 	int quotef;
 	int dblquote;
-	int varnest;	/* levels of variables expansion */
-	int arinest;	/* levels of arithmetic expansion */
-	int parenlevel;	/* levels of parens in arithmetic */
-	int dqvarnest;	/* levels of variables expansion within double quotes */
+	int varnest;    /* levels of variables expansion */
+	int arinest;    /* levels of arithmetic expansion */
+	int parenlevel; /* levels of parens in arithmetic */
+	int dqvarnest;  /* levels of variables expansion within double quotes */
 	int oldstyle;
-	char const *prevsyntax;	/* syntax before arithmetic */
+	char const *prevsyntax; /* syntax before arithmetic */
 #if __GNUC__
 	/* Avoid longjmp clobbering */
 	(void) &out;
@@ -10132,24 +10844,14 @@
 	dqvarnest = 0;
 
 	STARTSTACKSTR(out);
-	loop: {	/* for each line, until end of word */
-#if ATTY
-		if (c == '\034' && doprompt
-		 && attyset() && ! equal(termval(), "emacs")) {
-			attyline();
-			if (syntax == BASESYNTAX)
-				return readtoken();
-			c = pgetc();
-			goto loop;
-		}
-#endif
-		CHECKEND();	/* set c to PEOF if at end of here document */
-		for (;;) {	/* until end of line or end of word */
-			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
+	loop: { /* for each line, until end of word */
+		CHECKEND();     /* set c to PEOF if at end of here document */
+		for (;;) {      /* until end of line or end of word */
+			CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
 			switch(syntax[c]) {
-			case CNL:	/* '\n' */
+			case CNL:       /* '\n' */
 				if (syntax == BASESYNTAX)
-					goto endword;	/* exit outer loop */
+					goto endword;   /* exit outer loop */
 				USTPUTC(c, out);
 				plinno++;
 				if (doprompt)
@@ -10157,7 +10859,7 @@
 				else
 					setprompt(0);
 				c = pgetc();
-				goto loop;		/* continue outer loop */
+				goto loop;              /* continue outer loop */
 			case CWORD:
 				USTPUTC(c, out);
 				break;
@@ -10167,7 +10869,7 @@
 					USTPUTC(CTLESC, out);
 				USTPUTC(c, out);
 				break;
-			case CBACK:	/* backslash */
+			case CBACK:     /* backslash */
 				c = pgetc2();
 				if (c == PEOF) {
 					USTPUTC('\\', out);
@@ -10216,10 +10918,10 @@
 					quotef++;
 				}
 				break;
-			case CVAR:	/* '$' */
-				PARSESUB();		/* parse substitution */
+			case CVAR:      /* '$' */
+				PARSESUB();             /* parse substitution */
 				break;
-			case CENDVAR:	/* '}' */
+			case CENDVAR:   /* '}' */
 				if (varnest > 0) {
 					varnest--;
 					if (dqvarnest > 0) {
@@ -10231,11 +10933,11 @@
 				}
 				break;
 #ifdef ASH_MATH_SUPPORT
-			case CLP:	/* '(' in arithmetic */
+			case CLP:       /* '(' in arithmetic */
 				parenlevel++;
 				USTPUTC(c, out);
 				break;
-			case CRP:	/* ')' in arithmetic */
+			case CRP:       /* ')' in arithmetic */
 				if (parenlevel > 0) {
 					USTPUTC(c, out);
 					--parenlevel;
@@ -10261,16 +10963,16 @@
 				}
 				break;
 #endif
-			case CBQUOTE:	/* '`' */
+			case CBQUOTE:   /* '`' */
 				PARSEBACKQOLD();
 				break;
-			case CEOF:
-				goto endword;		/* exit outer loop */
+			case CENDFILE:
+				goto endword;           /* exit outer loop */
 			case CIGN:
 				break;
 			default:
 				if (varnest == 0)
-					goto endword;	/* exit outer loop */
+					goto endword;   /* exit outer loop */
 				if (c != PEOA) {
 					USTPUTC(c, out);
 				}
@@ -10318,9 +11020,11 @@
 
 checkend: {
 	if (eofmark) {
+#ifdef ASH_ALIAS
 		if (c == PEOA) {
 			c = pgetc2();
 		}
+#endif
 		if (striptabs) {
 			while (c == '\t') {
 				c = pgetc2();
@@ -10370,7 +11074,7 @@
 			np->type = NTO;
 			pungetc();
 		}
-	} else {	/* c == '<' */
+	} else {        /* c == '<' */
 		np->nfile.fd = 0;
 		switch (c = pgetc()) {
 		case '<':
@@ -10429,7 +11133,7 @@
 	) {
 		USTPUTC('$', out);
 		pungetc();
-	} else if (c == '(') {	/* $(command) or $((arith)) */
+	} else if (c == '(') {  /* $(command) or $((arith)) */
 		if (pgetc() == '(') {
 			PARSEARITH();
 		} else {
@@ -10468,7 +11172,7 @@
 			c = pgetc();
 		}
 		else
-badsub:			synerror("Bad substitution");
+badsub:                 synerror("Bad substitution");
 
 		STPUTC('=', out);
 		flags = 0;
@@ -10553,17 +11257,17 @@
 	savehandler = handler;
 	handler = &jmploc;
 	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.  */
-                char *pout;
-                int pc;
-                int psavelen;
-                char *pstr;
+	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.  */
+		char *pout;
+		int pc;
+		int psavelen;
+		char *pstr;
 
 
-                STARTSTACKSTR(pout);
+		STARTSTACKSTR(pout);
 		for (;;) {
 			if (needprompt) {
 				setprompt(2);
@@ -10574,7 +11278,7 @@
 				goto done;
 
 			case '\\':
-                                if ((pc = pgetc()) == '\n') {
+				if ((pc = pgetc()) == '\n') {
 					plinno++;
 					if (doprompt)
 						setprompt(2);
@@ -10588,17 +11292,19 @@
 					 */
 					continue;
 				}
-                                if (pc != '\\' && pc != '`' && pc != '$'
-                                    && (!dblquote || pc != '"'))
-                                        STPUTC('\\', pout);
+				if (pc != '\\' && pc != '`' && pc != '$'
+				    && (!dblquote || pc != '"'))
+					STPUTC('\\', pout);
 				if (pc > PEOA) {
 					break;
 				}
 				/* fall through */
 
 			case PEOF:
+#ifdef ASH_ALIAS
 			case PEOA:
-			        startlinno = plinno;
+#endif
+				startlinno = plinno;
 				synerror("EOF in backquote substitution");
 
 			case '\n':
@@ -10610,15 +11316,15 @@
 				break;
 			}
 			STPUTC(pc, pout);
-                }
+		}
 done:
-                STPUTC('\0', pout);
-                psavelen = pout - stackblock();
-                if (psavelen > 0) {
+		STPUTC('\0', pout);
+		psavelen = pout - stackblock();
+		if (psavelen > 0) {
 			pstr = grabstackstr(pout);
 			setinputstring(pstr);
-                }
-        }
+		}
+	}
 	nlpp = &bqlist;
 	while (*nlpp)
 		nlpp = &(*nlpp)->next;
@@ -10641,12 +11347,12 @@
 	}
 
 	(*nlpp)->n = n;
-        if (oldstyle) {
+	if (oldstyle) {
 		/*
 		 * Start reading from old file again, ignoring any pushed back
 		 * tokens left from the backquote parsing
 		 */
-                popfile();
+		popfile();
 		tokpushback = 0;
 	}
 	while (stackblocksize() <= savelen)
@@ -10698,16 +11404,6 @@
 } /* end of readtoken */
 
 
-
-#ifdef mkinit
-INCLUDE "parser.h"
-RESET {
-	tokpushback = 0;
-	checkkwd = 0;
-	checkalias = 0;
-}
-#endif
-
 /*
  * Returns true if the text contains nothing to expand (no dollar signs
  * or backquotes).
@@ -10739,9 +11435,9 @@
  */
 
 static int
-goodname(char *name)
-	{
-	char *p;
+goodname(const char *name)
+{
+	const char *p;
 
 	p = name;
 	if (! is_name(*p))
@@ -10778,9 +11474,8 @@
 
 
 static void
-synerror(msg)
-	const char *msg;
-	{
+synerror(const char *msg)
+{
 	if (commandname)
 		outfmt(&errout, "%s: %d: ", commandname, startlinno);
 	outfmt(&errout, "Syntax error: %s\n", msg);
@@ -10788,12 +11483,6 @@
 	/* NOTREACHED */
 }
 
-static void
-setprompt(int which)
-{
-    whichprompt = which;
-    putprompt(getprompt(NULL));
-}
 
 /*
  * called by editline -- any expansions to the prompt
@@ -10801,7 +11490,7 @@
  */
 static const char *
 getprompt(void *unused)
-	{
+{
 	switch (whichprompt) {
 	case 0:
 		return "";
@@ -10814,56 +11503,26 @@
 	}
 }
 
-static int
-isassignment(const char *word) {
-	if (!is_name(*word)) {
-		return 0;
-	}
-	do {
-		word++;
-	} while (is_in_name(*word));
-	return *word == '=';
+static void
+setprompt(int which)
+{
+    whichprompt = which;
+    putprompt(getprompt(NULL));
 }
 
-static const char *const *
-findkwd(const char *s) {
-	return findstring(
-		s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
-	);
-}
-/*	$NetBSD: redir.c,v 1.22 2000/05/22 10:18:47 elric Exp $	*/
 
 /*
  * Code for dealing with input/output redirection.
  */
 
-#define EMPTY -2		/* marks an unused slot in redirtab */
+#define EMPTY -2                /* marks an unused slot in redirtab */
 #ifndef PIPE_BUF
-# define PIPESIZE 4096		/* amount of buffering in a pipe */
+# define PIPESIZE 4096          /* amount of buffering in a pipe */
 #else
 # define PIPESIZE PIPE_BUF
 #endif
 
 
-struct redirtab *redirlist;
-
-/*
- * We keep track of whether or not fd0 has been redirected.  This is for
- * background commands, where we want to redirect fd0 to /dev/null only
- * if it hasn't already been redirected.
-*/
-static int fd0_redirected = 0;
-
-/*
- * We also keep track of where fileno2 goes.
- */
-static int fileno2 = 2;
-
-static int openredirect __P((union node *));
-static void dupredirect __P((union node *, int, char[10 ]));
-static int openhere __P((union node *));
-static int noclobberopen __P((const char *));
-
 
 /*
  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
@@ -10884,7 +11543,7 @@
 	int fd;
 	int newfd;
 	int try;
-	char memory[10];	/* file descriptors to write to memory */
+	char memory[10];        /* file descriptors to write to memory */
 
 	for (i = 10 ; --i >= 0 ; )
 		memory[i] = 0;
@@ -10923,7 +11582,7 @@
 						close(newfd);
 					}
 					INTON;
-					error("%d: %s", fd, strerror(errno));
+					error("%d: %m", fd);
 					/* NOTREACHED */
 				}
 			}
@@ -10939,8 +11598,8 @@
 		} else if (fd != newfd) {
 			close(fd);
 		}
-                if (fd == 0)
-                        fd0_redirected++;
+		if (fd == 0)
+			fd0_redirected++;
 		if (!try)
 			dupredirect(n, newfd, memory);
 		INTON;
@@ -11024,16 +11683,13 @@
 
 
 static void
-dupredirect(redir, f, memory)
-	union node *redir;
-	int f;
-	char memory[10];
-	{
+dupredirect(union node *redir, int f, char memory[10])
+{
 	int fd = redir->nfile.fd;
 
 	memory[fd] = 0;
 	if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
-		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
+		if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
 			if (memory[redir->ndup.dupfd])
 				memory[fd] = 1;
 			else
@@ -11093,21 +11749,21 @@
 }
 
 
-
 /*
  * Undo the effects of the last redirection.
  */
 
 static void
-popredir() {
+popredir(void)
+{
 	struct redirtab *rp = redirlist;
 	int i;
 
 	INTOFF;
 	for (i = 0 ; i < 10 ; i++) {
 		if (rp->renamed[i] != EMPTY) {
-                        if (i == 0)
-                                fd0_redirected--;
+			if (i == 0)
+				fd0_redirected--;
 			close(i);
 			if (rp->renamed[i] >= 0) {
 				dup_as_newfd(rp->renamed[i], i);
@@ -11124,36 +11780,11 @@
 }
 
 /*
- * Undo all redirections.  Called on error or interrupt.
- */
-
-#ifdef mkinit
-
-INCLUDE "redir.h"
-
-RESET {
-	while (redirlist)
-		popredir();
-}
-
-SHELLPROC {
-	clearredir();
-}
-
-#endif
-
-/* Return true if fd 0 has already been redirected at least once.  */
-static int
-fd0_redirected_p () {
-        return fd0_redirected != 0;
-}
-
-/*
  * Discard all saved file descriptors.
  */
 
 static void
-clearredir() {
+clearredir(void) {
 	struct redirtab *rp;
 	int i;
 
@@ -11175,7 +11806,6 @@
 }
 
 
-
 /*
  * Copy a file descriptor to be >= to.  Returns -1
  * if the source file descriptor is closed, EMPTY if there are no unused
@@ -11194,7 +11824,7 @@
 		if (errno == EMFILE)
 			return EMPTY;
 		else
-			error("%d: %s", from, strerror(errno));
+			error("%d: %m", from);
 	}
 	return newfd;
 }
@@ -11204,8 +11834,7 @@
  * The code was copied from bash.
  */
 static int
-noclobberopen(fname)
-	const char *fname;
+noclobberopen(const char *fname)
 {
 	int r, fd;
 	struct stat finfo, finfo2;
@@ -11250,43 +11879,41 @@
 	 */
 	 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
 	     finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
-	 	return fd;
+		return fd;
 
 	/* The file has been replaced.  badness. */
 	close(fd);
 	errno = EEXIST;
 	return -1;
 }
-/*	$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $	*/
-
-#ifdef __weak_alias
+/*#ifdef __weak_alias
 __weak_alias(getmode,_getmode)
 __weak_alias(setmode,_setmode)
-#endif
+#endif*/
 
 #ifdef __GLIBC__
 #define S_ISTXT __S_ISVTX
 #endif
 
-#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
-#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+#define SET_LEN 6               /* initial # of bitcmd struct to malloc */
+#define SET_LEN_INCR 4          /* # of bitcmd structs to add as needed */
 
 typedef struct bitcmd {
-	char	cmd;
-	char	cmd2;
-	mode_t	bits;
+	char    cmd;
+	char    cmd2;
+	mode_t  bits;
 } BITCMD;
 
-#define	CMD2_CLR	0x01
-#define	CMD2_SET	0x02
-#define	CMD2_GBITS	0x04
-#define	CMD2_OBITS	0x08
-#define	CMD2_UBITS	0x10
+#define CMD2_CLR        0x01
+#define CMD2_SET        0x02
+#define CMD2_GBITS      0x04
+#define CMD2_OBITS      0x08
+#define CMD2_UBITS      0x10
 
-static BITCMD	*addcmd __P((BITCMD *, int, int, int, u_int));
-static void	 compress_mode __P((BITCMD *));
+static BITCMD   *addcmd (BITCMD *, int, int, int, u_int);
+static void      compress_mode (BITCMD *);
 #ifdef SETMODE_DEBUG
-static void	 dumpmode __P((BITCMD *));
+static void      dumpmode (BITCMD *);
 #endif
 
 /*
@@ -11295,7 +11922,7 @@
  * Note that there is no '=' command; a strict assignment is just a '-' (clear
  * bits) followed by a '+' (set bits).
  */
-mode_t
+static mode_t
 getmode(bbox, omode)
 	const void *bbox;
 	mode_t omode;
@@ -11325,7 +11952,7 @@
 
 		case 'o':
 			value = newmode & S_IRWXO;
-common:			if (set->cmd2 & CMD2_CLR) {
+common:                 if (set->cmd2 & CMD2_CLR) {
 				clrval =
 				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
 				if (set->cmd2 & CMD2_UBITS)
@@ -11367,23 +11994,23 @@
 		}
 }
 
-#define	ADDCMD(a, b, c, d) do {						\
-	if (set >= endset) {						\
-		BITCMD *newset;						\
-		setlen += SET_LEN_INCR;					\
-		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
-		if (newset == NULL) {					\
-			free(saveset);					\
-			return (NULL);					\
-		}							\
-		set = newset + (set - saveset);				\
-		saveset = newset;					\
-		endset = newset + (setlen - 2);				\
-	}								\
-	set = addcmd(set, (a), (b), (c), (d));				\
+#define ADDCMD(a, b, c, d) do {                                         \
+	if (set >= endset) {                                            \
+		BITCMD *newset;                                         \
+		setlen += SET_LEN_INCR;                                 \
+		newset = realloc(saveset, sizeof(BITCMD) * setlen);     \
+		if (newset == NULL) {                                   \
+			free(saveset);                                  \
+			return (NULL);                                  \
+		}                                                       \
+		set = newset + (set - saveset);                         \
+		saveset = newset;                                       \
+		endset = newset + (setlen - 2);                         \
+	}                                                               \
+	set = addcmd(set, (a), (b), (c), (d));                          \
 } while (/*CONSTCOND*/0)
 
-#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+#define STANDARD_BITS   (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
 
 static void *
 setmode(p)
@@ -11394,7 +12021,7 @@
 	BITCMD *set, *saveset, *endset;
 	sigset_t mysigset, sigoset;
 	mode_t mask;
-	int equalopdone = 0;	/* pacify gcc */
+	int equalopdone = 0;    /* pacify gcc */
 	int permXbits, setlen;
 
 	if (!*p)
@@ -11413,7 +12040,7 @@
 	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
 
 	setlen = SET_LEN + 2;
-	
+
 	if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
 		return (NULL);
 	saveset = set;
@@ -11459,7 +12086,7 @@
 			}
 		}
 
-getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
+getop:          if ((op = *p++) != '+' && op != '-' && op != '=') {
 			free(saveset);
 			return (NULL);
 		}
@@ -11474,16 +12101,16 @@
 				break;
 			case 's':
 				/*
-				 * If specific bits where requested and 
-				 * only "other" bits ignore set-id. 
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
 				 */
 				if (who == 0 || (who & ~S_IRWXO))
 					perm |= S_ISUID|S_ISGID;
 				break;
 			case 't':
 				/*
-				 * If specific bits where requested and 
-				 * only "other" bits ignore set-id. 
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
 				 */
 				if (who == 0 || (who & ~S_IRWXO)) {
 					who |= S_ISTXT;
@@ -11539,7 +12166,7 @@
 			}
 		}
 
-apply:		if (!*p)
+apply:          if (!*p)
 			break;
 		if (*p != ',')
 			goto getop;
@@ -11596,7 +12223,7 @@
 			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
 			set->bits = mask;
 		}
-	
+
 		if (oparg == '+')
 			set->cmd2 |= CMD2_SET;
 		else if (oparg == '-')
@@ -11630,7 +12257,7 @@
 /*
  * Given an array of bitcmd structures, compress by compacting consecutive
  * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
- * 'g' and 'o' commands continue to be separate.  They could probably be 
+ * 'g' and 'o' commands continue to be separate.  They could probably be
  * compacted, but it's not worth the effort.
  */
 static void
@@ -11684,15 +12311,12 @@
 		}
 	}
 }
-/*	$NetBSD: show.c,v 1.18 1999/10/08 21:10:44 pk Exp $	*/
-
-
 #ifdef DEBUG
-static void shtree __P((union node *, int, char *, FILE*));
-static void shcmd __P((union node *, FILE *));
-static void sharg __P((union node *, FILE *));
-static void indent __P((int, char *, FILE *));
-static void trstring __P((char *));
+static void shtree (union node *, int, char *, FILE*);
+static void shcmd (union node *, FILE *);
+static void sharg (union node *, FILE *);
+static void indent (int, char *, FILE *);
+static void trstring (char *);
 
 
 static void
@@ -11780,14 +12404,14 @@
 		if (! first)
 			putchar(' ');
 		switch (np->nfile.type) {
-			case NTO:	s = ">";  dftfd = 1; break;
-			case NAPPEND:	s = ">>"; dftfd = 1; break;
-			case NTOFD:	s = ">&"; dftfd = 1; break;
-			case NTOOV:	s = ">|"; dftfd = 1; break;
-			case NFROM:	s = "<";  dftfd = 0; break;
-			case NFROMFD:	s = "<&"; dftfd = 0; break;
-			case NFROMTO:	s = "<>"; dftfd = 0; break;
-			default:  	s = "*error*"; dftfd = 0; break;
+			case NTO:       s = ">";  dftfd = 1; break;
+			case NAPPEND:   s = ">>"; dftfd = 1; break;
+			case NTOFD:     s = ">&"; dftfd = 1; break;
+			case NTOOV:     s = ">|"; dftfd = 1; break;
+			case NFROM:     s = "<";  dftfd = 0; break;
+			case NFROMFD:   s = "<&"; dftfd = 0; break;
+			case NFROMTO:   s = "<>"; dftfd = 0; break;
+			default:        s = "*error*"; dftfd = 0; break;
 		}
 		if (np->nfile.fd != dftfd)
 			fprintf(fp, "%d", np->nfile.fd);
@@ -11988,7 +12612,7 @@
 		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
 		case CTLBACKQ:  c = 'q';  goto backslash;
 		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
-backslash:	  putc('\\', tracefile);
+backslash:        putc('\\', tracefile);
 			putc(c, tracefile);
 			break;
 		default:
@@ -12042,11 +12666,11 @@
 			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\n", s);
@@ -12063,356 +12687,6 @@
 
 
 /*
- * This file was generated by the mksyntax program.
- */
-
-/* syntax table used when not in quotes */
-static const char basesyntax[257] = {
-      CEOF,    CSPCL,   CWORD,   CCTL,
-      CCTL,    CCTL,    CCTL,    CCTL,
-      CCTL,    CCTL,    CCTL,    CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CSPCL,
-      CNL,     CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CSPCL,   CWORD,
-      CDQUOTE, CWORD,   CVAR,    CWORD,
-      CSPCL,   CSQUOTE, CSPCL,   CSPCL,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CSPCL,   CSPCL,   CWORD,
-      CSPCL,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CBACK,   CWORD,
-      CWORD,   CWORD,   CBQUOTE, CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CSPCL,   CENDVAR,
-      CWORD
-};
-
-/* syntax table used when in double quotes */
-static const char dqsyntax[257] = {
-      CEOF,    CIGN,    CWORD,   CCTL,
-      CCTL,    CCTL,    CCTL,    CCTL,
-      CCTL,    CCTL,    CCTL,    CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CNL,     CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CCTL,
-      CENDQUOTE,CWORD,  CVAR,    CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CCTL,    CWORD,   CWORD,   CCTL,
-      CWORD,   CCTL,    CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CCTL,    CWORD,   CWORD,   CCTL,
-      CWORD,   CCTL,    CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CCTL,    CBACK,   CCTL,
-      CWORD,   CWORD,   CBQUOTE, CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CENDVAR,
-      CCTL
-};
-
-/* syntax table used when in single quotes */
-static const char sqsyntax[257] = {
-      CEOF,    CIGN,    CWORD,   CCTL,
-      CCTL,    CCTL,    CCTL,    CCTL,
-      CCTL,    CCTL,    CCTL,    CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CNL,     CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CCTL,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CENDQUOTE,CWORD,  CWORD,
-      CCTL,    CWORD,   CWORD,   CCTL,
-      CWORD,   CCTL,    CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CCTL,    CWORD,   CWORD,   CCTL,
-      CWORD,   CCTL,    CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CCTL,    CCTL,    CCTL,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CCTL
-};
-
-/* syntax table used when in arithmetic */
-static const char arisyntax[257] = {
-      CEOF,    CIGN,    CWORD,   CCTL,
-      CCTL,    CCTL,    CCTL,    CCTL,
-      CCTL,    CCTL,    CCTL,    CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CNL,     CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CDQUOTE, CWORD,   CVAR,    CWORD,
-      CWORD,   CSQUOTE, CLP,     CRP,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CBACK,   CWORD,
-      CWORD,   CWORD,   CBQUOTE, CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CWORD,
-      CWORD,   CWORD,   CWORD,   CENDVAR,
-      CWORD
-};
-
-/* character classification table */
-static const char is_type[257] = {
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       ISSPECL,
-      0,       ISSPECL, ISSPECL, 0,
-      0,       0,       0,       0,
-      ISSPECL, 0,       0,       ISSPECL,
-      0,       0,       ISDIGIT, ISDIGIT,
-      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
-      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
-      0,       0,       0,       0,
-      0,       ISSPECL, ISSPECL, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, 0,       0,       0,
-      0,       ISUNDER, 0,       ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, 0,       0,       0,
-      0
-};
-/*	$NetBSD: trap.c,v 1.25 2001/02/04 19:52:07 christos Exp $	*/
-
-/*
  * The trap builtin.
  */
 
@@ -12467,25 +12741,6 @@
 
 
 
-/*
- * Clear traps on a fork.
- */
-
-static void
-clear_traps() {
-	char **tp;
-
-	for (tp = trap ; tp < &trap[NSIG] ; tp++) {
-		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
-			INTOFF;
-			ckfree(*tp);
-			*tp = NULL;
-			if (tp != &trap[0])
-				setsignal(tp - trap);
-			INTON;
-		}
-	}
-}
 
 
 
@@ -12495,8 +12750,7 @@
  */
 
 static void
-setsignal(signo)
-	int signo;
+setsignal(int signo)
 {
 	int action;
 	char *t;
@@ -12517,7 +12771,6 @@
 		case SIGQUIT:
 #ifdef DEBUG
 			{
-			extern int debug;
 
 			if (debug)
 				break;
@@ -12528,7 +12781,7 @@
 			if (iflag)
 				action = S_IGN;
 			break;
-#if JOBS
+#ifdef JOBS
 		case SIGTSTP:
 		case SIGTTOU:
 			if (mflag)
@@ -12554,11 +12807,11 @@
 		if (act.sa_handler == SIG_IGN) {
 			if (mflag && (signo == SIGTSTP ||
 			     signo == SIGTTIN || signo == SIGTTOU)) {
-				*t = S_IGN;	/* don't hard ignore these */
+				*t = S_IGN;     /* don't hard ignore these */
 			} else
 				*t = S_HARD_IGN;
 		} else {
-			*t = S_RESET;	/* force to be set */
+			*t = S_RESET;   /* force to be set */
 		}
 	}
 	if (*t == S_HARD_IGN || *t == action)
@@ -12594,30 +12847,12 @@
 }
 
 
-#ifdef mkinit
-INCLUDE <signal.h>
-INCLUDE "trap.h"
-
-SHELLPROC {
-	char *sm;
-
-	clear_traps();
-	for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
-		if (*sm == S_IGN)
-			*sm = S_HARD_IGN;
-	}
-}
-#endif
-
-
-
 /*
  * Signal handler.
  */
 
 static void
-onsig(signo)
-	int signo;
+onsig(int signo)
 {
 	if (signo == SIGINT && trap[SIGINT] == NULL) {
 		onint();
@@ -12628,14 +12863,14 @@
 }
 
 
-
 /*
  * Called to execute a trap.  Perhaps we should avoid entering new trap
  * handlers while we are executing a trap handler.
  */
 
 static void
-dotrap() {
+dotrap(void)
+{
 	int i;
 	int savestatus;
 
@@ -12655,37 +12890,12 @@
 	pendingsigs = 0;
 }
 
-
-
-/*
- * Controls whether the shell is interactive or not.
- */
-
-
-static void
-setinteractive(on)
-	int on;
-{
-	static int is_interactive;
-
-	if (on == is_interactive)
-		return;
-	setsignal(SIGINT);
-	setsignal(SIGQUIT);
-	setsignal(SIGTERM);
-	chkmail(1);
-	is_interactive = on;
-}
-
-
-
 /*
  * Called to exit the shell.
  */
 
 static void
-exitshell(status)
-	int status;
+exitshell(int status)
 {
 	struct jmploc loc1, loc2;
 	char *p;
@@ -12702,9 +12912,9 @@
 		trap[0] = NULL;
 		evalstring(p, 0);
 	}
-l1:   handler = &loc2;			/* probably unnecessary */
+l1:   handler = &loc2;                  /* probably unnecessary */
 	flushall();
-#if JOBS
+#ifdef JOBS
 	setjobctl(0);
 #endif
 l2:   _exit(status);
@@ -12715,8 +12925,7 @@
 {
 	int signo;
 
-	if (is_number(string)) {
-		signo = atoi(string);
+	if (is_number(string, &signo)) {
 		if (signo >= NSIG) {
 			return -1;
 		}
@@ -12739,100 +12948,14 @@
 
 	return -1;
 }
-/*	$NetBSD: var.c,v 1.27 2001/02/04 19:52:07 christos Exp $	*/
-
-#define VTABSIZE 39
-
-
-struct varinit {
-	struct var *var;
-	int flags;
-	const char *text;
-	void (*func) __P((const char *));
-};
-
-struct localvar *localvars;
-
-#if ATTY
-struct var vatty;
-#endif
-struct var vifs;
-struct var vmail;
-struct var vmpath;
-struct var vpath;
-struct var vps1;
-struct var vps2;
-struct var vvers;
-struct var voptind;
-
-static const char defpathvar[] =
-	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
-#ifdef IFS_BROKEN
-static const char defifsvar[] = "IFS= \t\n";
-#else
-static const char defifs[] = " \t\n";
-#endif
-
-static const struct varinit varinit[] = {
-#if ATTY
-	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
-	  NULL },
-#endif
-#ifdef IFS_BROKEN
-	{ &vifs,	VSTRFIXED|VTEXTFIXED,		defifsvar,
-#else
-	{ &vifs,	VSTRFIXED|VTEXTFIXED|VUNSET,	"IFS=",
-#endif
-	  NULL },
-	{ &vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",
-	  NULL },
-	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
-	  NULL },
-	{ &vpath,	VSTRFIXED|VTEXTFIXED,		defpathvar,
-	  changepath },
-	/*
-	 * vps1 depends on uid
-	 */
-	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
-	  NULL },
-	{ &voptind,	VSTRFIXED|VTEXTFIXED,		"OPTIND=1",
-	  getoptsreset },
-	{ NULL,	0,				NULL,
-	  NULL }
-};
-
-struct var *vartab[VTABSIZE];
-
-static struct var **hashvar __P((const char *));
-static void showvars __P((const char *, int, int));
-static struct var **findvar __P((struct var **, const char *));
+static struct var **hashvar (const char *);
+static void showvars (const char *, int, int);
+static struct var **findvar (struct var **, const char *);
 
 /*
  * Initialize the varable symbol tables and import the environment
  */
 
-#ifdef mkinit
-INCLUDE <unistd.h>
-INCLUDE "output.h"
-INCLUDE "var.h"
-static char **environ;
-INIT {
-	char **envp;
-	char ppid[32];
-
-	initvar();
-	for (envp = environ ; *envp ; envp++) {
-		if (strchr(*envp, '=')) {
-			setvareq(*envp, VEXPORT|VTEXTFIXED);
-		}
-	}
-
-	fmtstr(ppid, sizeof(ppid), "%d", (int) getppid());
-	setvar("PPID", ppid, 0);
-}
-#endif
-
-
 /*
  * This routine initializes the builtin variables.  It is called when the
  * shell is initialized and again when a shell procedure is spawned.
@@ -12899,7 +13022,7 @@
 	namelen = p - name;
 	if (isbad)
 		error("%.*s: bad variable name", namelen, name);
-	len = namelen + 2;		/* 2 is space for '=' and '\0' */
+	len = namelen + 2;              /* 2 is space for '=' and '\0' */
 	if (val == NULL) {
 		flags |= VUNSET;
 	} else {
@@ -13065,16 +13188,8 @@
  * VSTACK set since these are currently allocated on the stack.
  */
 
-#ifdef mkinit
-static void shprocvar __P((void));
-
-SHELLPROC {
-	shprocvar();
-}
-#endif
-
 static void
-shprocvar() {
+shprocvar(void) {
 	struct var **vpp;
 	struct var *vp, **prev;
 
@@ -13158,6 +13273,8 @@
  * The "local" command.
  */
 
+/* funcnest nonzero if we are currently evaluating a function */
+
 static int
 localcmd(argc, argv)
 	int argc;
@@ -13165,7 +13282,7 @@
 {
 	char *name;
 
-	if (! in_function())
+	if (! funcnest)
 		error("Not in a function");
 	while ((name = *argptr++) != NULL) {
 		mklocal(name);
@@ -13193,8 +13310,8 @@
 	lvp = ckmalloc(sizeof (struct localvar));
 	if (name[0] == '-' && name[1] == '\0') {
 		char *p;
-		p = ckmalloc(sizeof optlist);
-		lvp->text = memcpy(p, optlist, sizeof optlist);
+		p = ckmalloc(sizeof optet_vals);
+		lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
 		vp = NULL;
 	} else {
 		vpp = hashvar(name);
@@ -13204,7 +13321,7 @@
 				setvareq(savestr(name), VSTRFIXED);
 			else
 				setvar(name, NULL, VSTRFIXED);
-			vp = *vpp;	/* the new variable */
+			vp = *vpp;      /* the new variable */
 			lvp->text = NULL;
 			lvp->flags = VUNSET;
 		} else {
@@ -13234,8 +13351,8 @@
 	while ((lvp = localvars) != NULL) {
 		localvars = lvp->next;
 		vp = lvp->vp;
-		if (vp == NULL) {	/* $- saved */
-			memcpy(optlist, lvp->text, sizeof optlist);
+		if (vp == NULL) {       /* $- saved */
+			memcpy(optet_vals, lvp->text, sizeof optet_vals);
 			ckfree(lvp->text);
 		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
 			(void)unsetvar(vp->text);
@@ -13415,7 +13532,7 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: ash.c,v 1.3 2001/06/28 16:43:57 andersen Exp $
+ * $Id: ash.c,v 1.4 2001/07/02 17:27:21 andersen Exp $
  */
 static int timescmd (int argc, char **argv)
 {
@@ -13438,7 +13555,7 @@
 
 /*-
  * Copyright (c) 1989, 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
@@ -13452,8 +13569,8 @@
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
- * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change 
- *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> 
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
  *
  * 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