/*-
 * Copyright (c) 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Kenneth Almquist.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*	$NetBSD: alias.h,v 1.4 1995/05/11 21:28:42 christos Exp $	*/

#define ALIASINUSE	1
#define ALIASDEAD	2

struct alias {
	struct alias *next;
	char *name;
	char *val;
	int flag;
};

struct alias *lookupalias __P((const char *, int));
static int aliascmd __P((int, char **));
static int unaliascmd __P((int, char **));
static void rmaliases __P((void));
static int unalias __P((char *));
static void printalias __P((const struct alias *));
#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

/*
 * This file was generated by the mkbuiltins program.
 */


#define BUILTIN_SPECIAL 0x1
#define BUILTIN_REGULAR 0x2
#define BUILTIN_ASSIGN 0x4

struct builtincmd {
	const char *name;
	int (*const builtinfunc) __P((int, char **));
	unsigned flags;
};

extern const struct builtincmd builtincmds[];



/*	$NetBSD: cd.h,v 1.2 1997/07/04 21:01:52 christos Exp $	*/
static int	cdcmd __P((int, char **));
static int	pwdcmd __P((int, char **));
static void	setpwd __P((const char *, int));


/*	$NetBSD: error.h,v 1.14 2001/02/04 19:52:06 christos Exp $	*/

/*
 * 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 */


/*
 * 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;
};

extern struct jmploc *handler;
extern int exception;

/* 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 */


/*
 * 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. :-))
 */

extern int suppressint;
extern volatile int intpending;

#define INTOFF suppressint++
#ifdef REALLY_SMALL
static void __inton __P((void));
#define INTON __inton()
#else
#define INTON { if (--suppressint == 0 && intpending) onint(); }
#endif
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
#define CLEAR_PENDING_INT intpending = 0
#define int_pending() intpending

static void exraise __P((int)) __attribute__((__noreturn__));
static void onint __P((void));
static void error __P((const char *, ...)) __attribute__((__noreturn__));
static void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
static const char *errmsg __P((int, int));


/*
 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
 * so we use _setjmp instead.
 */

#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__)
#define setjmp(jmploc)	_setjmp(jmploc)
#define longjmp(jmploc, val)	_longjmp(jmploc, val)
#endif



/*	$NetBSD: shell.h,v 1.13 2000/05/22 10:18:47 elric Exp $	*/

/*
 * The follow should be set to reflect the type of system you have:
 *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
 *	SHORTNAMES -> 1 if your linker cannot handle long names.
 *	define BSD if you are running 4.2 BSD or later.
 *	define SYSV if you are running under System V.
 *	define DEBUG=1 to compile in debugging (set global "debug" to turn on)
 *	define DEBUG=2 to compile in and turn on debugging.
 *
 * When debugging is on, debugging info will be written to $HOME/trace and
 * a quit signal will generate a core dump.
 */


#define JOBS 1
#ifndef BSD
#define BSD 1
#endif

#ifdef __STDC__
typedef void *pointer;
#ifndef NULL
#define NULL (void *)0
#endif
#else /* not __STDC__ */
typedef char *pointer;
#ifndef NULL
#define NULL 0
#endif
#endif /*  not __STDC__ */

extern char nullstr[1];		/* null string */


#ifdef DEBUG
#define TRACE(param)	trace param
#else
#define TRACE(param)
#endif




/*
 * This file was generated by the mknodes program.
 */

#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



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;
};


#ifdef __STDC__
union node *copyfunc(union node *);
static void freefunc(union node *);
#else
union node *copyfunc();
static void freefunc();
#endif



/*	$NetBSD: eval.h,v 1.10 2000/01/27 23:39:40 christos Exp $	*/
extern char *commandname;	/* currently executing command */
extern int exitstatus;		/* exit status of last command */
extern struct strlist *cmdenviron;  /* environment for builtin command */


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 */
};

static int evalcmd __P((int, char **));
static void evalstring __P((char *, int));
static void evaltree __P((union node *, int));
static void evalbackcmd __P((union node *, struct backcmd *));
static int bltincmd __P((int, char **));
static int breakcmd __P((int, char **));
static int returncmd __P((int, char **));
static int execcmd __P((int, char **));

/* in_function returns nonzero if we are currently evaluating a function */
#define in_function()	funcnest
extern int funcnest;
extern int evalskip;

/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK	1
#define SKIPCONT	2
#define SKIPFUNC	3
#define SKIPFILE	4




/*	$NetBSD: exec.h,v 1.17 2000/05/22 10:18:47 elric Exp $	*/

/* 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 */


