hush/ash.h

1226 lines
31 KiB
C
Raw Normal View History

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