xref: /titanic_50/usr/src/cmd/csh/sh.h (revision 6c02b4a4b46fecc2fa6bf1ab6b5e3255ad1d0767)
17c478bd9Sstevel@tonic-gate /*
2*6c02b4a4Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <stdlib.h>	 /* MB_xxx, mbxxx(), wcxxx() etc. */
187c478bd9Sstevel@tonic-gate #include <limits.h>
197c478bd9Sstevel@tonic-gate #include <sys/time.h>
207c478bd9Sstevel@tonic-gate #include <sys/types.h>
217c478bd9Sstevel@tonic-gate #include <sys/siginfo.h>
227c478bd9Sstevel@tonic-gate #include <sys/ucontext.h>
237c478bd9Sstevel@tonic-gate #include <sys/param.h>
247c478bd9Sstevel@tonic-gate #include <sys/stat.h>
257c478bd9Sstevel@tonic-gate #include <sys/termios.h>
267c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
277c478bd9Sstevel@tonic-gate #include <errno.h>
287c478bd9Sstevel@tonic-gate #include <signal.h>	/* std sysV signal.h */
297c478bd9Sstevel@tonic-gate #include <setjmp.h>
307c478bd9Sstevel@tonic-gate #include <sys/resource.h>
317c478bd9Sstevel@tonic-gate #include "signal.h"	/* mainly BSD related signal.h */
327c478bd9Sstevel@tonic-gate #include "sh.local.h"
337c478bd9Sstevel@tonic-gate #include "sh.char.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * MAXHOSTNAMELEN is defined in param.h under SunOS
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate #define	MAXHOSTNAMELEN	64
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #ifdef MBCHAR
417c478bd9Sstevel@tonic-gate # if !defined(MB_LEN_MAX) || !defined(MB_CUR_MAX)
427c478bd9Sstevel@tonic-gate 	Error: I need both ANSI macros!
437c478bd9Sstevel@tonic-gate # endif
447c478bd9Sstevel@tonic-gate #else
457c478bd9Sstevel@tonic-gate # if !defined(MB_LEN_MAX)
467c478bd9Sstevel@tonic-gate #  define MB_LEN_MAX	1
477c478bd9Sstevel@tonic-gate # endif
487c478bd9Sstevel@tonic-gate # if !defined(MB_CUR_MAX)
497c478bd9Sstevel@tonic-gate #  define MB_CUR_MAX	1
507c478bd9Sstevel@tonic-gate # endif
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #ifndef MBCHAR /* Let's replace the ANSI functions with our own macro
547c478bd9Sstevel@tonic-gate 		* for efficiency!
557c478bd9Sstevel@tonic-gate 		*/
567c478bd9Sstevel@tonic-gate #define	mbtowc(pwc, pmb, n_is_ignored)	((*(pwc)=*(pmb)), 1)
577c478bd9Sstevel@tonic-gate #define	wctomb(pmb, wc)			((*(pmb)=((char)wc)), 1)
587c478bd9Sstevel@tonic-gate #endif/*!MBCHAR*/
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * C shell
627c478bd9Sstevel@tonic-gate  *
637c478bd9Sstevel@tonic-gate  * Bill Joy, UC Berkeley
647c478bd9Sstevel@tonic-gate  * October, 1978; May 1980
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  * Jim Kulp, IIASA, Laxenburg Austria
677c478bd9Sstevel@tonic-gate  * April, 1980
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*If we are setting the $cwd variable becuz we did a
717c478bd9Sstevel@tonic-gate   cd, chdir, pushd, popd command, then set didchdir to
727c478bd9Sstevel@tonic-gate   1.  This prevents globbing down when setting $cwd.
737c478bd9Sstevel@tonic-gate   However, if the user set $cwd, we want the globbing
747c478bd9Sstevel@tonic-gate   done; so, didchdir would be equal to 0 in that case.
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate int didchdir;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	isdir(d)	((d.st_mode & S_IFMT) == S_IFDIR)
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate typedef	char	bool;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /* tchar (Tagged CHARacter) is a place holder to keep a QUOTE bit and
837c478bd9Sstevel@tonic-gate  * a character.
847c478bd9Sstevel@tonic-gate  * For European language handling, lower 8 bits of tchar is used
857c478bd9Sstevel@tonic-gate  * to store a character.  For other languages, especially Asian, 16 bits
867c478bd9Sstevel@tonic-gate  * are used to store a character.
877c478bd9Sstevel@tonic-gate  * Following typedef's assume short int is a 16-bit entity and long int is
887c478bd9Sstevel@tonic-gate  * a 32-bit entity.
897c478bd9Sstevel@tonic-gate  * The QUOTE bit tells whether the character is subject to further
907c478bd9Sstevel@tonic-gate  * interpretation such as history substitution, file mathing, command
917c478bd9Sstevel@tonic-gate  * subsitution.  TRIM is a mask to strip off the QUOTE bit.
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate #ifdef MBCHAR		/* For multibyte character handling. */
947c478bd9Sstevel@tonic-gate typedef long int	tchar;
957c478bd9Sstevel@tonic-gate #define QUOTE	0x80000000
967c478bd9Sstevel@tonic-gate #define	TRIM	0x7fffffff
977c478bd9Sstevel@tonic-gate #else/*!MBCHAR*/	/* European language requires only 8 bits. */
987c478bd9Sstevel@tonic-gate typedef unsigned short int	tchar;
997c478bd9Sstevel@tonic-gate #define	QUOTE	0x8000
1007c478bd9Sstevel@tonic-gate #define	TRIM	0x00ff
1017c478bd9Sstevel@tonic-gate #endif/*!MBCHAR*/
1027c478bd9Sstevel@tonic-gate #define	eq(a, b)	(strcmp_(a, b) == 0)
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Global flags
1077c478bd9Sstevel@tonic-gate  */
1087c478bd9Sstevel@tonic-gate bool	chkstop;		/* Warned of stopped jobs... allow exit */
1097c478bd9Sstevel@tonic-gate bool	didfds;			/* Have setup i/o fd's for child */
1107c478bd9Sstevel@tonic-gate bool	doneinp;		/* EOF indicator after reset from readc */
1117c478bd9Sstevel@tonic-gate bool	exiterr;		/* Exit if error or non-zero exit status */
1127c478bd9Sstevel@tonic-gate bool	child;			/* Child shell ... errors cause exit */
1137c478bd9Sstevel@tonic-gate bool	haderr;			/* Reset was because of an error */
1147c478bd9Sstevel@tonic-gate bool	intty;			/* Input is a tty */
1157c478bd9Sstevel@tonic-gate bool	cflg;			/* invoked with -c option */
1167c478bd9Sstevel@tonic-gate bool	intact;			/* We are interactive... therefore prompt */
1177c478bd9Sstevel@tonic-gate bool	justpr;			/* Just print because of :p hist mod */
1187c478bd9Sstevel@tonic-gate bool	loginsh;		/* We are a loginsh -> .login/.logout */
1197c478bd9Sstevel@tonic-gate bool	neednote;		/* Need to pnotify() */
1207c478bd9Sstevel@tonic-gate bool	noexec;			/* Don't execute, just syntax check */
1217c478bd9Sstevel@tonic-gate bool	pjobs;			/* want to print jobs if interrupted */
1227c478bd9Sstevel@tonic-gate bool	pfcshflag;		/* set to 0 for pfcsh */
1237c478bd9Sstevel@tonic-gate bool	setintr;		/* Set interrupts on/off -> Wait intr... */
1247c478bd9Sstevel@tonic-gate bool	timflg;			/* Time the next waited for command */
1257c478bd9Sstevel@tonic-gate bool	havhash;		/* path hashing is available */
1267c478bd9Sstevel@tonic-gate bool	havhash2;		/* cdpath hashing is available */
1277c478bd9Sstevel@tonic-gate #ifdef FILEC
1287c478bd9Sstevel@tonic-gate bool	filec;			/* doing filename expansion */
1297c478bd9Sstevel@tonic-gate #endif
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * Global i/o info
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate tchar	*arginp;		/* Argument input for sh -c and internal `xx` */
1357c478bd9Sstevel@tonic-gate int	onelflg;		/* 2 -> need line for -t, 1 -> exit on read */
1367c478bd9Sstevel@tonic-gate tchar	*file;			/* Name of shell file for $0 */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate char	*err;			/* Error message from scanner/parser */
1397c478bd9Sstevel@tonic-gate struct	timeval time0;		/* Time at which the shell started */
1407c478bd9Sstevel@tonic-gate struct	rusage ru0;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate  * Miscellany
1447c478bd9Sstevel@tonic-gate  */
1457c478bd9Sstevel@tonic-gate tchar	*doldol;		/* Character pid for $$ */
1467c478bd9Sstevel@tonic-gate int	uid;			/* Invokers uid */
1477c478bd9Sstevel@tonic-gate time_t	chktim;			/* Time mail last checked */
1487c478bd9Sstevel@tonic-gate int	shpgrp;			/* Pgrp of shell */
1497c478bd9Sstevel@tonic-gate int	tpgrp;			/* Terminal process group */
1507c478bd9Sstevel@tonic-gate /* If tpgrp is -1, leave tty alone! */
1517c478bd9Sstevel@tonic-gate int	opgrp;			/* Initial pgrp and tty pgrp */
1527c478bd9Sstevel@tonic-gate int	oldisc;			/* Initial line discipline or -1 */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate  * These are declared here because they want to be
1567c478bd9Sstevel@tonic-gate  * initialized in sh.init.c (to allow them to be made readonly)
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate extern struct	biltins {
1607c478bd9Sstevel@tonic-gate 	tchar	*bname;
1617c478bd9Sstevel@tonic-gate 	int	(*bfunct)();
1627c478bd9Sstevel@tonic-gate 	short	minargs, maxargs;
1637c478bd9Sstevel@tonic-gate } bfunc[];
1647c478bd9Sstevel@tonic-gate extern int nbfunc;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate extern struct srch {
1677c478bd9Sstevel@tonic-gate 	tchar	*s_name;
1687c478bd9Sstevel@tonic-gate 	short	s_value;
1697c478bd9Sstevel@tonic-gate } srchn[];
1707c478bd9Sstevel@tonic-gate extern int nsrchn;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * To be able to redirect i/o for builtins easily, the shell moves the i/o
1747c478bd9Sstevel@tonic-gate  * descriptors it uses away from 0,1,2.
1757c478bd9Sstevel@tonic-gate  * Ideally these should be in units which are closed across exec's
1767c478bd9Sstevel@tonic-gate  * (this saves work) but for version 6, this is not usually possible.
1777c478bd9Sstevel@tonic-gate  * The desired initial values for these descriptors are defined in
1787c478bd9Sstevel@tonic-gate  * sh.local.h.
1797c478bd9Sstevel@tonic-gate  */
1807c478bd9Sstevel@tonic-gate short	SHIN;			/* Current shell input (script) */
1817c478bd9Sstevel@tonic-gate short	SHOUT;			/* Shell output */
1827c478bd9Sstevel@tonic-gate short	SHDIAG;			/* Diagnostic output... shell errs go here */
1837c478bd9Sstevel@tonic-gate short	OLDSTD;			/* Old standard input (def for cmds) */
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * Error control
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  * Errors in scanning and parsing set up an error message to be printed
1897c478bd9Sstevel@tonic-gate  * at the end and complete.  Other errors always cause a reset.
1907c478bd9Sstevel@tonic-gate  * Because of source commands and .cshrc we need nested error catches.
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate jmp_buf	reslab;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate #define	setexit()	((void) setjmp(reslab))
1967c478bd9Sstevel@tonic-gate #define	reset()		longjmp(reslab, 0)
1977c478bd9Sstevel@tonic-gate 	/* Should use structure assignment here */
1987c478bd9Sstevel@tonic-gate #define	getexit(a)	copy((void *)(a), (void *)reslab, sizeof reslab)
1997c478bd9Sstevel@tonic-gate #define	resexit(a)	copy((void *)reslab, ((void *)(a)), sizeof reslab)
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate tchar	*gointr;		/* Label for an onintr transfer */
2027c478bd9Sstevel@tonic-gate void	(*parintr)();		/* Parents interrupt catch */
2037c478bd9Sstevel@tonic-gate void	(*parterm)();		/* Parents terminate catch */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * Each level of input has a buffered input structure.
2087c478bd9Sstevel@tonic-gate  * There are one or more blocks of buffered input for each level,
2097c478bd9Sstevel@tonic-gate  * exactly one if the input is seekable and tell is available.
2107c478bd9Sstevel@tonic-gate  * In other cases, the shell buffers enough blocks to keep all loops
2117c478bd9Sstevel@tonic-gate  * in the buffer.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate struct	Bin {
2147c478bd9Sstevel@tonic-gate 	off_t	Bfseekp;		/* Seek pointer */
2157c478bd9Sstevel@tonic-gate 	off_t	Bfbobp;			/* Seekp of beginning of buffers */
2167c478bd9Sstevel@tonic-gate 	off_t	Bfeobp;			/* Seekp of end of buffers */
2177c478bd9Sstevel@tonic-gate 	short	Bfblocks;		/* Number of buffer blocks */
2187c478bd9Sstevel@tonic-gate 	tchar	**Bfbuf;		/* The array of buffer blocks */
2197c478bd9Sstevel@tonic-gate } B;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #define	fseekp	B.Bfseekp
2227c478bd9Sstevel@tonic-gate #define	fbobp	B.Bfbobp
2237c478bd9Sstevel@tonic-gate #define	feobp	B.Bfeobp
2247c478bd9Sstevel@tonic-gate #define	fblocks	B.Bfblocks
2257c478bd9Sstevel@tonic-gate #define	fbuf	B.Bfbuf
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate #define btell()	fseekp
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate #ifndef btell
230*6c02b4a4Smuffin off_t	btell(void);
2317c478bd9Sstevel@tonic-gate #endif
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate  * The shell finds commands in loops by reseeking the input
2357c478bd9Sstevel@tonic-gate  * For whiles, in particular, it reseeks to the beginning of the
2367c478bd9Sstevel@tonic-gate  * line the while was on; hence the while placement restrictions.
2377c478bd9Sstevel@tonic-gate  */
2387c478bd9Sstevel@tonic-gate off_t	lineloc;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate #ifdef	TELL
2417c478bd9Sstevel@tonic-gate bool	cantell;			/* Is current source tellable ? */
2427c478bd9Sstevel@tonic-gate #endif
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * Input lines are parsed into doubly linked circular
2467c478bd9Sstevel@tonic-gate  * lists of words of the following form.
2477c478bd9Sstevel@tonic-gate  */
2487c478bd9Sstevel@tonic-gate struct	wordent {
2497c478bd9Sstevel@tonic-gate 	tchar	*word;
2507c478bd9Sstevel@tonic-gate 	struct	wordent *prev;
2517c478bd9Sstevel@tonic-gate 	struct	wordent *next;
2527c478bd9Sstevel@tonic-gate };
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate  * During word building, both in the initial lexical phase and
2567c478bd9Sstevel@tonic-gate  * when expanding $ variable substitutions, expansion by `!' and `$'
2577c478bd9Sstevel@tonic-gate  * must be inhibited when reading ahead in routines which are themselves
2587c478bd9Sstevel@tonic-gate  * processing `!' and `$' expansion or after characters such as `\' or in
2597c478bd9Sstevel@tonic-gate  * quotations.  The following flags are passed to the getC routines
2607c478bd9Sstevel@tonic-gate  * telling them which of these substitutions are appropriate for the
2617c478bd9Sstevel@tonic-gate  * next character to be returned.
2627c478bd9Sstevel@tonic-gate  */
2637c478bd9Sstevel@tonic-gate #define	DODOL	1
2647c478bd9Sstevel@tonic-gate #define	DOEXCL	2
2657c478bd9Sstevel@tonic-gate #define	DOALL	DODOL|DOEXCL
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate  * Labuf implements a general buffer for lookahead during lexical operations.
2697c478bd9Sstevel@tonic-gate  * Text which is to be placed in the input stream can be stuck here.
2707c478bd9Sstevel@tonic-gate  * We stick parsed ahead $ constructs during initial input,
2717c478bd9Sstevel@tonic-gate  * process id's from `$$', and modified variable values (from qualifiers
2727c478bd9Sstevel@tonic-gate  * during expansion in sh.dol.c) here.
2737c478bd9Sstevel@tonic-gate  */
2747c478bd9Sstevel@tonic-gate tchar	*labuf;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate tchar	*lap;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate  * Parser structure
2807c478bd9Sstevel@tonic-gate  *
2817c478bd9Sstevel@tonic-gate  * Each command is parsed to a tree of command structures and
2827c478bd9Sstevel@tonic-gate  * flags are set bottom up during this process, to be propagated down
2837c478bd9Sstevel@tonic-gate  * as needed during the semantics/exeuction pass (sh.sem.c).
2847c478bd9Sstevel@tonic-gate  */
2857c478bd9Sstevel@tonic-gate struct	command {
2867c478bd9Sstevel@tonic-gate 	short	t_dtyp;				/* Type of node */
2877c478bd9Sstevel@tonic-gate 	short	t_dflg;				/* Flags, e.g. FAND|... */
2887c478bd9Sstevel@tonic-gate 	union {
2897c478bd9Sstevel@tonic-gate 		tchar	*T_dlef;		/* Input redirect word */
2907c478bd9Sstevel@tonic-gate 		struct	command *T_dcar;	/* Left part of list/pipe */
2917c478bd9Sstevel@tonic-gate 	} L;
2927c478bd9Sstevel@tonic-gate 	union {
2937c478bd9Sstevel@tonic-gate 		tchar	*T_drit;		/* Output redirect word */
2947c478bd9Sstevel@tonic-gate 		struct	command *T_dcdr;	/* Right part of list/pipe */
2957c478bd9Sstevel@tonic-gate 	} R;
2967c478bd9Sstevel@tonic-gate #define	t_dlef	L.T_dlef
2977c478bd9Sstevel@tonic-gate #define	t_dcar	L.T_dcar
2987c478bd9Sstevel@tonic-gate #define	t_drit	R.T_drit
2997c478bd9Sstevel@tonic-gate #define	t_dcdr	R.T_dcdr
3007c478bd9Sstevel@tonic-gate 	tchar	**t_dcom;			/* Command/argument vector */
3017c478bd9Sstevel@tonic-gate 	char	*cfname;			/* char pathname for execv */
3027c478bd9Sstevel@tonic-gate 	char	**cargs;			/* char arg vec  for execv */
3037c478bd9Sstevel@tonic-gate 	struct	command *t_dspr;		/* Pointer to ()'d subtree */
3047c478bd9Sstevel@tonic-gate 	short	t_nice;
3057c478bd9Sstevel@tonic-gate };
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate #define	TCOM	1		/* t_dcom <t_dlef >t_drit	*/
3087c478bd9Sstevel@tonic-gate #define	TPAR	2		/* ( t_dspr ) <t_dlef >t_drit	*/
3097c478bd9Sstevel@tonic-gate #define	TFIL	3		/* t_dlef | t_drit		*/
3107c478bd9Sstevel@tonic-gate #define	TLST	4		/* t_dlef ; t_drit		*/
3117c478bd9Sstevel@tonic-gate #define	TOR	5		/* t_dlef || t_drit		*/
3127c478bd9Sstevel@tonic-gate #define	TAND	6		/* t_dlef && t_drit		*/
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate #define	FSAVE	(FNICE|FTIME|FNOHUP)	/* save these when re-doing */
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate #define	FAND	(1<<0)		/* executes in background	*/
3177c478bd9Sstevel@tonic-gate #define	FCAT	(1<<1)		/* output is redirected >>	*/
3187c478bd9Sstevel@tonic-gate #define	FPIN	(1<<2)		/* input is a pipe		*/
3197c478bd9Sstevel@tonic-gate #define	FPOU	(1<<3)		/* output is a pipe		*/
3207c478bd9Sstevel@tonic-gate #define	FPAR	(1<<4)		/* don't fork, last ()ized cmd	*/
3217c478bd9Sstevel@tonic-gate #define	FINT	(1<<5)		/* should be immune from intr's */
3227c478bd9Sstevel@tonic-gate /* spare */
3237c478bd9Sstevel@tonic-gate #define	FDIAG	(1<<7)		/* redirect unit 2 with unit 1	*/
3247c478bd9Sstevel@tonic-gate #define	FANY	(1<<8)		/* output was !			*/
3257c478bd9Sstevel@tonic-gate #define	FHERE	(1<<9)		/* input redirection is <<	*/
3267c478bd9Sstevel@tonic-gate #define	FREDO	(1<<10)		/* reexec aft if, repeat,...	*/
3277c478bd9Sstevel@tonic-gate #define	FNICE	(1<<11)		/* t_nice is meaningful */
3287c478bd9Sstevel@tonic-gate #define	FNOHUP	(1<<12)		/* nohup this command */
3297c478bd9Sstevel@tonic-gate #define	FTIME	(1<<13)		/* time this command */
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate  * The keywords for the parser
3337c478bd9Sstevel@tonic-gate  */
3347c478bd9Sstevel@tonic-gate #define	ZBREAK		0
3357c478bd9Sstevel@tonic-gate #define	ZBRKSW		1
3367c478bd9Sstevel@tonic-gate #define	ZCASE		2
3377c478bd9Sstevel@tonic-gate #define	ZDEFAULT 	3
3387c478bd9Sstevel@tonic-gate #define	ZELSE		4
3397c478bd9Sstevel@tonic-gate #define	ZEND		5
3407c478bd9Sstevel@tonic-gate #define	ZENDIF		6
3417c478bd9Sstevel@tonic-gate #define	ZENDSW		7
3427c478bd9Sstevel@tonic-gate #define	ZEXIT		8
3437c478bd9Sstevel@tonic-gate #define	ZFOREACH	9
3447c478bd9Sstevel@tonic-gate #define	ZGOTO		10
3457c478bd9Sstevel@tonic-gate #define	ZIF		11
3467c478bd9Sstevel@tonic-gate #define	ZLABEL		12
3477c478bd9Sstevel@tonic-gate #define	ZLET		13
3487c478bd9Sstevel@tonic-gate #define	ZSET		14
3497c478bd9Sstevel@tonic-gate #define	ZSWITCH		15
3507c478bd9Sstevel@tonic-gate #define	ZTEST		16
3517c478bd9Sstevel@tonic-gate #define	ZTHEN		17
3527c478bd9Sstevel@tonic-gate #define	ZWHILE		18
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate  * Structure defining the existing while/foreach loops at this
3567c478bd9Sstevel@tonic-gate  * source level.  Loops are implemented by seeking back in the
3577c478bd9Sstevel@tonic-gate  * input.  For foreach (fe), the word list is attached here.
3587c478bd9Sstevel@tonic-gate  */
3597c478bd9Sstevel@tonic-gate struct	whyle {
3607c478bd9Sstevel@tonic-gate 	off_t	w_start;		/* Point to restart loop */
3617c478bd9Sstevel@tonic-gate 	off_t	w_end;			/* End of loop (0 if unknown) */
3627c478bd9Sstevel@tonic-gate 	tchar	**w_fe, **w_fe0;	/* Current/initial wordlist for fe */
3637c478bd9Sstevel@tonic-gate 	tchar	*w_fename;		/* Name for fe */
3647c478bd9Sstevel@tonic-gate 	struct	whyle *w_next;		/* Next (more outer) loop */
3657c478bd9Sstevel@tonic-gate } *whyles;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * Variable structure
3697c478bd9Sstevel@tonic-gate  *
3707c478bd9Sstevel@tonic-gate  * Aliases and variables are stored in AVL balanced binary trees.
3717c478bd9Sstevel@tonic-gate  */
3727c478bd9Sstevel@tonic-gate struct	varent {
3737c478bd9Sstevel@tonic-gate 	tchar	**vec;		/* Array of words which is the value */
3747c478bd9Sstevel@tonic-gate 	tchar	*v_name;	/* Name of variable/alias */
3757c478bd9Sstevel@tonic-gate 	struct	varent *v_link[3];	/* The links, see below */
3767c478bd9Sstevel@tonic-gate 	int	v_bal;		/* Balance factor */
3777c478bd9Sstevel@tonic-gate } shvhed, aliases;
3787c478bd9Sstevel@tonic-gate #define v_left		v_link[0]
3797c478bd9Sstevel@tonic-gate #define v_right		v_link[1]
3807c478bd9Sstevel@tonic-gate #define v_parent	v_link[2]
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate struct varent *adrof1();
3837c478bd9Sstevel@tonic-gate #define adrof(v)	adrof1(v, &shvhed)
3847c478bd9Sstevel@tonic-gate #define value(v)	value1(v, &shvhed)
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * MAX_VAR_LEN - maximum variable name defined by csh man page to be 20
3887c478bd9Sstevel@tonic-gate  */
3897c478bd9Sstevel@tonic-gate #define MAX_VAR_LEN           20
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate  * MAX_VREF_LEN - maximum variable reference $name[...]
3937c478bd9Sstevel@tonic-gate  * it can be as big as a csh word, which is 1024
3947c478bd9Sstevel@tonic-gate  */
3957c478bd9Sstevel@tonic-gate #define MAX_VREF_LEN  1024
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate /*
3997c478bd9Sstevel@tonic-gate  * The following are for interfacing redo substitution in
4007c478bd9Sstevel@tonic-gate  * aliases to the lexical routines.
4017c478bd9Sstevel@tonic-gate  */
4027c478bd9Sstevel@tonic-gate struct	wordent *alhistp;		/* Argument list (first) */
4037c478bd9Sstevel@tonic-gate struct	wordent *alhistt;		/* Node after last in arg list */
4047c478bd9Sstevel@tonic-gate tchar	**alvec;			/* The (remnants of) alias vector */
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate  * Filename/command name expansion variables
4087c478bd9Sstevel@tonic-gate  */
4097c478bd9Sstevel@tonic-gate short	gflag;				/* After tglob -> is globbing needed? */
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate  * A reasonable limit on number of arguments would seem to be
4137c478bd9Sstevel@tonic-gate  * the maximum number of characters in an arg list / 6.
4147c478bd9Sstevel@tonic-gate  *
4157c478bd9Sstevel@tonic-gate  * XXX:	With the new VM system, NCARGS has become enormous, making
4167c478bd9Sstevel@tonic-gate  *	it impractical to allocate arrays with NCARGS / 6 entries on
4177c478bd9Sstevel@tonic-gate  *	the stack.  The proper fix is to revamp code elsewhere (in
4187c478bd9Sstevel@tonic-gate  *	sh.dol.c and sh.glob.c) to use a different technique for handling
4197c478bd9Sstevel@tonic-gate  *	command line arguments.  In the meantime, we simply fall back
4207c478bd9Sstevel@tonic-gate  *	on using the old value of NCARGS.
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate #ifdef	notyet
4237c478bd9Sstevel@tonic-gate #define	GAVSIZ	(NCARGS / 6)
424*6c02b4a4Smuffin #else	/* notyet */
4257c478bd9Sstevel@tonic-gate #define	GAVSIZ	(10240 / 6)
426*6c02b4a4Smuffin #endif	/* notyet */
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate /*
4297c478bd9Sstevel@tonic-gate  * Variables for filename expansion
4307c478bd9Sstevel@tonic-gate  */
4317c478bd9Sstevel@tonic-gate tchar	**gargv;			/* Pointer to the (stack) arglist */
4327c478bd9Sstevel@tonic-gate long	gargc;				/* Number args in gargv */
4337c478bd9Sstevel@tonic-gate long	gnleft;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate  * Variables for command expansion.
4377c478bd9Sstevel@tonic-gate  */
4387c478bd9Sstevel@tonic-gate tchar	**pargv;			/* Pointer to the argv list space */
4397c478bd9Sstevel@tonic-gate tchar	*pargs;				/* Pointer to start current word */
4407c478bd9Sstevel@tonic-gate long	pargc;				/* Count of arguments in pargv */
4417c478bd9Sstevel@tonic-gate long	pnleft;				/* Number of chars left in pargs */
4427c478bd9Sstevel@tonic-gate tchar	*pargcp;			/* Current index into pargs */
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate  * History list
4467c478bd9Sstevel@tonic-gate  *
4477c478bd9Sstevel@tonic-gate  * Each history list entry contains an embedded wordlist
4487c478bd9Sstevel@tonic-gate  * from the scanner, a number for the event, and a reference count
4497c478bd9Sstevel@tonic-gate  * to aid in discarding old entries.
4507c478bd9Sstevel@tonic-gate  *
4517c478bd9Sstevel@tonic-gate  * Essentially "invisible" entries are put on the history list
4527c478bd9Sstevel@tonic-gate  * when history substitution includes modifiers, and thrown away
4537c478bd9Sstevel@tonic-gate  * at the next discarding since their event numbers are very negative.
4547c478bd9Sstevel@tonic-gate  */
4557c478bd9Sstevel@tonic-gate struct	Hist {
4567c478bd9Sstevel@tonic-gate 	struct	wordent Hlex;
4577c478bd9Sstevel@tonic-gate 	int	Hnum;
4587c478bd9Sstevel@tonic-gate 	int	Href;
4597c478bd9Sstevel@tonic-gate 	struct	Hist *Hnext;
4607c478bd9Sstevel@tonic-gate } Histlist;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate struct	wordent	paraml;			/* Current lexical word list */
4637c478bd9Sstevel@tonic-gate int	eventno;			/* Next events number */
4647c478bd9Sstevel@tonic-gate int	lastev;				/* Last event reference (default) */
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate tchar	HIST;				/* history invocation character */
4677c478bd9Sstevel@tonic-gate tchar	HISTSUB;			/* auto-substitute character */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate  * In lines for frequently called functions
4717c478bd9Sstevel@tonic-gate  *
4727c478bd9Sstevel@tonic-gate  * WARNING: changes here also need to occur in the xfree() function in
4737c478bd9Sstevel@tonic-gate  *	    sh.misc.c.
4747c478bd9Sstevel@tonic-gate  */
4757c478bd9Sstevel@tonic-gate #if defined(sparc)
4767c478bd9Sstevel@tonic-gate #define XFREE(cp) { \
4777c478bd9Sstevel@tonic-gate 	extern char end[]; \
4787c478bd9Sstevel@tonic-gate 	char stack; \
4797c478bd9Sstevel@tonic-gate /*??*/	if (((char *)(cp)) >= end && ((char *)(cp)) < &stack) \
4807c478bd9Sstevel@tonic-gate /*??*/		free((void *)(cp)); \
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate #elif defined(i386)
4837c478bd9Sstevel@tonic-gate #define XFREE(cp) { \
4847c478bd9Sstevel@tonic-gate 	extern char end[]; \
4857c478bd9Sstevel@tonic-gate 	if (((char *)(cp)) >= end) \
4867c478bd9Sstevel@tonic-gate 		free((void *)(cp)); \
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate #else
4897c478bd9Sstevel@tonic-gate #error XFREE macro is machine dependant and no machine type is recognized
4907c478bd9Sstevel@tonic-gate #endif
4917c478bd9Sstevel@tonic-gate void	*alloctmp;
4927c478bd9Sstevel@tonic-gate #define xalloc(i) ((alloctmp = (void *)malloc(i)) ? alloctmp : (void *)nomem(i))/*??*/
4937c478bd9Sstevel@tonic-gate #define	xrealloc(buf, i) ((alloctmp = (void *)realloc(buf, i)) ? alloctmp : \
4947c478bd9Sstevel@tonic-gate 				(void *)nomem(i))
495*6c02b4a4Smuffin extern void	Putchar(tchar);
496*6c02b4a4Smuffin extern void	bferr(char *)	__NORETURN;
497*6c02b4a4Smuffin extern void	error()	__NORETURN;
498*6c02b4a4Smuffin extern void	exitstat(void)	__NORETURN;
499*6c02b4a4Smuffin extern tchar	*Dfix1(tchar *);
500*6c02b4a4Smuffin extern tchar	**blkcpy(tchar **, tchar **);
501*6c02b4a4Smuffin extern tchar	**blkspl(tchar **, tchar **);
502*6c02b4a4Smuffin extern char	**blkspl_(char **, char **);
503*6c02b4a4Smuffin extern tchar	**copyblk(tchar **);
504*6c02b4a4Smuffin extern tchar	**dobackp(tchar *, bool);
505*6c02b4a4Smuffin extern tchar	*domod(tchar *, int);
506*6c02b4a4Smuffin extern struct	Hist *enthist(int, struct wordent *, bool);
507*6c02b4a4Smuffin extern tchar	*getenv_(tchar *);
508*6c02b4a4Smuffin extern tchar	*getenvs_(char *);
509*6c02b4a4Smuffin extern tchar	*getwd_(tchar *);
510*6c02b4a4Smuffin extern tchar	**glob(tchar **);
511*6c02b4a4Smuffin extern tchar	*globone(tchar *);
512*6c02b4a4Smuffin extern tchar	*index_(tchar *, tchar);
513*6c02b4a4Smuffin extern struct biltins	*isbfunc(struct command *);
514*6c02b4a4Smuffin extern void	pintr(void);
515*6c02b4a4Smuffin extern void	pchild(void);
516*6c02b4a4Smuffin extern tchar	*putn(int);
517*6c02b4a4Smuffin extern tchar	*rindex_(tchar *, tchar);
518*6c02b4a4Smuffin extern tchar	**saveblk(tchar **);
519*6c02b4a4Smuffin extern tchar	*savestr(tchar *);
520*6c02b4a4Smuffin extern tchar	*strcat_(tchar *, tchar *);
521*6c02b4a4Smuffin extern int	strlen_(tchar *);
522*6c02b4a4Smuffin extern tchar	*strcpy_(tchar *, tchar *);
523*6c02b4a4Smuffin extern tchar	*strend(tchar *);
524*6c02b4a4Smuffin extern tchar	*strip(tchar *);
525*6c02b4a4Smuffin extern tchar	*strspl(tchar *, tchar *);
526*6c02b4a4Smuffin extern struct command	*syntax(struct wordent *, struct wordent *, int);
527*6c02b4a4Smuffin extern tchar	*value1(tchar *, struct varent *);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate #define	NOSTR	((tchar *) 0)
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate  * setname is a macro to copy the path in bname. (see sh.err.c)
5337c478bd9Sstevel@tonic-gate  * Here we are dynamically reallocating the bname to the new length
5347c478bd9Sstevel@tonic-gate  * to store the new path
5357c478bd9Sstevel@tonic-gate  */
5367c478bd9Sstevel@tonic-gate tchar	*bname;
5377c478bd9Sstevel@tonic-gate #define	setname(a)	 { \
5387c478bd9Sstevel@tonic-gate 	bname = xrealloc(bname, (strlen_(a)+1) * sizeof (tchar)); \
5397c478bd9Sstevel@tonic-gate 	strcpy_(bname, a); \
5407c478bd9Sstevel@tonic-gate 	bname[strlen_(a)] = '\0'; \
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate #ifdef VFORK
5447c478bd9Sstevel@tonic-gate tchar	*Vsav;
5457c478bd9Sstevel@tonic-gate tchar	**Vav;
5467c478bd9Sstevel@tonic-gate tchar	*Vdp;
5477c478bd9Sstevel@tonic-gate #endif
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate tchar	**evalvec;
5507c478bd9Sstevel@tonic-gate tchar	*evalp;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate /* Conversion functions between char and tchar strings. */
5537c478bd9Sstevel@tonic-gate tchar	*strtots(/* tchar * , char * */);
5547c478bd9Sstevel@tonic-gate char	*tstostr(/* char *  , tchar * */);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate #ifndef NULL
5577c478bd9Sstevel@tonic-gate #define	NULL	0
5587c478bd9Sstevel@tonic-gate #endif
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate /*
5627c478bd9Sstevel@tonic-gate  * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
5637c478bd9Sstevel@tonic-gate  * to hash execs.  If it is allocated (havhash true), then to tell
5647c478bd9Sstevel@tonic-gate  * whether ``name'' is (possibly) present in the i'th component
5657c478bd9Sstevel@tonic-gate  * of the variable path, you look at the bit in xhash indexed by
5667c478bd9Sstevel@tonic-gate  * hash(hashname("name"), i).  This is setup automatically
5677c478bd9Sstevel@tonic-gate  * after .login is executed, and recomputed whenever ``path'' is
5687c478bd9Sstevel@tonic-gate  * changed.
5697c478bd9Sstevel@tonic-gate  * The two part hash function is designed to let texec() call the
5707c478bd9Sstevel@tonic-gate  * more expensive hashname() only once and the simple hash() several
5717c478bd9Sstevel@tonic-gate  * times (once for each path component checked).
5727c478bd9Sstevel@tonic-gate  * Byte size is assumed to be 8.
5737c478bd9Sstevel@tonic-gate  */
5747c478bd9Sstevel@tonic-gate #define HSHSIZ          (32*1024)       /* 4k bytes */
5757c478bd9Sstevel@tonic-gate #define HSHMASK         (HSHSIZ - 1)
5767c478bd9Sstevel@tonic-gate #define HSHMUL          243
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate /*
5797c478bd9Sstevel@tonic-gate  * The following two arrays are used for caching.  xhash
5807c478bd9Sstevel@tonic-gate  * is for caching path variable and xhash2 is for cdpath
5817c478bd9Sstevel@tonic-gate  * variable.
5827c478bd9Sstevel@tonic-gate  */
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate char xhash[HSHSIZ / 8];
5857c478bd9Sstevel@tonic-gate char xhash2[HSHSIZ / 8];
5867c478bd9Sstevel@tonic-gate #define hash(a, b)      ((a) * HSHMUL + (b) & HSHMASK)
5877c478bd9Sstevel@tonic-gate #define bit(h, b)       ((h)[(b) >> 3] & 1 << ((b) & 7))        /* bit test */
5887c478bd9Sstevel@tonic-gate #define bis(h, b)       ((h)[(b) >> 3] |= 1 << ((b) & 7))       /* bit set */
5897c478bd9Sstevel@tonic-gate #ifdef VFORK
5907c478bd9Sstevel@tonic-gate int     hits, misses;
5917c478bd9Sstevel@tonic-gate #endif
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 
594