struct cmdentry {
	int cmdtype;
	union param {
		int index;
		union node *func;
		const struct builtincmd *cmd;
	} u;
};


#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 */

extern const char *pathopt;	/* set by padvance */
extern int exerrno;		/* last exec error */

static void shellexec __P((char **, char **, const char *, int))
    __attribute__((noreturn));
static char *padvance __P((const char **, const char *));
static int hashcmd __P((int, char **));
static void find_command __P((char *, struct cmdentry *, int, const char *));
struct builtincmd *find_builtin __P((char *));
static void hashcd __P((void));
static void changepath __P((const char *));
static void deletefuncs __P((void));
#ifdef notdef
static void getcmdentry __P((char *, struct cmdentry *));
#endif
static void addcmdentry __P((char *, struct cmdentry *));
static void defun __P((char *, union node *));
static void unsetfunc __P((char *));
#ifdef ASH_TYPE
static int typecmd __P((int, char **));
#endif
static int commandcmd __P((int, char **));



/*	$NetBSD: expand.h,v 1.12 1999/07/09 03:05:50 christos Exp $	*/
struct strlist {
	struct strlist *next;
	char *text;
};


struct arglist {
	struct strlist *list;
	struct strlist **lastp;
};

/*
 * 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 */


static void expandhere __P((union node *, int));
static void expandarg __P((union node *, struct arglist *, int));
#ifdef ASH_MATH_SUPPORT
static void expari __P((int));
#endif
#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
static int patmatch __P((char *, char *, int));
#endif
#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
#define rmescapes(p) _rmescapes((p), 0)
static char *_rmescapes __P((char *, int));
#else
static void rmescapes __P((char *));
#endif
static int casematch __P((union node *, char *));


#ifdef ASH_MATH_SUPPORT
/* From arith.y */
static int arith __P((const char *));
static int expcmd __P((int , char **));
static void arith_lex_reset __P((void));
static int yylex __P((void));
#endif	




/*	$NetBSD: init.h,v 1.8 1995/05/11 21:29:14 christos Exp $	*/
static void init __P((void));
static void reset __P((void));
static void initshellproc __P((void));



/*	$NetBSD: input.h,v 1.12 2000/05/22 10:18:47 elric Exp $	*/

/* PEOF (the end of file marker) is defined in syntax.h */
/*
 * The input line number.  Input.c just defines this variable, and saves
 * and restores it when files are pushed and popped.  The user of this
 * package must set its value.
 */
extern int plinno;
extern int parsenleft;		/* number of characters left in input buffer */
extern char *parsenextc;	/* next character in input buffer */

static char *pfgets __P((char *, int));
static int pgetc __P((void));
static int pgetc2 __P((void));
static int preadbuffer __P((void));
static void pungetc __P((void));
static void pushstring __P((char *, int, void *));
static void popstring __P((void));
static void setinputfile __P((const char *, int));
static void setinputfd __P((int, int));
static void setinputstring __P((char *));
static void popfile __P((void));
static void popallfiles __P((void));
static void closescript __P((void));

#define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())



/*	$NetBSD: jobs.h,v 1.12 2000/05/22 10:18:47 elric Exp $	*/

/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
#define FORK_FG 0
#define FORK_BG 1
#define FORK_NOJOB 2


/*
 * 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.
 */

struct procstat {
	pid_t pid;		/* process id */
	int status;		/* status flags (defined above) */
	char *cmd;		/* text of command being run */
};


/* states */
#define JOBSTOPPED 1		/* all procs are stopped */
#define JOBDONE 2		/* all procs are completed */


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 */
#if JOBS
	char jobctl;		/* job running under job control */
#endif
};

extern short backgndpid;	/* pid of last background process */
extern int job_warning;		/* user was warned about stopped jobs */

static void setjobctl __P((int));
static int killcmd __P((int, char **));
static int fgcmd __P((int, char **));
static int bgcmd __P((int, char **));
static int jobscmd __P((int, char **));
static void showjobs __P((int));
static int waitcmd __P((int, char **));
struct job *makejob __P((union node *, int));
static int forkshell __P((struct job *, union node *, int));
static int waitforjob __P((struct job *));
static int stoppedjobs __P((void));
static char *commandtext __P((union node *));

#if ! JOBS
#define setjobctl(on)	/* do nothing */
#endif



/*	$NetBSD: machdep.h,v 1.8 1995/05/11 21:29:21 christos Exp $	*/

/*
 * 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



/*	$NetBSD: mail.h,v 1.8 1995/05/11 21:29:23 christos Exp $	*/

