1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin /*
22*4887Schin  * David Korn
23*4887Schin  * AT&T Labs
24*4887Schin  *
25*4887Schin  * Shell interface private definitions
26*4887Schin  *
27*4887Schin  */
28*4887Schin 
29*4887Schin #include	<ast.h>
30*4887Schin #include	<sfio.h>
31*4887Schin #include	<error.h>
32*4887Schin #include	"FEATURE/options"
33*4887Schin #include	<cdt.h>
34*4887Schin #include	<history.h>
35*4887Schin #include	"fault.h"
36*4887Schin #include	"argnod.h"
37*4887Schin 
38*4887Schin #ifndef pointerof
39*4887Schin #define pointerof(x)		((void*)((char*)0+(x)))
40*4887Schin #endif
41*4887Schin 
42*4887Schin #define	env_change()		(++ast.env_serial)
43*4887Schin #if SHOPT_ENV
44*4887Schin #   include	<env.h>
45*4887Schin #else
46*4887Schin #   define Env_t		void
47*4887Schin #   define sh_envput(e,p)	env_change()
48*4887Schin #   define env_delete(e,p)	env_change()
49*4887Schin #endif
50*4887Schin 
51*4887Schin /*
52*4887Schin  * note that the first few fields have to be the same as for
53*4887Schin  * Shscoped_t in <shell.h>
54*4887Schin  */
55*4887Schin struct sh_scoped
56*4887Schin {
57*4887Schin 	struct sh_scoped *prevst;	/* pointer to previous state */
58*4887Schin 	int		dolc;
59*4887Schin 	char		**dolv;
60*4887Schin 	char		*cmdname;
61*4887Schin 	char		*filename;
62*4887Schin 	int		lineno;
63*4887Schin 	Dt_t		*save_tree;	/* var_tree for calling function */
64*4887Schin 	struct sh_scoped *self;		/* pointer to copy of this scope*/
65*4887Schin 	Dt_t		*var_local;	/* local level variables for name() */
66*4887Schin 	struct slnod	*staklist;	/* link list of function stacks */
67*4887Schin 	int		states;
68*4887Schin 	int		breakcnt;
69*4887Schin 	int		execbrk;
70*4887Schin 	int		loopcnt;
71*4887Schin 	int		firstline;
72*4887Schin 	int32_t		optindex;
73*4887Schin 	int32_t		optnum;
74*4887Schin 	int32_t		tmout;		/* value for TMOUT */
75*4887Schin 	short		optchar;
76*4887Schin 	short		opterror;
77*4887Schin 	int		ioset;
78*4887Schin 	unsigned short	trapmax;
79*4887Schin 	char		*trap[SH_DEBUGTRAP+1];
80*4887Schin 	char		**trapcom;
81*4887Schin 	char		**otrapcom;
82*4887Schin 	void		*timetrap;
83*4887Schin };
84*4887Schin 
85*4887Schin struct limits
86*4887Schin {
87*4887Schin 	long		arg_max;	/* max arg+env exec() size */
88*4887Schin 	int		open_max;	/* maximum number of file descriptors */
89*4887Schin 	int		clk_tck;	/* number of ticks per second */
90*4887Schin 	int		child_max;	/* maxumum number of children */
91*4887Schin 	int		ngroups_max;	/* maximum number of process groups */
92*4887Schin 	unsigned char	posix_version;	/* posix version number */
93*4887Schin 	unsigned char	posix_jobcontrol;/* non-zero for job control systems */
94*4887Schin 	unsigned char	fs3d;		/* non-zero for 3-d file system */
95*4887Schin };
96*4887Schin 
97*4887Schin #define _SH_PRIVATE \
98*4887Schin 	struct sh_scoped st;		/* scoped information */ \
99*4887Schin 	struct limits	lim;		/* run time limits */ \
100*4887Schin 	Sfio_t		*heredocs;	/* current here-doc temp file */ \
101*4887Schin 	Sfio_t		*funlog;	/* for logging function definitions */ \
102*4887Schin 	int		**fdptrs;	/* pointer to file numbers */ \
103*4887Schin 	int		savexit; \
104*4887Schin 	char		*lastarg; \
105*4887Schin 	char		*lastpath;	/* last alsolute path found */ \
106*4887Schin 	int		path_err;	/* last error on path search */ \
107*4887Schin 	Dt_t		*track_tree;	/* for tracked aliases*/ \
108*4887Schin 	Namval_t	*bltin_nodes;	/* pointer to built-in variables */ \
109*4887Schin 	Dt_t		*var_base;	/* global level variables */ \
110*4887Schin 	Namval_t	*namespace;	/* current active namespace*/ \
111*4887Schin 	Namval_t	*last_table;	/* last table used in last nv_open  */ \
112*4887Schin 	Sfio_t		*outpool;	/* ouput stream pool */ \
113*4887Schin 	long		timeout;	/* read timeout */ \
114*4887Schin 	short		curenv;		/* current subshell number */ \
115*4887Schin 	short		jobenv;		/* subshell number for jobs */ \
116*4887Schin 	int		nextprompt;	/* next prompt is PS<nextprompt> */ \
117*4887Schin 	Namval_t	*bltin_cmds;	/* pointer to built-in commands */ \
118*4887Schin 	Namval_t	*posix_fun;	/* points to last name() function */ \
119*4887Schin 	int		infd;		/* input file descriptor */ \
120*4887Schin 	char		*outbuff;	/* pointer to output buffer */ \
121*4887Schin 	char		*errbuff;	/* pointer to stderr buffer */ \
122*4887Schin 	char		*prompt;	/* pointer to prompt string */ \
123*4887Schin 	char		*shname;	/* shell name */ \
124*4887Schin 	char		*shpath;	/* path name of shell */ \
125*4887Schin 	char		*user;		/* name of real user for pfsh */ \
126*4887Schin 	char		*comdiv;	/* points to sh -c argument */ \
127*4887Schin 	char		*prefix;	/* prefix for compound assignment */ \
128*4887Schin 	sigjmp_buf	*jmplist;	/* longjmp return stack */ \
129*4887Schin 	char		**sigmsg;	/* points to signal messages */ \
130*4887Schin 	int		oldexit; \
131*4887Schin 	uid_t 		userid,euserid;	/* real and effective user id */ \
132*4887Schin 	gid_t 		groupid,egroupid;/* real and effective group id */ \
133*4887Schin 	pid_t		pid;		/* process id of shell */ \
134*4887Schin 	pid_t		bckpid;		/* background process id */ \
135*4887Schin 	pid_t		cpid; \
136*4887Schin 	int32_t		ppid;		/* parent process id of shell */ \
137*4887Schin 	int		topfd; \
138*4887Schin 	int		sigmax;		/* maximum number of signals */ \
139*4887Schin 	int		savesig; \
140*4887Schin 	unsigned char	*sigflag;	/* pointer to signal states */ \
141*4887Schin 	char		intrap; \
142*4887Schin 	char		login_sh; \
143*4887Schin 	char		lastbase; \
144*4887Schin 	char		forked;	\
145*4887Schin 	char		binscript; \
146*4887Schin 	char		deftype; \
147*4887Schin 	char		used_pos;	/* used postional parameter */\
148*4887Schin 	unsigned char	lastsig;	/* last signal received */ \
149*4887Schin 	char		*readscript;	/* set before reading a script */ \
150*4887Schin 	int		*inpipe;	/* input pipe pointer */ \
151*4887Schin 	int		*outpipe;	/* output pipe pointer */ \
152*4887Schin 	int		cpipe[2]; \
153*4887Schin 	int		coutpipe; \
154*4887Schin 	int		inuse_bits; \
155*4887Schin 	struct argnod	*envlist; \
156*4887Schin 	struct dolnod	*arglist; \
157*4887Schin 	int		fn_depth; \
158*4887Schin 	int		dot_depth; \
159*4887Schin 	int		hist_depth; \
160*4887Schin 	int		xargmin; \
161*4887Schin 	int		xargmax; \
162*4887Schin 	int		xargexit; \
163*4887Schin 	mode_t		mask; \
164*4887Schin 	long		nforks; \
165*4887Schin 	Env_t		*env; \
166*4887Schin 	void		*init_context; \
167*4887Schin 	void		*mac_context; \
168*4887Schin 	void		*lex_context; \
169*4887Schin 	void		*arg_context; \
170*4887Schin 	void		*ed_context; \
171*4887Schin 	void		*job_context; \
172*4887Schin 	void		*pathlist; \
173*4887Schin 	void		*defpathlist; \
174*4887Schin 	void		*cdpathlist; \
175*4887Schin 	char		**argaddr; \
176*4887Schin 	void		*optlist; \
177*4887Schin 	int		optcount ; \
178*4887Schin 	struct sh_scoped global; \
179*4887Schin 	struct checkpt	checkbase; \
180*4887Schin 	Shinit_f	userinit; \
181*4887Schin 	Shbltin_f	bltinfun; \
182*4887Schin 	Shwait_f	waitevent; \
183*4887Schin 	char		*cur_line; \
184*4887Schin 	char		*rcfile; \
185*4887Schin 	char		**login_files; \
186*4887Schin 	short		offsets[10]; \
187*4887Schin 	Sfio_t		**sftable; \
188*4887Schin 	unsigned char	*fdstatus; \
189*4887Schin 	const char	*pwd; \
190*4887Schin 	History_t	*hist_ptr; \
191*4887Schin 	char		universe; \
192*4887Schin 	void		*jmpbuffer; \
193*4887Schin 	void		*mktype; \
194*4887Schin 	Sfio_t		*strbuf; \
195*4887Schin 	Dt_t		*last_root; \
196*4887Schin 	char		ifstable[256]; \
197*4887Schin 	Shopt_t		offoptions;
198*4887Schin 
199*4887Schin #include	<shell.h>
200*4887Schin 
201*4887Schin 
202*4887Schin /* error exits from various parts of shell */
203*4887Schin #define	NIL(type)	((type)0)
204*4887Schin 
205*4887Schin #define new_of(type,x)	((type*)malloc((unsigned)sizeof(type)+(x)))
206*4887Schin 
207*4887Schin #define exitset()	(sh.savexit=sh.exitval)
208*4887Schin 
209*4887Schin #ifndef SH_DICT
210*4887Schin #define SH_DICT		(void*)e_dict
211*4887Schin #endif
212*4887Schin 
213*4887Schin #ifndef SH_CMDLIB_DIR
214*4887Schin #define SH_CMDLIB_DIR	"/opt/ast/bin"
215*4887Schin #endif
216*4887Schin 
217*4887Schin /* states */
218*4887Schin /* low numbered states are same as options */
219*4887Schin #define SH_NOFORK	0	/* set when fork not necessary, not a state */
220*4887Schin #define SH_COMPLETE	0	/* set for command completion */
221*4887Schin #define	SH_FORKED	7	/* set when process has been forked */
222*4887Schin #define	SH_PROFILE	8	/* set when processing profiles */
223*4887Schin #define SH_NOALIAS	9	/* do not expand non-exported aliases */
224*4887Schin #define SH_NOTRACK	10	/* set to disable sftrack() function */
225*4887Schin #define SH_STOPOK	11	/* set for stopable builtins */
226*4887Schin #define SH_GRACE	12	/* set for timeout grace period */
227*4887Schin #define SH_TIMING	13	/* set while timing pipelines */
228*4887Schin #define SH_DEFPATH	14	/* set when using default path */
229*4887Schin #define SH_INIT		15	/* set when initializing the shell */
230*4887Schin #define SH_TTYWAIT	16	/* waiting for keyboard input */
231*4887Schin #define	SH_FCOMPLETE	17	/* set for filename completion */
232*4887Schin #define	SH_PREINIT	18	/* set with SH_INIT before parsing options */
233*4887Schin 
234*4887Schin #define SH_BASH			41
235*4887Schin #define SH_BRACEEXPAND		42
236*4887Schin #define SH_POSIX		46
237*4887Schin #define SH_MULTILINE    	47
238*4887Schin 
239*4887Schin #define SH_NOPROFILE		78
240*4887Schin #define SH_NOUSRPROFILE		79
241*4887Schin #define SH_LOGIN_SHELL		67
242*4887Schin #define SH_COMMANDLINE		0x100
243*4887Schin #define SH_BASHEXTRA		0x200
244*4887Schin #define SH_BASHOPT		0x400
245*4887Schin 
246*4887Schin #define SH_ID			"ksh"	/* ksh id */
247*4887Schin #define SH_STD			"sh"	/* standard sh id */
248*4887Schin 
249*4887Schin /* defines for sh_type() */
250*4887Schin 
251*4887Schin #define SH_TYPE_SH		001
252*4887Schin #define SH_TYPE_KSH		002
253*4887Schin #define SH_TYPE_BASH		004
254*4887Schin #define SH_TYPE_LOGIN		010
255*4887Schin #define SH_TYPE_PROFILE		020
256*4887Schin #define SH_TYPE_RESTRICTED	040
257*4887Schin 
258*4887Schin #if SHOPT_BASH
259*4887Schin #   ifndef SHOPT_HISTEXPAND
260*4887Schin #	define SHOPT_HISTEXPAND	1
261*4887Schin #   endif
262*4887Schin /*
263*4887Schin  *  define for all the bash options
264*4887Schin  */
265*4887Schin #   define SH_CDABLE_VARS	51
266*4887Schin #   define SH_CDSPELL		52
267*4887Schin #   define SH_CHECKHASH		53
268*4887Schin #   define SH_CHECKWINSIZE	54
269*4887Schin #   define SH_CMDHIST		55
270*4887Schin #   define SH_DOTGLOB		56
271*4887Schin #   define SH_EXECFAIL		57
272*4887Schin #   define SH_EXPAND_ALIASES	58
273*4887Schin #   define SH_EXTGLOB		59
274*4887Schin #   define SH_HOSTCOMPLETE	63
275*4887Schin #   define SH_HUPONEXIT		64
276*4887Schin #   define SH_INTERACTIVE_COMM	65
277*4887Schin #   define SH_LITHIST		66
278*4887Schin #   define SH_MAILWARN		68
279*4887Schin #   define SH_NOEMPTYCMDCOMPL	69
280*4887Schin #   define SH_NOCASEGLOB	70
281*4887Schin #   define SH_NULLGLOB		71
282*4887Schin #   define SH_PHYSICAL		45
283*4887Schin #   define SH_PROGCOMP		72
284*4887Schin #   define SH_PROMPTVARS	73
285*4887Schin #   define SH_RESTRICTED2	74
286*4887Schin #   define SH_SHIFT_VERBOSE	75
287*4887Schin #   define SH_SOURCEPATH	76
288*4887Schin #   define SH_XPG_ECHO		77
289*4887Schin #endif
290*4887Schin 
291*4887Schin #if SHOPT_HISTEXPAND
292*4887Schin #   define SH_HISTAPPEND	60
293*4887Schin #   define SH_HISTEXPAND	43
294*4887Schin #   define SH_HISTORY2		44
295*4887Schin #   define SH_HISTREEDIT	61
296*4887Schin #   define SH_HISTVERIFY	62
297*4887Schin #endif
298*4887Schin 
299*4887Schin #ifndef PIPE_BUF
300*4887Schin #   define PIPE_BUF		512
301*4887Schin #endif
302*4887Schin 
303*4887Schin #define MATCH_MAX		64
304*4887Schin 
305*4887Schin extern int		sh_addlib(void*);
306*4887Schin extern void 		*sh_argopen(Shell_t*);
307*4887Schin extern Namval_t		*sh_assignok(Namval_t*,int);
308*4887Schin extern char		*sh_checkid(char*,char*);
309*4887Schin extern int		sh_debug(const char*,const char*,const char*,char *const[],int);
310*4887Schin extern int 		sh_echolist(Sfio_t*, int, char**);
311*4887Schin extern struct argnod	*sh_endword(int);
312*4887Schin extern char 		**sh_envgen(void);
313*4887Schin #if SHOPT_ENV
314*4887Schin extern void 		sh_envput(Env_t*, Namval_t*);
315*4887Schin #endif
316*4887Schin extern void 		sh_envnolocal(Namval_t*,void*);
317*4887Schin extern Sfdouble_t	sh_arith(const char*);
318*4887Schin extern void		*sh_arithcomp(char*);
319*4887Schin extern pid_t 		sh_fork(int,int*);
320*4887Schin extern pid_t		_sh_fork(pid_t, int ,int*);
321*4887Schin extern char 		*sh_mactrim(char*,int);
322*4887Schin extern int 		sh_macexpand(struct argnod*,struct argnod**,int);
323*4887Schin extern void 		sh_machere(Sfio_t*, Sfio_t*, char*);
324*4887Schin extern void 		*sh_macopen(Shell_t*);
325*4887Schin extern char 		*sh_macpat(struct argnod*,int);
326*4887Schin extern char 		*sh_mactry(char*);
327*4887Schin extern void		sh_printopts(Shopt_t,int,Shopt_t*);
328*4887Schin extern int 		sh_readline(Shell_t*,char**,int,int,long);
329*4887Schin extern Sfio_t		*sh_sfeval(char*[]);
330*4887Schin extern void		sh_setmatch(const char*,int,int,int[]);
331*4887Schin extern Dt_t		*sh_subaliastree(int);
332*4887Schin extern Dt_t		*sh_subfuntree(int);
333*4887Schin extern int		sh_subsavefd(int);
334*4887Schin extern void		sh_subtmpfile(void);
335*4887Schin extern char 		*sh_substitute(const char*,const char*,char*);
336*4887Schin extern const char	*_sh_translate(const char*);
337*4887Schin extern int		sh_trace(char*[],int);
338*4887Schin extern void		sh_trim(char*);
339*4887Schin extern int		sh_type(const char*);
340*4887Schin extern void		sh_utol(const char*, char*);
341*4887Schin extern int 		sh_whence(char**,int);
342*4887Schin 
343*4887Schin #ifndef ERROR_dictionary
344*4887Schin #   define ERROR_dictionary(s)	(s)
345*4887Schin #endif
346*4887Schin #define sh_translate(s)	_sh_translate(ERROR_dictionary(s))
347*4887Schin 
348*4887Schin #define WBITS		(sizeof(long)*8)
349*4887Schin #define WMASK		(0xff)
350*4887Schin 
351*4887Schin #define is_option(s,x)	((s)->v[((x)&WMASK)/WBITS] & (1L << ((x) % WBITS)))
352*4887Schin #define on_option(s,x)	((s)->v[((x)&WMASK)/WBITS] |= (1L << ((x) % WBITS)))
353*4887Schin #define off_option(s,x)	((s)->v[((x)&WMASK)/WBITS] &= ~(1L << ((x) % WBITS)))
354*4887Schin #define sh_isoption(x)	is_option(&sh.options,x)
355*4887Schin #define sh_onoption(x)	on_option(&sh.options,x)
356*4887Schin #define sh_offoption(x)	off_option(&sh.options,x)
357*4887Schin 
358*4887Schin 
359*4887Schin #define sh_state(x)	( 1<<(x))
360*4887Schin #define	sh_isstate(x)	(sh.st.states&sh_state(x))
361*4887Schin #define	sh_onstate(x)	(sh.st.states |= sh_state(x))
362*4887Schin #define	sh_offstate(x)	(sh.st.states &= ~sh_state(x))
363*4887Schin #define	sh_getstate()	(sh.st.states)
364*4887Schin #define	sh_setstate(x)	(sh.st.states = (x))
365*4887Schin 
366*4887Schin #define sh_sigcheck() do{if(sh.trapnote&SH_SIGSET)sh_exit(SH_EXITSIG);} while(0)
367*4887Schin 
368*4887Schin extern int32_t		sh_mailchk;
369*4887Schin extern const char	e_dict[];
370*4887Schin 
371*4887Schin /* sh_printopts() mode flags -- set --[no]option by default */
372*4887Schin 
373*4887Schin #define PRINT_VERBOSE	0x01	/* option on|off list		*/
374*4887Schin #define PRINT_ALL	0x02	/* list unset iptions too	*/
375*4887Schin #define PRINT_NO_HEADER	0x04	/* omit listing header		*/
376*4887Schin #define PRINT_SHOPT	0x08	/* shopt -s|-u			*/
377*4887Schin #define PRINT_TABLE	0x10	/* table of all options		*/
378