xref: /openbsd-src/bin/ksh/sh.h (revision abe762909b634ba7ba5f0581239afbd78014160a)
1*abe76290Smillert /*	$OpenBSD: sh.h,v 1.77 2023/06/21 22:22:08 millert Exp $	*/
27cb960a2Sdownsj 
37cb960a2Sdownsj /*
47cb960a2Sdownsj  * Public Domain Bourne/Korn shell
57cb960a2Sdownsj  */
67cb960a2Sdownsj 
77cb960a2Sdownsj /* $From: sh.h,v 1.2 1994/05/19 18:32:40 michael Exp michael $ */
87cb960a2Sdownsj 
97cb960a2Sdownsj #include "config.h"	/* system and option configuration info */
107cb960a2Sdownsj 
117cb960a2Sdownsj /* Start of common headers */
127cb960a2Sdownsj 
132b1380e7Sjca #include <limits.h>
147cb960a2Sdownsj #include <setjmp.h>
157cb960a2Sdownsj #include <stdarg.h>
164c503bcdSmillert #include <stddef.h>
177cb960a2Sdownsj #include <signal.h>
184a010e0cStb #include <stdbool.h>
1969b9f96bSmillert 
207cb960a2Sdownsj /* end of common headers */
217cb960a2Sdownsj 
227cb960a2Sdownsj #define	NELEM(a) (sizeof(a) / sizeof((a)[0]))
237cb960a2Sdownsj #define	BIT(i)	(1<<(i))	/* define bit in flag */
247cb960a2Sdownsj 
25c3e29789Sniklas #define	NUFILE	32		/* Number of user-accessible files */
267cb960a2Sdownsj #define	FDBASE	10		/* First file usable by Shell */
277cb960a2Sdownsj 
28fe47dfe3Snicm #define BITS(t)	(CHAR_BIT * sizeof(t))
29fe47dfe3Snicm 
307cb960a2Sdownsj /* Make MAGIC a char that might be printed to make bugs more obvious, but
317cb960a2Sdownsj  * not a char that is used often.  Also, can't use the high bit as it causes
327cb960a2Sdownsj  * portability problems (calling strchr(x, 0x80|'x') is error prone).
337cb960a2Sdownsj  */
347cb960a2Sdownsj #define	MAGIC		(7)	/* prefix for *?[!{,} during expand */
357cb960a2Sdownsj #define ISMAGIC(c)	((unsigned char)(c) == MAGIC)
367cb960a2Sdownsj 
3738bcb596Smartijn #define	LINE	4096		/* input line size */
387cb960a2Sdownsj 
39772a9c36Smmcc extern	const char *kshname;	/* $0 */
40772a9c36Smmcc extern	pid_t	kshpid;		/* $$, shell pid */
41772a9c36Smmcc extern	pid_t	procpid;	/* pid of executing process */
42772a9c36Smmcc extern	uid_t	ksheuid;	/* effective uid of shell */
43772a9c36Smmcc extern	int	exstat;		/* exit status */
44772a9c36Smmcc extern	int	subst_exstat;	/* exit status of last $(..)/`..` */
45772a9c36Smmcc extern	const char *safe_prompt; /* safe prompt if PS1 substitution fails */
46772a9c36Smmcc extern	char	username[];	/* username for \u prompt expansion */
470ac57757Sschwarze extern	int	disable_subst;	/* disable substitution during evaluation */
487cb960a2Sdownsj 
497cb960a2Sdownsj /*
507cb960a2Sdownsj  * Area-based allocation built on malloc/free
517cb960a2Sdownsj  */
527cb960a2Sdownsj typedef struct Area {
53b57c16d2Sespie 	struct link *freelist;	/* free list */
547cb960a2Sdownsj } Area;
557cb960a2Sdownsj 
56fa9dffc6Smmcc extern	Area	aperm;		/* permanent object space */
577cb960a2Sdownsj #define	APERM	&aperm
585ae5b57eStedu #define	ATEMP	&genv->area
597cb960a2Sdownsj 
60945abdecSmillert #ifdef KSH_DEBUG
61945abdecSmillert # define kshdebug_init()	kshdebug_init_()
62945abdecSmillert # define kshdebug_printf(a)	kshdebug_printf_ a
63945abdecSmillert # define kshdebug_dump(a)	kshdebug_dump_ a
64945abdecSmillert #else /* KSH_DEBUG */
65945abdecSmillert # define kshdebug_init()
66945abdecSmillert # define kshdebug_printf(a)
67945abdecSmillert # define kshdebug_dump(a)
68945abdecSmillert #endif /* KSH_DEBUG */
69945abdecSmillert 
707cb960a2Sdownsj /*
717cb960a2Sdownsj  * parsing & execution environment
727cb960a2Sdownsj  */
73fa9dffc6Smmcc struct env {
7446f8e29aSmillert 	short	type;			/* environment type - see below */
757cb960a2Sdownsj 	short	flags;			/* EF_* */
767cb960a2Sdownsj 	Area	area;			/* temporary allocation area */
777cb960a2Sdownsj 	struct	block *loc;		/* local variables and functions */
787cb960a2Sdownsj 	short  *savefd;			/* original redirected fd's */
7946f8e29aSmillert 	struct	env *oenv;		/* link to previous environment */
8069b9f96bSmillert 	sigjmp_buf jbuf;		/* long jump back to env creator */
817cb960a2Sdownsj 	struct temp *temps;		/* temp files */
82fa9dffc6Smmcc };
835ae5b57eStedu extern	struct env	*genv;
847cb960a2Sdownsj 
857cb960a2Sdownsj /* struct env.type values */
8646f8e29aSmillert #define	E_NONE	0		/* dummy environment */
877cb960a2Sdownsj #define	E_PARSE	1		/* parsing command # */
887cb960a2Sdownsj #define	E_FUNC	2		/* executing function # */
897cb960a2Sdownsj #define	E_INCL	3		/* including a file via . # */
907cb960a2Sdownsj #define	E_EXEC	4		/* executing command tree */
917cb960a2Sdownsj #define	E_LOOP	5		/* executing for/while # */
927cb960a2Sdownsj #define	E_ERRH	6		/* general error handler # */
937cb960a2Sdownsj /* # indicates env has valid jbuf (see unwind()) */
947cb960a2Sdownsj 
957cb960a2Sdownsj /* struct env.flag values */
967cb960a2Sdownsj #define EF_FUNC_PARSE	BIT(0)	/* function being parsed */
977cb960a2Sdownsj #define EF_BRKCONT_PASS	BIT(1)	/* set if E_LOOP must pass break/continue on */
98f00c5086Smillert #define EF_FAKE_SIGDIE	BIT(2)	/* hack to get info from unwind to quitenv */
997cb960a2Sdownsj 
1007cb960a2Sdownsj /* Do breaks/continues stop at env type e? */
1017cb960a2Sdownsj #define STOP_BRKCONT(t)	((t) == E_NONE || (t) == E_PARSE \
1027cb960a2Sdownsj 			 || (t) == E_FUNC || (t) == E_INCL)
1037cb960a2Sdownsj /* Do returns stop at env type e? */
1047cb960a2Sdownsj #define STOP_RETURN(t)	((t) == E_FUNC || (t) == E_INCL)
1057cb960a2Sdownsj 
10669b9f96bSmillert /* values for siglongjmp(e->jbuf, 0) */
1077cb960a2Sdownsj #define LRETURN	1		/* return statement */
1087cb960a2Sdownsj #define	LEXIT	2		/* exit statement */
1097cb960a2Sdownsj #define LERROR	3		/* errorf() called */
1107cb960a2Sdownsj #define LLEAVE	4		/* untrappable exit/error */
1117cb960a2Sdownsj #define LINTR	5		/* ^C noticed */
1127cb960a2Sdownsj #define	LBREAK	6		/* break statement */
1137cb960a2Sdownsj #define	LCONTIN	7		/* continue statement */
1147cb960a2Sdownsj #define LSHELL	8		/* return to interactive shell() */
1157cb960a2Sdownsj #define LAEXPR	9		/* error in arithmetic expression */
1167cb960a2Sdownsj 
1177cb960a2Sdownsj /* option processing */
1187cb960a2Sdownsj #define OF_CMDLINE	0x01	/* command line */
1197cb960a2Sdownsj #define OF_SET		0x02	/* set builtin */
1207cb960a2Sdownsj #define OF_SPECIAL	0x04	/* a special variable changing */
1213b015934Smillert #define OF_INTERNAL	0x08	/* set internally by shell */
1223b015934Smillert #define OF_ANY		(OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL)
1237cb960a2Sdownsj 
1247cb960a2Sdownsj struct option {
1257cb960a2Sdownsj     const char	*name;	/* long name of option */
1267cb960a2Sdownsj     char	c;	/* character flag (if any) */
1277cb960a2Sdownsj     short	flags;	/* OF_* */
1287cb960a2Sdownsj };
129201e0776Smillert extern const struct option sh_options[];
1307cb960a2Sdownsj 
1317cb960a2Sdownsj /*
1327cb960a2Sdownsj  * flags (the order of these enums MUST match the order in misc.c(options[]))
1337cb960a2Sdownsj  */
1347cb960a2Sdownsj enum sh_flag {
1357cb960a2Sdownsj 	FEXPORT = 0,	/* -a: export all */
1367cb960a2Sdownsj 	FBRACEEXPAND,	/* enable {} globbing */
1377cb960a2Sdownsj 	FBGNICE,	/* bgnice */
1387cb960a2Sdownsj 	FCOMMAND,	/* -c: (invocation) execute specified command */
139f740f764Sderaadt 	FCSHHISTORY,	/* csh-style history enabled */
1407cb960a2Sdownsj #ifdef EMACS
1417cb960a2Sdownsj 	FEMACS,		/* emacs command editing */
1427cb960a2Sdownsj #endif
1437cb960a2Sdownsj 	FERREXIT,	/* -e: quit on error */
1447cb960a2Sdownsj #ifdef EMACS
1457cb960a2Sdownsj 	FGMACS,		/* gmacs command editing */
1467cb960a2Sdownsj #endif
1477cb960a2Sdownsj 	FIGNOREEOF,	/* eof does not exit */
1487cb960a2Sdownsj 	FTALKING,	/* -i: interactive */
149060cee32Sjmc 	FKEYWORD,	/* -k: name=value anywhere */
1507cb960a2Sdownsj 	FLOGIN,		/* -l: a login shell */
1517cb960a2Sdownsj 	FMARKDIRS,	/* mark dirs with / in file name completion */
1527cb960a2Sdownsj 	FMONITOR,	/* -m: job control monitoring */
1537cb960a2Sdownsj 	FNOCLOBBER,	/* -C: don't overwrite existing files */
1547cb960a2Sdownsj 	FNOEXEC,	/* -n: don't execute any commands */
1557cb960a2Sdownsj 	FNOGLOB,	/* -f: don't do file globbing */
1567cb960a2Sdownsj 	FNOHUP,		/* -H: don't kill running jobs when login shell exits */
1577cb960a2Sdownsj 	FNOLOG,		/* don't save functions in history (ignored) */
1587cb960a2Sdownsj 	FNOTIFY,	/* -b: asynchronous job completion notification */
1597cb960a2Sdownsj 	FNOUNSET,	/* -u: using an unset var is an error */
1607cb960a2Sdownsj 	FPHYSICAL,	/* -o physical: don't do logical cd's/pwd's */
161cbb0b321Sjca 	FPIPEFAIL,	/* -o pipefail: all commands in pipeline can affect $? */
1627cb960a2Sdownsj 	FPOSIX,		/* -o posix: be posixly correct */
1637cb960a2Sdownsj 	FPRIVILEGED,	/* -p: use suid_profile */
1647cb960a2Sdownsj 	FRESTRICTED,	/* -r: restricted shell */
165060cee32Sjmc 	FSH,		/* -o sh: favor sh behaviour */
1667cb960a2Sdownsj 	FSTDIN,		/* -s: (invocation) parse stdin */
1677cb960a2Sdownsj 	FTRACKALL,	/* -h: create tracked aliases for all commands */
1687cb960a2Sdownsj 	FVERBOSE,	/* -v: echo input */
1697cb960a2Sdownsj #ifdef VI
1707cb960a2Sdownsj 	FVI,		/* vi command editing */
1717cb960a2Sdownsj 	FVIRAW,		/* always read in raw mode (ignored) */
1727cb960a2Sdownsj 	FVISHOW8,	/* display chars with 8th bit set as is (versus M-) */
1737cb960a2Sdownsj 	FVITABCOMPLETE,	/* enable tab as file name completion char */
174dcacb757Sdownsj 	FVIESCCOMPLETE,	/* enable ESC as file name completion in command mode */
1757cb960a2Sdownsj #endif
1767cb960a2Sdownsj 	FXTRACE,	/* -x: execution trace */
1773b015934Smillert 	FTALKING_I,	/* (internal): initial shell was interactive */
1787cb960a2Sdownsj 	FNFLAGS /* (place holder: how many flags are there) */
1797cb960a2Sdownsj };
1807cb960a2Sdownsj 
1817cb960a2Sdownsj #define Flag(f)	(shell_flags[(int) (f)])
1827cb960a2Sdownsj 
183fa9dffc6Smmcc extern	char shell_flags[FNFLAGS];
1847cb960a2Sdownsj 
185778289f2Smmcc extern	char	null[];	/* null value for variable */
1867cb960a2Sdownsj 
187f00c5086Smillert enum temp_type {
188f00c5086Smillert 	TT_HEREDOC_EXP,	/* expanded heredoc */
189f00c5086Smillert 	TT_HIST_EDIT	/* temp file used for history editing (fc -e) */
190f00c5086Smillert };
191f00c5086Smillert typedef enum temp_type Temp_type;
192f00c5086Smillert /* temp/heredoc files.  The file is removed when the struct is freed. */
1937cb960a2Sdownsj struct temp {
1947cb960a2Sdownsj 	struct temp	*next;
1957cb960a2Sdownsj 	struct shf	*shf;
1967cb960a2Sdownsj 	int		pid;		/* pid of process parsed here-doc */
197f00c5086Smillert 	Temp_type	type;
1987cb960a2Sdownsj 	char		*name;
1997cb960a2Sdownsj };
2007cb960a2Sdownsj 
2017cb960a2Sdownsj /*
2027cb960a2Sdownsj  * stdio and our IO routines
2037cb960a2Sdownsj  */
2047cb960a2Sdownsj 
2057cb960a2Sdownsj #define shl_spare	(&shf_iob[0])	/* for c_read()/c_print() */
2067cb960a2Sdownsj #define shl_stdout	(&shf_iob[1])
2077cb960a2Sdownsj #define shl_out		(&shf_iob[2])
208778289f2Smmcc extern int shl_stdout_ok;
2097cb960a2Sdownsj 
2107cb960a2Sdownsj /*
2117cb960a2Sdownsj  * trap handlers
2127cb960a2Sdownsj  */
2137cb960a2Sdownsj typedef struct trap {
2147cb960a2Sdownsj 	int	signal;		/* signal number */
2157cb960a2Sdownsj 	const char *name;	/* short name */
2167cb960a2Sdownsj 	const char *mess;	/* descriptive name */
2177cb960a2Sdownsj 	char   *trap;		/* trap command */
2188d672f80Smillert 	volatile sig_atomic_t set; /* trap pending */
2197cb960a2Sdownsj 	int	flags;		/* TF_* */
2203f3749e5Smillert 	sig_t cursig;		/* current handler (valid if TF_ORIG_* set) */
2213f3749e5Smillert 	sig_t shtrap;		/* shell signal handler */
2227cb960a2Sdownsj } Trap;
2237cb960a2Sdownsj 
2247cb960a2Sdownsj /* values for Trap.flags */
2257cb960a2Sdownsj #define TF_SHELL_USES	BIT(0)	/* shell uses signal, user can't change */
2267cb960a2Sdownsj #define TF_USER_SET	BIT(1)	/* user has (tried to) set trap */
2277cb960a2Sdownsj #define TF_ORIG_IGN	BIT(2)	/* original action was SIG_IGN */
2287cb960a2Sdownsj #define TF_ORIG_DFL	BIT(3)	/* original action was SIG_DFL */
2297cb960a2Sdownsj #define TF_EXEC_IGN	BIT(4)	/* restore SIG_IGN just before exec */
2307cb960a2Sdownsj #define TF_EXEC_DFL	BIT(5)	/* restore SIG_DFL just before exec */
2317cb960a2Sdownsj #define TF_DFL_INTR	BIT(6)	/* when received, default action is LINTR */
2327cb960a2Sdownsj #define TF_TTY_INTR	BIT(7)	/* tty generated signal (see j_waitj) */
2337cb960a2Sdownsj #define TF_CHANGED	BIT(8)	/* used by runtrap() to detect trap changes */
2347cb960a2Sdownsj #define TF_FATAL	BIT(9)	/* causes termination if not trapped */
2357cb960a2Sdownsj 
2367cb960a2Sdownsj /* values for setsig()/setexecsig() flags argument */
2377cb960a2Sdownsj #define SS_RESTORE_MASK	0x3	/* how to restore a signal before an exec() */
2387cb960a2Sdownsj #define SS_RESTORE_CURR	0	/* leave current handler in place */
2397cb960a2Sdownsj #define SS_RESTORE_ORIG	1	/* restore original handler */
240dcacb757Sdownsj #define SS_RESTORE_DFL	2	/* restore to SIG_DFL */
241dcacb757Sdownsj #define SS_RESTORE_IGN	3	/* restore to SIG_IGN */
2427cb960a2Sdownsj #define SS_FORCE	BIT(3)	/* set signal even if original signal ignored */
2437cb960a2Sdownsj #define SS_USER		BIT(4)	/* user is doing the set (ie, trap command) */
244dcacb757Sdownsj #define SS_SHTRAP	BIT(5)	/* trap for internal use (CHLD,ALRM,WINCH) */
2457cb960a2Sdownsj 
2467cb960a2Sdownsj #define SIGEXIT_	0	/* for trap EXIT */
24769b9f96bSmillert #define SIGERR_		NSIG	/* for trap ERR */
2487cb960a2Sdownsj 
249778289f2Smmcc extern	volatile sig_atomic_t trap;	/* traps pending? */
250778289f2Smmcc extern	volatile sig_atomic_t intrsig;	/* pending trap interrupts command */
251778289f2Smmcc extern	volatile sig_atomic_t fatal_trap;	/* received a fatal signal */
2520bd8b190Stedu extern	volatile sig_atomic_t got_sigwinch;
25369b9f96bSmillert extern	Trap	sigtraps[NSIG+1];
2547cb960a2Sdownsj 
2557cb960a2Sdownsj /*
2567cb960a2Sdownsj  * TMOUT support
2577cb960a2Sdownsj  */
2587cb960a2Sdownsj /* values for ksh_tmout_state */
2597cb960a2Sdownsj enum tmout_enum {
2607cb960a2Sdownsj 	TMOUT_EXECUTING	= 0,	/* executing commands */
2617cb960a2Sdownsj 	TMOUT_READING,		/* waiting for input */
2627cb960a2Sdownsj 	TMOUT_LEAVING		/* have timed out */
2637cb960a2Sdownsj };
264778289f2Smmcc extern unsigned int ksh_tmout;
265778289f2Smmcc extern enum tmout_enum ksh_tmout_state;
2667cb960a2Sdownsj 
2677cb960a2Sdownsj /* For "You have stopped jobs" message */
268778289f2Smmcc extern int really_exit;
2697cb960a2Sdownsj 
2707cb960a2Sdownsj /*
2717cb960a2Sdownsj  * fast character classes
2727cb960a2Sdownsj  */
273dcacb757Sdownsj #define	C_ALPHA	 BIT(0)		/* a-z_A-Z */
274bbf05626Smmcc /* was	C_DIGIT */
275dcacb757Sdownsj #define	C_LEX1	 BIT(2)		/* \0 \t\n|&;<>() */
276dcacb757Sdownsj #define	C_VAR1	 BIT(3)		/* *@#!$-? */
277dcacb757Sdownsj #define	C_IFSWS	 BIT(4)		/* \t \n (IFS white space) */
278dcacb757Sdownsj #define	C_SUBOP1 BIT(5)		/* "=-+?" */
27951c2de25Santon #define	C_SUBOP2 BIT(6)		/* "#%" */
280dcacb757Sdownsj #define	C_IFS	 BIT(7)		/* $IFS */
281dcacb757Sdownsj #define	C_QUOTE	 BIT(8)		/*  \n\t"#$&'()*;<>?[\`| (needing quoting) */
2827cb960a2Sdownsj 
283dcacb757Sdownsj extern	short ctypes [];
2847cb960a2Sdownsj 
2857cb960a2Sdownsj #define	ctype(c, t)	!!(ctypes[(unsigned char)(c)]&(t))
2867cb960a2Sdownsj #define	letter(c)	ctype(c, C_ALPHA)
287bbf05626Smmcc #define	digit(c)	isdigit((unsigned char)(c))
288bbf05626Smmcc #define	letnum(c)	(ctype(c, C_ALPHA) || isdigit((unsigned char)(c)))
2897cb960a2Sdownsj 
290778289f2Smmcc extern int ifs0;	/* for "$*" */
2917cb960a2Sdownsj 
2927cb960a2Sdownsj /* Argument parsing for built-in commands and getopts command */
2937cb960a2Sdownsj 
2947cb960a2Sdownsj /* Values for Getopt.flags */
2957cb960a2Sdownsj #define GF_ERROR	BIT(0)	/* call errorf() if there is an error */
2967cb960a2Sdownsj #define GF_PLUSOPT	BIT(1)	/* allow +c as an option */
2977cb960a2Sdownsj #define GF_NONAME	BIT(2)	/* don't print argv[0] in errors */
2987cb960a2Sdownsj 
2997cb960a2Sdownsj /* Values for Getopt.info */
3007cb960a2Sdownsj #define GI_MINUS	BIT(0)	/* an option started with -... */
3017cb960a2Sdownsj #define GI_PLUS		BIT(1)	/* an option started with +... */
3027cb960a2Sdownsj #define GI_MINUSMINUS	BIT(2)	/* arguments were ended with -- */
3037cb960a2Sdownsj 
3047cb960a2Sdownsj typedef struct {
3057cb960a2Sdownsj 	int		optind;
3063b015934Smillert 	int		uoptind;/* what user sees in $OPTIND */
3077cb960a2Sdownsj 	char		*optarg;
3087cb960a2Sdownsj 	int		flags;	/* see GF_* */
3097cb960a2Sdownsj 	int		info;	/* see GI_* */
3107cb960a2Sdownsj 	unsigned int	p;	/* 0 or index into argv[optind - 1] */
3117cb960a2Sdownsj 	char		buf[2];	/* for bad option OPTARG value */
3127cb960a2Sdownsj } Getopt;
3137cb960a2Sdownsj 
314778289f2Smmcc extern Getopt builtin_opt;	/* for shell builtin commands */
315778289f2Smmcc extern Getopt user_opt;		/* parsing state for getopts builtin command */
3167cb960a2Sdownsj 
3177cb960a2Sdownsj /* This for co-processes */
318dcacb757Sdownsj 
319c3ad38e4Snicm typedef int Coproc_id; /* something that won't (realistically) wrap */
3207cb960a2Sdownsj struct coproc {
3217cb960a2Sdownsj 	int	read;		/* pipe from co-process's stdout */
3227cb960a2Sdownsj 	int	readw;		/* other side of read (saved temporarily) */
3237cb960a2Sdownsj 	int	write;		/* pipe to co-process's stdin */
324dcacb757Sdownsj 	Coproc_id id;		/* id of current output pipe */
325dcacb757Sdownsj 	int	njobs;		/* number of live jobs using output pipe */
326dcacb757Sdownsj 	void	*job;		/* 0 or job of co-process using input pipe */
3277cb960a2Sdownsj };
3281ff40150Smmcc extern struct coproc coproc;
3297cb960a2Sdownsj 
330dcacb757Sdownsj /* Used in jobs.c and by coprocess stuff in exec.c */
3311ff40150Smmcc extern sigset_t		sm_default, sm_sigchld;
332dcacb757Sdownsj 
3337cb960a2Sdownsj extern const char ksh_version[];
3347cb960a2Sdownsj 
3357cb960a2Sdownsj /* name of called builtin function (used by error functions) */
3361ff40150Smmcc extern char	*builtin_argv0;
3371ff40150Smmcc extern int	builtin_flag;	/* flags of called builtin (SPEC_BI, etc.) */
3387cb960a2Sdownsj 
3397cb960a2Sdownsj /* current working directory, and size of memory allocated for same */
3401ff40150Smmcc extern char	*current_wd;
3411ff40150Smmcc extern int	current_wd_size;
3427cb960a2Sdownsj 
343060cee32Sjmc /* Minimum required space to work with on a line - if the prompt leaves less
3447cb960a2Sdownsj  * space than this on a line, the prompt is truncated.
3457cb960a2Sdownsj  */
3467cb960a2Sdownsj #define MIN_EDIT_SPACE	7
347060cee32Sjmc /* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line
3487cb960a2Sdownsj  */
3497cb960a2Sdownsj #define MIN_COLS	(2 + MIN_EDIT_SPACE + 3)
3501ff40150Smmcc extern	int	x_cols;	/* tty columns */
3517cb960a2Sdownsj 
3527cb960a2Sdownsj /* These to avoid bracket matching problems */
3537cb960a2Sdownsj #define OPAREN	'('
3547cb960a2Sdownsj #define CPAREN	')'
3557cb960a2Sdownsj #define OBRACK	'['
3567cb960a2Sdownsj #define CBRACK	']'
3577cb960a2Sdownsj #define OBRACE	'{'
3587cb960a2Sdownsj #define CBRACE	'}'
3597cb960a2Sdownsj 
3607055cce3Sdownsj /* Determine the location of the system (common) profile */
3617055cce3Sdownsj #define KSH_SYSTEM_PROFILE "/etc/profile"
3627cb960a2Sdownsj 
363f00c5086Smillert /* Used by v_evaluate() and setstr() to control action when error occurs */
364e862637cSmillert #define KSH_UNWIND_ERROR	0x0	/* unwind the stack (longjmp) */
365e862637cSmillert #define KSH_RETURN_ERROR	0x1	/* return 1/0 for success/failure */
366e862637cSmillert #define KSH_IGNORE_RDONLY	0x4	/* ignore the read-only flag */
367f00c5086Smillert 
3687cb960a2Sdownsj #include "shf.h"
3697cb960a2Sdownsj #include "table.h"
3707cb960a2Sdownsj #include "tree.h"
3717cb960a2Sdownsj #include "expand.h"
3727cb960a2Sdownsj #include "lex.h"
3739fe385e5Smmcc 
3749fe385e5Smmcc /* alloc.c */
3759fe385e5Smmcc Area *	ainit(Area *);
3769fe385e5Smmcc void	afreeall(Area *);
3779fe385e5Smmcc void *	alloc(size_t, Area *);
378d67c3782Smmcc void *	areallocarray(void *, size_t, size_t, Area *);
3799fe385e5Smmcc void *	aresize(void *, size_t, Area *);
3809fe385e5Smmcc void	afree(void *, Area *);
3819fe385e5Smmcc /* c_ksh.c */
3829fe385e5Smmcc int	c_cd(char **);
3839fe385e5Smmcc int	c_pwd(char **);
3849fe385e5Smmcc int	c_print(char **);
3859fe385e5Smmcc int	c_whence(char **);
3869fe385e5Smmcc int	c_command(char **);
387b4fe65e7Sbenno int	c_type(char **);
3889fe385e5Smmcc int	c_typeset(char **);
3899fe385e5Smmcc int	c_alias(char **);
3909fe385e5Smmcc int	c_unalias(char **);
3919fe385e5Smmcc int	c_let(char **);
3929fe385e5Smmcc int	c_jobs(char **);
3939fe385e5Smmcc int	c_fgbg(char **);
3949fe385e5Smmcc int	c_kill(char **);
3959fe385e5Smmcc void	getopts_reset(int);
3969fe385e5Smmcc int	c_getopts(char **);
3979fe385e5Smmcc int	c_bind(char **);
3989fe385e5Smmcc /* c_sh.c */
3999fe385e5Smmcc int	c_label(char **);
4009fe385e5Smmcc int	c_shift(char **);
4019fe385e5Smmcc int	c_umask(char **);
4029fe385e5Smmcc int	c_dot(char **);
4039fe385e5Smmcc int	c_wait(char **);
4049fe385e5Smmcc int	c_read(char **);
4059fe385e5Smmcc int	c_eval(char **);
4069fe385e5Smmcc int	c_trap(char **);
4079fe385e5Smmcc int	c_brkcont(char **);
4089fe385e5Smmcc int	c_exitreturn(char **);
4099fe385e5Smmcc int	c_set(char **);
4109fe385e5Smmcc int	c_unset(char **);
4119fe385e5Smmcc int	c_ulimit(char **);
4129fe385e5Smmcc int	c_times(char **);
4139fe385e5Smmcc int	timex(struct op *, int, volatile int *);
4149fe385e5Smmcc void	timex_hook(struct op *, char ** volatile *);
4159fe385e5Smmcc int	c_exec(char **);
4169fe385e5Smmcc int	c_builtin(char **);
4179fe385e5Smmcc /* c_test.c */
4189fe385e5Smmcc int	c_test(char **);
4199fe385e5Smmcc /* edit.c: most prototypes in edit.h */
4209fe385e5Smmcc void	x_init(void);
4219fe385e5Smmcc int	x_read(char *, size_t);
4229fe385e5Smmcc void	set_editmode(const char *);
4239fe385e5Smmcc /* emacs.c: most prototypes in edit.h */
4249fe385e5Smmcc int	x_bind(const char *, const char *, int, int);
4259fe385e5Smmcc /* eval.c */
4269fe385e5Smmcc char *	substitute(const char *, int);
4279fe385e5Smmcc char **	eval(char **, int);
4289fe385e5Smmcc char *	evalstr(char *cp, int);
4299fe385e5Smmcc char *	evalonestr(char *cp, int);
4309fe385e5Smmcc char	*debunk(char *, const char *, size_t);
4319fe385e5Smmcc void	expand(char *, XPtrV *, int);
4329fe385e5Smmcc int	glob_str(char *, XPtrV *, int);
4339fe385e5Smmcc /* exec.c */
4349fe385e5Smmcc int	execute(struct op * volatile, volatile int, volatile int *);
4359fe385e5Smmcc int	shcomexec(char **);
4369fe385e5Smmcc struct tbl * findfunc(const char *, unsigned int, int);
4379fe385e5Smmcc int	define(const char *, struct op *);
4389fe385e5Smmcc void	builtin(const char *, int (*)(char **));
4399fe385e5Smmcc struct tbl *	findcom(const char *, int);
4409fe385e5Smmcc void	flushcom(int);
4419fe385e5Smmcc char *	search(const char *, const char *, int, int *);
4429fe385e5Smmcc int	search_access(const char *, int, int *);
4439fe385e5Smmcc int	pr_menu(char *const *);
4449fe385e5Smmcc /* expr.c */
445517d3880Stobias int	evaluate(const char *, int64_t *, int, bool);
4469fe385e5Smmcc int	v_evaluate(struct tbl *, const char *, volatile int, bool);
4479fe385e5Smmcc /* history.c */
4489fe385e5Smmcc void	init_histvec(void);
4499fe385e5Smmcc void	hist_init(Source *);
4509fe385e5Smmcc void	hist_finish(void);
4519fe385e5Smmcc void	histsave(int, const char *, int);
4529fe385e5Smmcc int	c_fc(char **);
453c722fcadSmartijn void	c_fc_reset(void);
454a725701fSjca void	sethistcontrol(const char *);
4559fe385e5Smmcc void	sethistsize(int);
4569fe385e5Smmcc void	sethistfile(const char *);
4579fe385e5Smmcc char **	histpos(void);
4589fe385e5Smmcc int	histnum(int);
4599fe385e5Smmcc int	findhist(int, int, const char *, int);
4609fe385e5Smmcc int	findhistrel(const char *);
4619fe385e5Smmcc char  **hist_get_newest(int);
4629fe385e5Smmcc 
4639fe385e5Smmcc /* io.c */
4649fe385e5Smmcc void	errorf(const char *, ...)
4659fe385e5Smmcc 	    __attribute__((__noreturn__, __format__ (printf, 1, 2)));
466504796f7Smmcc void	warningf(bool, const char *, ...)
4679fe385e5Smmcc 	    __attribute__((__format__ (printf, 2, 3)));
4689fe385e5Smmcc void	bi_errorf(const char *, ...)
4699fe385e5Smmcc 	    __attribute__((__format__ (printf, 1, 2)));
4706c72b531Sjca void	internal_errorf(const char *, ...)
4716c72b531Sjca 	    __attribute__((__noreturn__, __format__ (printf, 1, 2)));
4726c72b531Sjca void	internal_warningf(const char *, ...)
4736c72b531Sjca 	    __attribute__((__format__ (printf, 1, 2)));
4749fe385e5Smmcc void	error_prefix(int);
4759fe385e5Smmcc void	shellf(const char *, ...)
4769fe385e5Smmcc 	    __attribute__((__format__ (printf, 1, 2)));
4779fe385e5Smmcc void	shprintf(const char *, ...)
4789fe385e5Smmcc 	    __attribute__((__format__ (printf, 1, 2)));
4799fe385e5Smmcc #ifdef KSH_DEBUG
4809fe385e5Smmcc void	kshdebug_init_(void);
4819fe385e5Smmcc void	kshdebug_printf_(const char *, ...)
4829fe385e5Smmcc 	    __attribute__((__format__ (printf, 1, 2)));
4839fe385e5Smmcc void	kshdebug_dump_(const char *, const void *, int);
4849fe385e5Smmcc #endif /* KSH_DEBUG */
4859fe385e5Smmcc int	can_seek(int);
4869fe385e5Smmcc void	initio(void);
4879fe385e5Smmcc int	ksh_dup2(int, int, int);
4889fe385e5Smmcc int	savefd(int);
4899fe385e5Smmcc void	restfd(int, int);
4909fe385e5Smmcc void	openpipe(int *);
4919fe385e5Smmcc void	closepipe(int *);
4929fe385e5Smmcc int	check_fd(char *, int, const char **);
4939fe385e5Smmcc void	coproc_init(void);
4949fe385e5Smmcc void	coproc_read_close(int);
4959fe385e5Smmcc void	coproc_readw_close(int);
4969fe385e5Smmcc void	coproc_write_close(int);
4979fe385e5Smmcc int	coproc_getfd(int, const char **);
4989fe385e5Smmcc void	coproc_cleanup(int);
4999fe385e5Smmcc struct temp *maketemp(Area *, Temp_type, struct temp **);
5009fe385e5Smmcc /* jobs.c */
5019fe385e5Smmcc void	j_init(int);
5029fe385e5Smmcc void	j_suspend(void);
5039fe385e5Smmcc void	j_exit(void);
5049fe385e5Smmcc void	j_change(void);
5059fe385e5Smmcc int	exchild(struct op *, int, volatile int *, int);
5069fe385e5Smmcc void	startlast(void);
5079fe385e5Smmcc int	waitlast(void);
5089fe385e5Smmcc int	waitfor(const char *, int *);
5099fe385e5Smmcc int	j_kill(const char *, int);
5109fe385e5Smmcc int	j_resume(const char *, int);
5119fe385e5Smmcc int	j_jobs(const char *, int, int);
5129fe385e5Smmcc int	j_njobs(void);
5139fe385e5Smmcc void	j_notify(void);
5149fe385e5Smmcc pid_t	j_async(void);
5159fe385e5Smmcc int	j_stopped_running(void);
5169fe385e5Smmcc /* mail.c */
5179fe385e5Smmcc void	mcheck(void);
518517d3880Stobias void	mcset(int64_t);
5199fe385e5Smmcc void	mbset(char *);
5209fe385e5Smmcc void	mpset(char *);
5219fe385e5Smmcc /* main.c */
5229fe385e5Smmcc int	include(const char *, int, char **, int);
5239fe385e5Smmcc int	command(const char *, int);
5249fe385e5Smmcc int	shell(Source *volatile, int volatile);
5259fe385e5Smmcc void	unwind(int) __attribute__((__noreturn__));
5269fe385e5Smmcc void	newenv(int);
5279fe385e5Smmcc void	quitenv(struct shf *);
5289fe385e5Smmcc void	cleanup_parents_env(void);
5299fe385e5Smmcc void	cleanup_proc_env(void);
5309fe385e5Smmcc /* misc.c */
5319fe385e5Smmcc void	setctypes(const char *, int);
5329fe385e5Smmcc void	initctypes(void);
533517d3880Stobias char *	u64ton(uint64_t, int);
5349fe385e5Smmcc char *	str_save(const char *, Area *);
5359fe385e5Smmcc char *	str_nsave(const char *, int, Area *);
5369fe385e5Smmcc int	option(const char *);
5379fe385e5Smmcc char *	getoptions(void);
5389fe385e5Smmcc void	change_flag(enum sh_flag, int, int);
5399fe385e5Smmcc int	parse_args(char **, int, int *);
5409fe385e5Smmcc int	getn(const char *, int *);
5419fe385e5Smmcc int	bi_getn(const char *, int *);
5429fe385e5Smmcc int	gmatch(const char *, const char *, int);
5439fe385e5Smmcc int	has_globbing(const char *, const char *);
5449fe385e5Smmcc const unsigned char *pat_scan(const unsigned char *, const unsigned char *,
5459fe385e5Smmcc     int);
5469fe385e5Smmcc void	qsortp(void **, size_t, int (*)(const void *, const void *));
5479fe385e5Smmcc int	xstrcmp(const void *, const void *);
5489fe385e5Smmcc void	ksh_getopt_reset(Getopt *, int);
5499fe385e5Smmcc int	ksh_getopt(char **, Getopt *, const char *);
5509fe385e5Smmcc void	print_value_quoted(const char *);
5519fe385e5Smmcc void	print_columns(struct shf *, int, char *(*)(void *, int, char *, int),
5529fe385e5Smmcc     void *, int, int prefcol);
5539fe385e5Smmcc int	strip_nuls(char *, int);
5549fe385e5Smmcc int	blocking_read(int, char *, int);
5559fe385e5Smmcc int	reset_nonblock(int);
5569fe385e5Smmcc char	*ksh_get_wd(char *, int);
5579fe385e5Smmcc /* path.c */
5589fe385e5Smmcc int	make_path(const char *, const char *, char **, XString *, int *);
5599fe385e5Smmcc void	simplify_path(char *);
5609fe385e5Smmcc char	*get_phys_path(const char *);
5619fe385e5Smmcc void	set_current_wd(char *);
5629fe385e5Smmcc /* syn.c */
5639fe385e5Smmcc void	initkeywords(void);
5649fe385e5Smmcc struct op * compile(Source *);
5659fe385e5Smmcc /* trap.c */
5669fe385e5Smmcc void	inittraps(void);
5679fe385e5Smmcc void	alarm_init(void);
5689fe385e5Smmcc Trap *	gettrap(const char *, int);
5699fe385e5Smmcc void	trapsig(int);
5709fe385e5Smmcc void	intrcheck(void);
5719fe385e5Smmcc int	fatal_trap_check(void);
5729fe385e5Smmcc int	trap_pending(void);
5739fe385e5Smmcc void	runtraps(int intr);
5749fe385e5Smmcc void	runtrap(Trap *);
5759fe385e5Smmcc void	cleartraps(void);
5769fe385e5Smmcc void	restoresigs(void);
5779fe385e5Smmcc void	settrap(Trap *, char *);
5789fe385e5Smmcc int	block_pipe(void);
5799fe385e5Smmcc void	restore_pipe(int);
5809fe385e5Smmcc int	setsig(Trap *, sig_t, int);
5819fe385e5Smmcc void	setexecsig(Trap *, int);
5829fe385e5Smmcc /* var.c */
5839fe385e5Smmcc void	newblock(void);
5849fe385e5Smmcc void	popblock(void);
5859fe385e5Smmcc void	initvar(void);
5869fe385e5Smmcc struct tbl *	global(const char *);
5879fe385e5Smmcc struct tbl *	local(const char *, bool);
5889fe385e5Smmcc char *	str_val(struct tbl *);
589517d3880Stobias int64_t	intval(struct tbl *);
5909fe385e5Smmcc int	setstr(struct tbl *, const char *, int);
5919fe385e5Smmcc struct tbl *setint_v(struct tbl *, struct tbl *, bool);
592517d3880Stobias void	setint(struct tbl *, int64_t);
593517d3880Stobias int	getint(struct tbl *, int64_t *, bool);
5949fe385e5Smmcc struct tbl *typeset(const char *, int, int, int, int);
5959fe385e5Smmcc void	unset(struct tbl *, int);
5969fe385e5Smmcc char  * skip_varname(const char *, int);
5979fe385e5Smmcc char	*skip_wdvarname(const char *, int);
5989fe385e5Smmcc int	is_wdvarname(const char *, int);
5999fe385e5Smmcc int	is_wdvarassign(const char *);
6009fe385e5Smmcc char **	makenv(void);
6019fe385e5Smmcc void	change_random(void);
6029fe385e5Smmcc int	array_ref_len(const char *);
6039fe385e5Smmcc char *	arrayname(const char *);
6049fe385e5Smmcc void    set_array(const char *, int, char **);
6059fe385e5Smmcc /* vi.c: see edit.h */
606