static void chkmail __P((int));



/*	$NetBSD: main.h,v 1.8 1995/05/11 21:29:27 christos Exp $	*/
extern int rootpid;	/* pid of main shell */
extern int rootshell;	/* true if we aren't a child of the main shell */

static void readcmdfile __P((char *));
static void cmdloop __P((int));
static int dotcmd __P((int, char **));
static int exitcmd __P((int, char **));



/*	$NetBSD: memalloc.h,v 1.11 2000/11/01 19:56:01 christos Exp $	*/
struct stackmark {
	struct stack_block *stackp;
	char *stacknxt;
	int stacknleft;
	struct stackmark *marknext;
};


extern char *stacknxt;
extern int stacknleft;
extern int sstrnleft;
extern int herefd;

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);      }

pointer stalloc __P((int));
static void stunalloc __P((pointer));
static void setstackmark __P((struct stackmark *));
static void popstackmark __P((struct stackmark *));
static void growstackblock __P((void));
static void grabstackblock __P((int));
static char *growstackstr __P((void));
static char *makestrspace __P((size_t));
static void ungrabstackstr __P((char *, char *));



#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))



/*	$NetBSD: miscbltin.h,v 1.1 1997/07/04 21:02:10 christos Exp $	*/
static int readcmd __P((int, char **));
static int umaskcmd __P((int, char **));
static int ulimitcmd __P((int, char **));



/*	$NetBSD: mystring.h,v 1.9 1995/05/11 21:29:42 christos Exp $	*/

extern const char snlfmt[];
extern const char spcstr[];

#if 0
static void scopyn __P((const char *, char *, int));
#endif
static int prefix __P((const char *, const char *));
static int number __P((const char *));
static int is_number __P((const char *));
static char *single_quote __P((const char *));
static char *sstrdup __P((const char *));
static int pstrcmp __P((const void *, const void *));
static const char *const *findstring __P((const char *, const char *const *, size_t));

#define equal(s1, s2)	(strcmp(s1, s2) == 0)
#define scopy(s1, s2)	((void)strcpy(s2, s1))


/*	$NetBSD: options.h,v 1.14 2001/02/04 19:52:06 christos Exp $	*/

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 */
};



#define eflag optlist[0].val
#define fflag optlist[1].val
#define Iflag optlist[2].val
#define iflag optlist[3].val
#define mflag optlist[4].val
#define nflag optlist[5].val
#define sflag optlist[6].val
#define xflag optlist[7].val
#define vflag optlist[8].val
#define Vflag optlist[9].val
#define	Eflag optlist[10].val
#define	Cflag optlist[11].val
#define	aflag optlist[12].val
#define	bflag optlist[13].val
#define	uflag optlist[14].val
#define	qflag optlist[15].val

#define NOPTS	16

struct optent {
	const char *name;
	const char letter;
	char val;
};

extern struct optent optlist[NOPTS];


extern char *minusc;		/* argument to -c option */
extern char *arg0;		/* $0 */
extern struct shparam shellparam;  /* $@ */
extern char **argptr;		/* argument list for builtin commands */
extern char *optionarg;		/* set by nextopt */
extern char *optptr;		/* used by nextopt */

static void procargs __P((int, char **));
static void optschanged __P((void));
static void setparam __P((char **));
static void freeparam __P((volatile struct shparam *));
static int shiftcmd __P((int, char **));
static int setcmd __P((int, char **));
#ifdef ASH_GETOPTS
static int getoptscmd __P((int, char **));
static int setvarsafe __P((const char *, const char *, int));
#endif
static int nextopt __P((const char *));
static void getoptsreset __P((const char *));



/*	$NetBSD: output.h,v 1.14 1998/01/31 12:37:55 christos Exp $	*/
struct output {
#ifdef USE_GLIBC_STDIO
	FILE *stream;
#endif
	char *nextc;
	int nleft;
	char *buf;
	int bufsize;
	int fd;
	short flags;
};

extern struct output output;
extern struct output errout;
extern struct output memout;
extern struct output *out1;
extern struct output *out2;

static void outstr __P((const char *, struct output *));
#ifndef USE_GLIBC_STDIO
static void outcslow __P((char, struct output *));
#endif
static void flushall __P((void));
static void flushout __P((struct output *));
static void freestdout __P((void));
static void outfmt __P((struct output *, const char *, ...))
    __attribute__((__format__(__printf__,2,3)));
static void out1fmt __P((const char *, ...))
    __attribute__((__format__(__printf__,1,2)));
static void fmtstr __P((char *, size_t, const char *, ...))
    __attribute__((__format__(__printf__,3,4)));
#ifndef USE_GLIBC_STDIO
static void doformat __P((struct output *, const char *, va_list));
#endif
static int xwrite __P((int, const char *, int));
#ifdef USE_GLIBC_STDIO
static void initstreams __P((void));
static void openmemout __P((void));
static int __closememout __P((void));
#endif

#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)



/*	$NetBSD: parser.h,v 1.14 2000/07/27 04:09:28 cgd Exp $	*/
/* 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'

/* 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 */

/* 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} */


/*
 * 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.
 */
extern int tokpushback;
#define NEOF ((union node *)&tokpushback)
extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
extern int checkalias;


union node *parsecmd(int);
static void fixredir(union node *, const char *, int);
static int goodname(char *);
static const char *getprompt(void *);
static int isassignment __P((const char *));
static const char *const *findkwd __P((const char *));


/*	$NetBSD: redir.h,v 1.12 2000/05/22 10:18:47 elric Exp $	*/
/* flags passed to redirect */
#define REDIR_PUSH 01		/* save previous values of file descriptors */
#define REDIR_BACKQ 02		/* save the command output in memory */

extern int fileno2;

static void redirect __P((union node *, int));
static void popredir __P((void));
static int fd0_redirected_p __P((void));
static void clearredir __P((void));
static int dup_as_newfd __P((int, int));




/*	$NetBSD: show.h,v 1.4 1999/10/08 21:10:44 pk Exp $	*/
#ifdef DEBUG
static void trace __P((const char *, ...));
static void trargs __P((char **));
static void showtree __P((union node *));
static void trputc __P((int));
static void trputs __P((const char *));
static void opentrace __P((void));
#endif
/*
 * This file was generated by the mksyntax program.
 */

#ifdef CEOF
#undef CEOF
#endif

/* 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 CEOF 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 BASESYNTAX (basesyntax + SYNBASE)
#define DQSYNTAX (dqsyntax + SYNBASE)
#define SQSYNTAX (sqsyntax + SYNBASE)
#define ARISYNTAX (arisyntax + SYNBASE)

#define is_digit(c)	((unsigned)((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')

extern const char basesyntax[];
extern const char dqsyntax[];
extern const char sqsyntax[];
extern const char arisyntax[];
extern const char is_type[];
#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

/* 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",
	"{",
	"}"
};




/*	$NetBSD: trap.h,v 1.14 2000/05/22 10:18:47 elric Exp $	*/
extern int pendingsigs;

static int trapcmd __P((int, char **));
static void clear_traps __P((void));
static void setsignal __P((int));
static void ignoresig __P((int));
static void onsig __P((int));
static void dotrap __P((void));
static void setinteractive __P((int));
static void exitshell __P((int)) __attribute__((noreturn));
static int decode_signal __P((const char *, int));



/*	$NetBSD: var.h,v 1.18 2000/05/22 10:18:47 elric Exp $	*/

/*
 * 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) __P((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 */
};


extern struct localvar *localvars;

#if ATTY
extern struct var vatty;
#endif
extern struct var vifs;
extern struct var vmail;
extern struct var vmpath;
extern struct var vpath;
extern struct var vps1;
extern struct var vps2;
#ifndef SMALL
extern struct var vterm;
extern struct var vtermcap;
extern struct var vhistsize;
#endif

#ifdef IFS_BROKEN
extern const char defifsvar[];
#define defifs (defifsvar + 4)
#else
extern const char defifs[];
#endif
extern const char defpathvar[];
#define defpath (defpathvar + 5)

/*
 * 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)
#ifndef SMALL
#define histsizeval()	(vhistsize.text + 9)
#define termval()	(vterm.text + 5)
#endif

#if ATTY
#define attyset()	((vatty.flags & VUNSET) == 0)
#endif
#define mpathset()	((vmpath.flags & VUNSET) == 0)

static void initvar __P((void));
static void setvar __P((const char *, const char *, int));
static void setvareq __P((char *, int));
struct strlist;
static void listsetvar __P((struct strlist *));
static char *lookupvar __P((const char *));
static char *bltinlookup __P((const char *));
static char **environment __P((void));
static void shprocvar __P((void));
static int showvarscmd __P((int, char **));
static int exportcmd __P((int, char **));
static int localcmd __P((int, char **));
static void mklocal __P((char *));
static void poplocalvars __P((void));
static int setvarcmd __P((int, char **));
static int unsetcmd __P((int, char **));
static int unsetvar __P((const char *));
static int varequal __P((const char *, const char *));