xref: /titanic_50/usr/src/lib/libshell/common/sh/init.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  *
23da2e3ebdSchin  * Shell initialization
24da2e3ebdSchin  *
25da2e3ebdSchin  *   David Korn
26da2e3ebdSchin  *   AT&T Labs
27da2e3ebdSchin  *
28da2e3ebdSchin  */
29da2e3ebdSchin 
30da2e3ebdSchin #include        "defs.h"
31da2e3ebdSchin #include        <stak.h>
32da2e3ebdSchin #include        <ccode.h>
33da2e3ebdSchin #include        <pwd.h>
347c2fbfb3SApril Chin #include        <tmx.h>
35da2e3ebdSchin #include        "variables.h"
36da2e3ebdSchin #include        "path.h"
37da2e3ebdSchin #include        "fault.h"
38da2e3ebdSchin #include        "name.h"
39da2e3ebdSchin #include	"edit.h"
40da2e3ebdSchin #include	"jobs.h"
41da2e3ebdSchin #include	"io.h"
42da2e3ebdSchin #include	"shlex.h"
43da2e3ebdSchin #include	"builtins.h"
44da2e3ebdSchin #include	"FEATURE/time"
45da2e3ebdSchin #include	"FEATURE/dynamic"
4634f9b3eeSRoland Mainz #include	"FEATURE/externs"
47da2e3ebdSchin #include	"lexstates.h"
48da2e3ebdSchin #include	"version.h"
49da2e3ebdSchin 
507c2fbfb3SApril Chin char e_version[]	= "\n@(#)$Id: Version "
517c2fbfb3SApril Chin #if SHOPT_AUDIT
527c2fbfb3SApril Chin #define ATTRS		1
537c2fbfb3SApril Chin 			"A"
547c2fbfb3SApril Chin #endif
557c2fbfb3SApril Chin #if SHOPT_BASH
567c2fbfb3SApril Chin #define ATTRS		1
577c2fbfb3SApril Chin 			"B"
587c2fbfb3SApril Chin #endif
5934f9b3eeSRoland Mainz #if SHOPT_BGX
6034f9b3eeSRoland Mainz #define ATTRS		1
6134f9b3eeSRoland Mainz 			"J"
6234f9b3eeSRoland Mainz #endif
637c2fbfb3SApril Chin #if SHOPT_ACCT
647c2fbfb3SApril Chin #define ATTRS		1
657c2fbfb3SApril Chin 			"L"
667c2fbfb3SApril Chin #endif
67da2e3ebdSchin #if SHOPT_MULTIBYTE
687c2fbfb3SApril Chin #define ATTRS		1
697c2fbfb3SApril Chin 			"M"
707c2fbfb3SApril Chin #endif
717c2fbfb3SApril Chin #if SHOPT_PFSH && _hdr_exec_attr
727c2fbfb3SApril Chin #define ATTRS		1
737c2fbfb3SApril Chin 			"P"
747c2fbfb3SApril Chin #endif
7534f9b3eeSRoland Mainz #if SHOPT_REGRESS
7634f9b3eeSRoland Mainz #define ATTRS		1
7734f9b3eeSRoland Mainz 			"R"
7834f9b3eeSRoland Mainz #endif
797c2fbfb3SApril Chin #if ATTRS
807c2fbfb3SApril Chin 			" "
817c2fbfb3SApril Chin #endif
827c2fbfb3SApril Chin 			SH_RELEASE " $\0\n";
83da2e3ebdSchin 
84da2e3ebdSchin #if SHOPT_BASH
857c2fbfb3SApril Chin     extern void bash_init(Shell_t*,int);
86da2e3ebdSchin #endif
87da2e3ebdSchin 
88da2e3ebdSchin #define RANDMASK	0x7fff
897c2fbfb3SApril Chin 
907c2fbfb3SApril Chin #ifndef ARG_MAX
917c2fbfb3SApril Chin #   define ARG_MAX	(1*1024*1024)
927c2fbfb3SApril Chin #endif
937c2fbfb3SApril Chin #ifndef CHILD_MAX
947c2fbfb3SApril Chin #   define CHILD_MAX	(1*1024)
957c2fbfb3SApril Chin #endif
96da2e3ebdSchin #ifndef CLK_TCK
97da2e3ebdSchin #   define CLK_TCK	60
98da2e3ebdSchin #endif /* CLK_TCK */
99da2e3ebdSchin 
100da2e3ebdSchin #ifndef environ
101da2e3ebdSchin     extern char	**environ;
102da2e3ebdSchin #endif
103da2e3ebdSchin 
104da2e3ebdSchin #undef	getconf
105da2e3ebdSchin #define getconf(x)	strtol(astconf(x,NiL,NiL),NiL,0)
106da2e3ebdSchin 
107da2e3ebdSchin struct seconds
108da2e3ebdSchin {
109da2e3ebdSchin 	Namfun_t	hdr;
110da2e3ebdSchin 	Shell_t		*sh;
111da2e3ebdSchin };
112da2e3ebdSchin 
113da2e3ebdSchin struct rand
114da2e3ebdSchin {
115da2e3ebdSchin 	Namfun_t	hdr;
116da2e3ebdSchin 	int32_t		rand_last;
117da2e3ebdSchin };
118da2e3ebdSchin 
119da2e3ebdSchin struct ifs
120da2e3ebdSchin {
121da2e3ebdSchin 	Namfun_t	hdr;
122da2e3ebdSchin 	Namval_t	*ifsnp;
123da2e3ebdSchin };
124da2e3ebdSchin 
125da2e3ebdSchin struct match
126da2e3ebdSchin {
127da2e3ebdSchin 	Namfun_t	hdr;
128da2e3ebdSchin 	char		*val;
129da2e3ebdSchin 	char		*rval;
130da2e3ebdSchin 	int		vsize;
131da2e3ebdSchin 	int		nmatch;
132da2e3ebdSchin 	int		lastsub;
133da2e3ebdSchin 	int		match[2*(MATCH_MAX+1)];
134da2e3ebdSchin };
135da2e3ebdSchin 
136da2e3ebdSchin typedef struct _init_
137da2e3ebdSchin {
138da2e3ebdSchin 	Shell_t		*sh;
139da2e3ebdSchin #if SHOPT_FS_3D
140da2e3ebdSchin 	Namfun_t	VPATH_init;
141da2e3ebdSchin #endif /* SHOPT_FS_3D */
142da2e3ebdSchin 	struct ifs	IFS_init;
1437c2fbfb3SApril Chin 	Namfun_t	PATH_init;
1447c2fbfb3SApril Chin 	Namfun_t	FPATH_init;
1457c2fbfb3SApril Chin 	Namfun_t	CDPATH_init;
1467c2fbfb3SApril Chin 	Namfun_t	SHELL_init;
1477c2fbfb3SApril Chin 	Namfun_t	ENV_init;
1487c2fbfb3SApril Chin 	Namfun_t	VISUAL_init;
1497c2fbfb3SApril Chin 	Namfun_t	EDITOR_init;
1507c2fbfb3SApril Chin 	Namfun_t	HISTFILE_init;
1517c2fbfb3SApril Chin 	Namfun_t	HISTSIZE_init;
1527c2fbfb3SApril Chin 	Namfun_t	OPTINDEX_init;
153da2e3ebdSchin 	struct seconds	SECONDS_init;
154da2e3ebdSchin 	struct rand	RAND_init;
1557c2fbfb3SApril Chin 	Namfun_t	LINENO_init;
1567c2fbfb3SApril Chin 	Namfun_t	L_ARG_init;
1577c2fbfb3SApril Chin 	Namfun_t	SH_VERSION_init;
158da2e3ebdSchin 	struct match	SH_MATCH_init;
159da2e3ebdSchin #ifdef _hdr_locale
1607c2fbfb3SApril Chin 	Namfun_t	LC_TYPE_init;
1617c2fbfb3SApril Chin 	Namfun_t	LC_NUM_init;
1627c2fbfb3SApril Chin 	Namfun_t	LC_COLL_init;
1637c2fbfb3SApril Chin 	Namfun_t	LC_MSG_init;
1647c2fbfb3SApril Chin 	Namfun_t	LC_ALL_init;
1657c2fbfb3SApril Chin 	Namfun_t	LANG_init;
166da2e3ebdSchin #endif /* _hdr_locale */
167da2e3ebdSchin } Init_t;
168da2e3ebdSchin 
1697c2fbfb3SApril Chin static int		nbltins;
170da2e3ebdSchin static void		env_init(Shell_t*);
171da2e3ebdSchin static Init_t		*nv_init(Shell_t*);
172da2e3ebdSchin static Dt_t		*inittree(Shell_t*,const struct shtable2*);
17334f9b3eeSRoland Mainz static int		shlvl;
174da2e3ebdSchin 
175da2e3ebdSchin #ifdef _WINIX
176da2e3ebdSchin #   define EXE	"?(.exe)"
177da2e3ebdSchin #else
178da2e3ebdSchin #   define EXE
179da2e3ebdSchin #endif
180da2e3ebdSchin 
181da2e3ebdSchin static int		rand_shift;
182da2e3ebdSchin 
183da2e3ebdSchin 
184da2e3ebdSchin /*
185da2e3ebdSchin  * Invalidate all path name bindings
186da2e3ebdSchin  */
rehash(register Namval_t * np,void * data)187da2e3ebdSchin static void rehash(register Namval_t *np,void *data)
188da2e3ebdSchin {
189da2e3ebdSchin 	NOT_USED(data);
190da2e3ebdSchin 	nv_onattr(np,NV_NOALIAS);
191da2e3ebdSchin }
192da2e3ebdSchin 
193da2e3ebdSchin /*
194da2e3ebdSchin  * out of memory routine for stak routines
195da2e3ebdSchin  */
nospace(int unused)196da2e3ebdSchin static char *nospace(int unused)
197da2e3ebdSchin {
198da2e3ebdSchin 	NOT_USED(unused);
199da2e3ebdSchin 	errormsg(SH_DICT,ERROR_exit(3),e_nospace);
200da2e3ebdSchin 	return(NIL(char*));
201da2e3ebdSchin }
202da2e3ebdSchin 
203da2e3ebdSchin /* Trap for VISUAL and EDITOR variables */
put_ed(register Namval_t * np,const char * val,int flags,Namfun_t * fp)204da2e3ebdSchin static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
205da2e3ebdSchin {
206da2e3ebdSchin 	register const char *cp, *name=nv_name(np);
20734f9b3eeSRoland Mainz 	register int	newopt=0;
2087c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
2097c2fbfb3SApril Chin 	if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
210da2e3ebdSchin 		goto done;
2117c2fbfb3SApril Chin 	if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
212da2e3ebdSchin 		goto done;
213da2e3ebdSchin 	/* turn on vi or emacs option if editor name is either*/
214da2e3ebdSchin 	cp = path_basename(cp);
215da2e3ebdSchin 	if(strmatch(cp,"*[Vv][Ii]*"))
21634f9b3eeSRoland Mainz 		newopt=SH_VI;
217da2e3ebdSchin 	else if(strmatch(cp,"*gmacs*"))
21834f9b3eeSRoland Mainz 		newopt=SH_GMACS;
219da2e3ebdSchin 	else if(strmatch(cp,"*macs*"))
22034f9b3eeSRoland Mainz 		newopt=SH_EMACS;
22134f9b3eeSRoland Mainz 	if(newopt)
22234f9b3eeSRoland Mainz 	{
22334f9b3eeSRoland Mainz 		sh_offoption(SH_VI);
22434f9b3eeSRoland Mainz 		sh_offoption(SH_EMACS);
22534f9b3eeSRoland Mainz 		sh_offoption(SH_GMACS);
22634f9b3eeSRoland Mainz 		sh_onoption(newopt);
22734f9b3eeSRoland Mainz 	}
228da2e3ebdSchin done:
229da2e3ebdSchin 	nv_putv(np, val, flags, fp);
230da2e3ebdSchin }
231da2e3ebdSchin 
2327c2fbfb3SApril Chin /* Trap for HISTFILE and HISTSIZE variables */
put_history(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2337c2fbfb3SApril Chin static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2347c2fbfb3SApril Chin {
2357c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
2367c2fbfb3SApril Chin 	void 	*histopen = shp->hist_ptr;
23734f9b3eeSRoland Mainz 	char	*cp;
2387c2fbfb3SApril Chin 	if(val && histopen)
2397c2fbfb3SApril Chin 	{
24034f9b3eeSRoland Mainz 		if(np==HISTFILE && (cp=nv_getval(np)) && strcmp(val,cp)==0)
2417c2fbfb3SApril Chin 			return;
2427c2fbfb3SApril Chin 		if(np==HISTSIZE && sh_arith(val)==nv_getnum(HISTSIZE))
2437c2fbfb3SApril Chin 			return;
2447c2fbfb3SApril Chin 		hist_close(shp->hist_ptr);
2457c2fbfb3SApril Chin 	}
2467c2fbfb3SApril Chin 	nv_putv(np, val, flags, fp);
2477c2fbfb3SApril Chin 	if(histopen)
2487c2fbfb3SApril Chin 	{
2497c2fbfb3SApril Chin 		if(val)
2507c2fbfb3SApril Chin 			sh_histinit(shp);
2517c2fbfb3SApril Chin 		else
2527c2fbfb3SApril Chin 			hist_close(histopen);
2537c2fbfb3SApril Chin 	}
2547c2fbfb3SApril Chin }
2557c2fbfb3SApril Chin 
256da2e3ebdSchin /* Trap for OPTINDEX */
put_optindex(Namval_t * np,const char * val,int flags,Namfun_t * fp)257da2e3ebdSchin static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
258da2e3ebdSchin {
2597c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
260da2e3ebdSchin 	shp->st.opterror = shp->st.optchar = 0;
261da2e3ebdSchin 	nv_putv(np, val, flags, fp);
2627c2fbfb3SApril Chin 	if(!val)
2637c2fbfb3SApril Chin 		nv_disc(np,fp,NV_POP);
264da2e3ebdSchin }
265da2e3ebdSchin 
nget_optindex(register Namval_t * np,Namfun_t * fp)266da2e3ebdSchin static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp)
267da2e3ebdSchin {
268da2e3ebdSchin 	return((Sfdouble_t)*np->nvalue.lp);
269da2e3ebdSchin }
270da2e3ebdSchin 
clone_optindex(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)2717c2fbfb3SApril Chin static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
2727c2fbfb3SApril Chin {
2737c2fbfb3SApril Chin 	Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t));
2747c2fbfb3SApril Chin 	memcpy((void*)dp,(void*)fp,sizeof(Namfun_t));
2757c2fbfb3SApril Chin 	mp->nvalue.lp = np->nvalue.lp;
2767c2fbfb3SApril Chin 	dp->nofree = 0;
2777c2fbfb3SApril Chin 	return(dp);
2787c2fbfb3SApril Chin }
2797c2fbfb3SApril Chin 
2807c2fbfb3SApril Chin 
281da2e3ebdSchin /* Trap for restricted variables FPATH, PATH, SHELL, ENV */
put_restricted(register Namval_t * np,const char * val,int flags,Namfun_t * fp)282da2e3ebdSchin static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
283da2e3ebdSchin {
2847c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
285da2e3ebdSchin 	int	path_scoped = 0;
286da2e3ebdSchin 	Pathcomp_t *pp;
287da2e3ebdSchin 	char *name = nv_name(np);
288da2e3ebdSchin 	if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED))
289da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
290da2e3ebdSchin 	if(np==PATHNOD	|| (path_scoped=(strcmp(name,PATHNOD->nvname)==0)))
291da2e3ebdSchin 	{
292da2e3ebdSchin 		nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
293da2e3ebdSchin 		if(path_scoped && !val)
294da2e3ebdSchin 			val = PATHNOD->nvalue.cp;
295da2e3ebdSchin 	}
296da2e3ebdSchin 	if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0)
297da2e3ebdSchin 		 return;
2987c2fbfb3SApril Chin 	if(np==FPATHNOD)
299da2e3ebdSchin 		shp->pathlist = (void*)path_unsetfpath((Pathcomp_t*)shp->pathlist);
300da2e3ebdSchin 	nv_putv(np, val, flags, fp);
3017c2fbfb3SApril Chin 	shp->universe = 0;
302da2e3ebdSchin 	if(shp->pathlist)
303da2e3ebdSchin 	{
304da2e3ebdSchin 		val = np->nvalue.cp;
305da2e3ebdSchin 		if(np==PATHNOD || path_scoped)
306da2e3ebdSchin 			pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_PATH);
307da2e3ebdSchin 		else if(val && np==FPATHNOD)
308da2e3ebdSchin 			pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
309da2e3ebdSchin 		else
310da2e3ebdSchin 			return;
311da2e3ebdSchin 		if(shp->pathlist = (void*)pp)
312da2e3ebdSchin 			pp->shp = shp;
313da2e3ebdSchin 		if(!val && (flags&NV_NOSCOPE))
314da2e3ebdSchin 		{
315da2e3ebdSchin 			Namval_t *mp = dtsearch(shp->var_tree,np);
316da2e3ebdSchin 			if(mp && (val=nv_getval(mp)))
317da2e3ebdSchin 				nv_putval(mp,val,NV_RDONLY);
318da2e3ebdSchin 		}
319da2e3ebdSchin #if 0
320da2e3ebdSchin sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val);
321da2e3ebdSchin path_dump((Pathcomp_t*)shp->pathlist);
322da2e3ebdSchin #endif
323da2e3ebdSchin 	}
324da2e3ebdSchin }
325da2e3ebdSchin 
put_cdpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)326da2e3ebdSchin static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
327da2e3ebdSchin {
328da2e3ebdSchin 	Pathcomp_t *pp;
3297c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
330da2e3ebdSchin 	nv_putv(np, val, flags, fp);
331da2e3ebdSchin 	if(!shp->cdpathlist)
332da2e3ebdSchin 		return;
333da2e3ebdSchin 	val = np->nvalue.cp;
334da2e3ebdSchin 	pp = (void*)path_addpath((Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH);
335da2e3ebdSchin 	if(shp->cdpathlist = (void*)pp)
336da2e3ebdSchin 		pp->shp = shp;
337da2e3ebdSchin }
338da2e3ebdSchin 
339da2e3ebdSchin #ifdef _hdr_locale
340da2e3ebdSchin     /*
341da2e3ebdSchin      * This function needs to be modified to handle international
342da2e3ebdSchin      * error message translations
343da2e3ebdSchin      */
344da2e3ebdSchin #if ERROR_VERSION >= 20000101L
msg_translate(const char * catalog,const char * message)345da2e3ebdSchin     static char* msg_translate(const char* catalog, const char* message)
346da2e3ebdSchin     {
347da2e3ebdSchin 	NOT_USED(catalog);
348da2e3ebdSchin 	return((char*)message);
349da2e3ebdSchin     }
350da2e3ebdSchin #else
msg_translate(const char * message,int type)351da2e3ebdSchin     static char* msg_translate(const char* message, int type)
352da2e3ebdSchin     {
353da2e3ebdSchin 	NOT_USED(type);
354da2e3ebdSchin 	return((char*)message);
355da2e3ebdSchin     }
356da2e3ebdSchin #endif
357da2e3ebdSchin 
35834f9b3eeSRoland Mainz     /* Trap for LC_ALL, LC_CTYPE, LC_MESSAGES, LC_COLLATE and LANG */
put_lang(Namval_t * np,const char * val,int flags,Namfun_t * fp)359da2e3ebdSchin     static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
360da2e3ebdSchin     {
3617c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
362da2e3ebdSchin 	int type;
363*3e14f97fSRoger A. Faulkner 	char *cp;
364da2e3ebdSchin 	char *name = nv_name(np);
365da2e3ebdSchin 	if(name==(LCALLNOD)->nvname)
366da2e3ebdSchin 		type = LC_ALL;
367da2e3ebdSchin 	else if(name==(LCTYPENOD)->nvname)
368da2e3ebdSchin 		type = LC_CTYPE;
369da2e3ebdSchin 	else if(name==(LCMSGNOD)->nvname)
370da2e3ebdSchin 		type = LC_MESSAGES;
371da2e3ebdSchin 	else if(name==(LCCOLLNOD)->nvname)
372da2e3ebdSchin 		type = LC_COLLATE;
373da2e3ebdSchin 	else if(name==(LCNUMNOD)->nvname)
374da2e3ebdSchin 		type = LC_NUMERIC;
37534f9b3eeSRoland Mainz #ifdef LC_LANG
37634f9b3eeSRoland Mainz 	else if(name==(LANGNOD)->nvname)
37734f9b3eeSRoland Mainz 		type = LC_LANG;
37834f9b3eeSRoland Mainz #else
37934f9b3eeSRoland Mainz #define LC_LANG		LC_ALL
380*3e14f97fSRoger A. Faulkner 	else if(name==(LANGNOD)->nvname && (!(cp=nv_getval(LCALLNOD)) || !*cp))
38134f9b3eeSRoland Mainz 		type = LC_LANG;
38234f9b3eeSRoland Mainz #endif
383da2e3ebdSchin 	else
384da2e3ebdSchin 		type= -1;
385*3e14f97fSRoger A. Faulkner 	if(!sh_isstate(SH_INIT) && (type>=0 || type==LC_ALL || type==LC_LANG))
386da2e3ebdSchin 	{
387*3e14f97fSRoger A. Faulkner 		struct lconv*	lc;
388*3e14f97fSRoger A. Faulkner 		char*		r;
389*3e14f97fSRoger A. Faulkner #ifdef AST_LC_setenv
390*3e14f97fSRoger A. Faulkner 		ast.locale.set |= AST_LC_setenv;
391*3e14f97fSRoger A. Faulkner #endif
392*3e14f97fSRoger A. Faulkner 		r = setlocale(type,val?val:"");
393*3e14f97fSRoger A. Faulkner #ifdef AST_LC_setenv
394*3e14f97fSRoger A. Faulkner 		ast.locale.set ^= AST_LC_setenv;
395*3e14f97fSRoger A. Faulkner #endif
396*3e14f97fSRoger A. Faulkner 		if(!r && val)
397da2e3ebdSchin 		{
3987c2fbfb3SApril Chin 			if(!sh_isstate(SH_INIT) || shp->login_sh==0)
399da2e3ebdSchin 				errormsg(SH_DICT,0,e_badlocale,val);
400da2e3ebdSchin 			return;
401da2e3ebdSchin 		}
402*3e14f97fSRoger A. Faulkner 		shp->decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
403da2e3ebdSchin 	}
40434f9b3eeSRoland Mainz 	nv_putv(np, val, flags, fp);
405*3e14f97fSRoger A. Faulkner 	if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
406da2e3ebdSchin 	{
407da2e3ebdSchin 		if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
408da2e3ebdSchin 			free((void*)sh_lexstates[ST_BEGIN]);
409da2e3ebdSchin 		if(ast.locale.set&(1<<AST_LC_CTYPE))
410da2e3ebdSchin 		{
411da2e3ebdSchin 			register int c;
412da2e3ebdSchin 			char *state[4];
413da2e3ebdSchin 			sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT));
414da2e3ebdSchin 			memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT));
415da2e3ebdSchin 			sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT);
416da2e3ebdSchin 			memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT));
417da2e3ebdSchin 			sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT);
418da2e3ebdSchin 			memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT));
419da2e3ebdSchin 			sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT);
420da2e3ebdSchin 			memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT));
421da2e3ebdSchin 			for(c=0; c<(1<<CHAR_BIT); c++)
422da2e3ebdSchin 			{
423da2e3ebdSchin 				if(state[0][c]!=S_REG)
424da2e3ebdSchin 					continue;
425da2e3ebdSchin 				if(state[2][c]!=S_ERR)
426da2e3ebdSchin 					continue;
427da2e3ebdSchin 				if(isblank(c))
428da2e3ebdSchin 				{
429da2e3ebdSchin 					state[0][c]=0;
430da2e3ebdSchin 					state[1][c]=S_BREAK;
431da2e3ebdSchin 					state[2][c]=S_BREAK;
432da2e3ebdSchin 					continue;
433da2e3ebdSchin 				}
434da2e3ebdSchin 				if(!isalpha(c))
435da2e3ebdSchin 					continue;
436da2e3ebdSchin 				state[0][c]=S_NAME;
437da2e3ebdSchin 				if(state[1][c]==S_REG)
438da2e3ebdSchin 					state[1][c]=0;
439da2e3ebdSchin 				state[2][c]=S_ALP;
440da2e3ebdSchin 				if(state[3][c]==S_ERR)
441da2e3ebdSchin 					state[3][c]=0;
442da2e3ebdSchin 			}
443da2e3ebdSchin 		}
444da2e3ebdSchin 		else
445da2e3ebdSchin 		{
446da2e3ebdSchin 			sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN];
447da2e3ebdSchin 			sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME];
448da2e3ebdSchin 			sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL];
449da2e3ebdSchin 			sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE];
450da2e3ebdSchin 		}
451da2e3ebdSchin 	}
452da2e3ebdSchin #if ERROR_VERSION < 20000101L
453da2e3ebdSchin 	if(type==LC_ALL || type==LC_MESSAGES)
454da2e3ebdSchin 		error_info.translate = msg_translate;
455da2e3ebdSchin #endif
456da2e3ebdSchin     }
457da2e3ebdSchin #endif /* _hdr_locale */
458da2e3ebdSchin 
459da2e3ebdSchin /* Trap for IFS assignment and invalidates state table */
put_ifs(register Namval_t * np,const char * val,int flags,Namfun_t * fp)460da2e3ebdSchin static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
461da2e3ebdSchin {
462da2e3ebdSchin 	register struct ifs *ip = (struct ifs*)fp;
46334f9b3eeSRoland Mainz 	Shell_t		*shp;
464da2e3ebdSchin 	ip->ifsnp = 0;
46534f9b3eeSRoland Mainz 	if(!val)
46634f9b3eeSRoland Mainz 	{
46734f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
46834f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
46934f9b3eeSRoland Mainz 			free((void*)fp);
47034f9b3eeSRoland Mainz 	}
471da2e3ebdSchin 	if(val != np->nvalue.cp)
472da2e3ebdSchin 		nv_putv(np, val, flags, fp);
47334f9b3eeSRoland Mainz 	if(!val && !(flags&NV_CLONE) && (fp=np->nvfun) && !fp->disc && (shp=(Shell_t*)(fp->last)))
47434f9b3eeSRoland Mainz 		nv_stack(np,&((Init_t*)shp->init_context)->IFS_init.hdr);
475da2e3ebdSchin }
476da2e3ebdSchin 
477da2e3ebdSchin /*
478da2e3ebdSchin  * This is the lookup function for IFS
479da2e3ebdSchin  * It keeps the sh.ifstable up to date
480da2e3ebdSchin  */
get_ifs(register Namval_t * np,Namfun_t * fp)481da2e3ebdSchin static char* get_ifs(register Namval_t* np, Namfun_t *fp)
482da2e3ebdSchin {
483da2e3ebdSchin 	register struct ifs *ip = (struct ifs*)fp;
484da2e3ebdSchin 	register char *cp, *value;
485da2e3ebdSchin 	register int c,n;
4867c2fbfb3SApril Chin 	register Shell_t *shp = nv_shell(np);
487da2e3ebdSchin 	value = nv_getv(np,fp);
488da2e3ebdSchin 	if(np!=ip->ifsnp)
489da2e3ebdSchin 	{
490da2e3ebdSchin 		ip->ifsnp = np;
491da2e3ebdSchin 		memset(shp->ifstable,0,(1<<CHAR_BIT));
492da2e3ebdSchin 		if(cp=value)
493da2e3ebdSchin 		{
494da2e3ebdSchin #if SHOPT_MULTIBYTE
495da2e3ebdSchin 			while(n=mbsize(cp),c= *(unsigned char*)cp)
496da2e3ebdSchin #else
497da2e3ebdSchin 			while(c= *(unsigned char*)cp++)
498da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
499da2e3ebdSchin 			{
500da2e3ebdSchin #if SHOPT_MULTIBYTE
501da2e3ebdSchin 				cp++;
502da2e3ebdSchin 				if(n>1)
503da2e3ebdSchin 				{
504da2e3ebdSchin 					cp += (n-1);
505da2e3ebdSchin 					shp->ifstable[c] = S_MBYTE;
506da2e3ebdSchin 					continue;
507da2e3ebdSchin 				}
508da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
509da2e3ebdSchin 				n = S_DELIM;
510da2e3ebdSchin 				if(c== *cp)
511da2e3ebdSchin 					cp++;
512da2e3ebdSchin 				else if(c=='\n')
513da2e3ebdSchin 					n = S_NL;
514da2e3ebdSchin 				else if(isspace(c))
515da2e3ebdSchin 					n = S_SPACE;
516da2e3ebdSchin 				shp->ifstable[c] = n;
517da2e3ebdSchin 			}
518da2e3ebdSchin 		}
519da2e3ebdSchin 		else
520da2e3ebdSchin 		{
521da2e3ebdSchin 			shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
522da2e3ebdSchin 			shp->ifstable['\n'] = S_NL;
523da2e3ebdSchin 		}
524da2e3ebdSchin 	}
525da2e3ebdSchin 	return(value);
526da2e3ebdSchin }
527da2e3ebdSchin 
528da2e3ebdSchin /*
529da2e3ebdSchin  * these functions are used to get and set the SECONDS variable
530da2e3ebdSchin  */
531da2e3ebdSchin #ifdef timeofday
532da2e3ebdSchin #   define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec)))
533da2e3ebdSchin #   define tms	timeval
534da2e3ebdSchin #else
535da2e3ebdSchin #   define dtime(tp)	(((double)times(tp))/sh.lim.clk_tck)
536da2e3ebdSchin #   define timeofday(a)
537da2e3ebdSchin #endif
538da2e3ebdSchin 
put_seconds(register Namval_t * np,const char * val,int flags,Namfun_t * fp)539da2e3ebdSchin static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
540da2e3ebdSchin {
541da2e3ebdSchin 	double d;
542da2e3ebdSchin 	struct tms tp;
543da2e3ebdSchin 	if(!val)
544da2e3ebdSchin 	{
54534f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
54634f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
54734f9b3eeSRoland Mainz 			free((void*)fp);
54834f9b3eeSRoland Mainz 		nv_putv(np, val, flags, fp);
549da2e3ebdSchin 		return;
550da2e3ebdSchin 	}
551da2e3ebdSchin 	if(!np->nvalue.dp)
552da2e3ebdSchin 	{
553da2e3ebdSchin 		nv_setsize(np,3);
5547c2fbfb3SApril Chin 		nv_onattr(np,NV_DOUBLE);
555da2e3ebdSchin 		np->nvalue.dp = new_of(double,0);
556da2e3ebdSchin 	}
557da2e3ebdSchin 	nv_putv(np, val, flags, fp);
558da2e3ebdSchin 	d = *np->nvalue.dp;
559da2e3ebdSchin 	timeofday(&tp);
560da2e3ebdSchin 	*np->nvalue.dp = dtime(&tp)-d;
561da2e3ebdSchin }
562da2e3ebdSchin 
get_seconds(register Namval_t * np,Namfun_t * fp)563da2e3ebdSchin static char* get_seconds(register Namval_t* np, Namfun_t *fp)
564da2e3ebdSchin {
5657c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
566da2e3ebdSchin 	register int places = nv_size(np);
567da2e3ebdSchin 	struct tms tp;
568da2e3ebdSchin 	double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
569da2e3ebdSchin 	NOT_USED(fp);
570da2e3ebdSchin 	timeofday(&tp);
571da2e3ebdSchin 	d = dtime(&tp)- offset;
5727c2fbfb3SApril Chin 	sfprintf(shp->strbuf,"%.*f",places,d);
5737c2fbfb3SApril Chin 	return(sfstruse(shp->strbuf));
574da2e3ebdSchin }
575da2e3ebdSchin 
nget_seconds(register Namval_t * np,Namfun_t * fp)576da2e3ebdSchin static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp)
577da2e3ebdSchin {
578da2e3ebdSchin 	struct tms tp;
579da2e3ebdSchin 	double offset = (np->nvalue.dp?*np->nvalue.dp:0);
580da2e3ebdSchin 	NOT_USED(fp);
581da2e3ebdSchin 	timeofday(&tp);
582da2e3ebdSchin 	return(dtime(&tp)- offset);
583da2e3ebdSchin }
584da2e3ebdSchin 
585da2e3ebdSchin /*
586da2e3ebdSchin  * These three functions are used to get and set the RANDOM variable
587da2e3ebdSchin  */
put_rand(register Namval_t * np,const char * val,int flags,Namfun_t * fp)588da2e3ebdSchin static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
589da2e3ebdSchin {
590da2e3ebdSchin 	struct rand *rp = (struct rand*)fp;
591da2e3ebdSchin 	register long n;
592da2e3ebdSchin 	if(!val)
593da2e3ebdSchin 	{
59434f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
59534f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
59634f9b3eeSRoland Mainz 			free((void*)fp);
597da2e3ebdSchin 		nv_unset(np);
598da2e3ebdSchin 		return;
599da2e3ebdSchin 	}
600da2e3ebdSchin 	if(flags&NV_INTEGER)
601da2e3ebdSchin 		n = *(double*)val;
602da2e3ebdSchin 	else
603da2e3ebdSchin 		n = sh_arith(val);
604da2e3ebdSchin 	srand((int)(n&RANDMASK));
605da2e3ebdSchin 	rp->rand_last = -1;
606da2e3ebdSchin 	if(!np->nvalue.lp)
607da2e3ebdSchin 		np->nvalue.lp = &rp->rand_last;
608da2e3ebdSchin }
609da2e3ebdSchin 
610da2e3ebdSchin /*
611da2e3ebdSchin  * get random number in range of 0 - 2**15
612da2e3ebdSchin  * never pick same number twice in a row
613da2e3ebdSchin  */
nget_rand(register Namval_t * np,Namfun_t * fp)614da2e3ebdSchin static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp)
615da2e3ebdSchin {
616da2e3ebdSchin 	register long cur, last= *np->nvalue.lp;
617da2e3ebdSchin 	NOT_USED(fp);
618da2e3ebdSchin 	do
619da2e3ebdSchin 		cur = (rand()>>rand_shift)&RANDMASK;
620da2e3ebdSchin 	while(cur==last);
621da2e3ebdSchin 	*np->nvalue.lp = cur;
622da2e3ebdSchin 	return((Sfdouble_t)cur);
623da2e3ebdSchin }
624da2e3ebdSchin 
get_rand(register Namval_t * np,Namfun_t * fp)625da2e3ebdSchin static char* get_rand(register Namval_t* np, Namfun_t *fp)
626da2e3ebdSchin {
627da2e3ebdSchin 	register long n = nget_rand(np,fp);
628da2e3ebdSchin 	return(fmtbase(n, 10, 0));
629da2e3ebdSchin }
630da2e3ebdSchin 
631da2e3ebdSchin /*
632da2e3ebdSchin  * These three routines are for LINENO
633da2e3ebdSchin  */
nget_lineno(Namval_t * np,Namfun_t * fp)634da2e3ebdSchin static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
635da2e3ebdSchin {
636da2e3ebdSchin 	double d=1;
637da2e3ebdSchin 	if(error_info.line >0)
638da2e3ebdSchin 		d = error_info.line;
639da2e3ebdSchin 	else if(error_info.context && error_info.context->line>0)
640da2e3ebdSchin 		d = error_info.context->line;
641da2e3ebdSchin 	NOT_USED(np);
642da2e3ebdSchin 	NOT_USED(fp);
643da2e3ebdSchin 	return(d);
644da2e3ebdSchin }
645da2e3ebdSchin 
put_lineno(Namval_t * np,const char * val,int flags,Namfun_t * fp)646da2e3ebdSchin static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
647da2e3ebdSchin {
648da2e3ebdSchin 	register long n;
6497c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
650da2e3ebdSchin 	if(!val)
651da2e3ebdSchin 	{
65234f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
65334f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
65434f9b3eeSRoland Mainz 			free((void*)fp);
655da2e3ebdSchin 		nv_unset(np);
656da2e3ebdSchin 		return;
657da2e3ebdSchin 	}
658da2e3ebdSchin 	if(flags&NV_INTEGER)
659da2e3ebdSchin 		n = *(double*)val;
660da2e3ebdSchin 	else
661da2e3ebdSchin 		n = sh_arith(val);
662da2e3ebdSchin 	shp->st.firstline += nget_lineno(np,fp)+1-n;
663da2e3ebdSchin }
664da2e3ebdSchin 
get_lineno(register Namval_t * np,Namfun_t * fp)665da2e3ebdSchin static char* get_lineno(register Namval_t* np, Namfun_t *fp)
666da2e3ebdSchin {
667da2e3ebdSchin 	register long n = nget_lineno(np,fp);
668da2e3ebdSchin 	return(fmtbase(n, 10, 0));
669da2e3ebdSchin }
670da2e3ebdSchin 
get_lastarg(Namval_t * np,Namfun_t * fp)671da2e3ebdSchin static char* get_lastarg(Namval_t* np, Namfun_t *fp)
672da2e3ebdSchin {
6737c2fbfb3SApril Chin 	Shell_t	*shp = nv_shell(np);
67434f9b3eeSRoland Mainz 	char	*cp;
67534f9b3eeSRoland Mainz 	int	pid;
67634f9b3eeSRoland Mainz         if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
67734f9b3eeSRoland Mainz 		nv_putval(np,(pid==getppid()?cp+1:0),0);
6787c2fbfb3SApril Chin 	return(shp->lastarg);
679da2e3ebdSchin }
680da2e3ebdSchin 
put_lastarg(Namval_t * np,const char * val,int flags,Namfun_t * fp)681da2e3ebdSchin static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
682da2e3ebdSchin {
6837c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
684da2e3ebdSchin 	if(flags&NV_INTEGER)
685da2e3ebdSchin 	{
6867c2fbfb3SApril Chin 		sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
6877c2fbfb3SApril Chin 		val = sfstruse(shp->strbuf);
688da2e3ebdSchin 	}
68934f9b3eeSRoland Mainz 	if(val)
69034f9b3eeSRoland Mainz 		val = strdup(val);
6917c2fbfb3SApril Chin 	if(shp->lastarg && !nv_isattr(np,NV_NOFREE))
6927c2fbfb3SApril Chin 		free((void*)shp->lastarg);
693da2e3ebdSchin 	else
694da2e3ebdSchin 		nv_offattr(np,NV_NOFREE);
69534f9b3eeSRoland Mainz 	shp->lastarg = (char*)val;
69634f9b3eeSRoland Mainz 	nv_offattr(np,NV_EXPORT);
69734f9b3eeSRoland Mainz 	np->nvenv = 0;
698da2e3ebdSchin }
699da2e3ebdSchin 
hasgetdisc(register Namfun_t * fp)700da2e3ebdSchin static int hasgetdisc(register Namfun_t *fp)
701da2e3ebdSchin {
702da2e3ebdSchin         while(fp && !fp->disc->getnum && !fp->disc->getval)
703da2e3ebdSchin                 fp = fp->next;
704da2e3ebdSchin 	return(fp!=0);
705da2e3ebdSchin }
706da2e3ebdSchin 
707da2e3ebdSchin /*
708da2e3ebdSchin  * store the most recent value for use in .sh.match
709da2e3ebdSchin  */
sh_setmatch(const char * v,int vsize,int nmatch,int match[])710da2e3ebdSchin void sh_setmatch(const char *v, int vsize, int nmatch, int match[])
711da2e3ebdSchin {
712da2e3ebdSchin 	struct match *mp = (struct match*)(SH_MATCHNOD->nvfun);
713da2e3ebdSchin 	register int i,n;
714da2e3ebdSchin 	if(mp->nmatch = nmatch)
715da2e3ebdSchin 	{
716da2e3ebdSchin 		memcpy(mp->match,match,nmatch*2*sizeof(match[0]));
717da2e3ebdSchin 		for(n=match[0],i=1; i < 2*nmatch; i++)
718da2e3ebdSchin 		{
719da2e3ebdSchin 			if(mp->match[i] < n)
720da2e3ebdSchin 				n = mp->match[i];
721da2e3ebdSchin 		}
722da2e3ebdSchin 		for(vsize=0,i=0; i < 2*nmatch; i++)
723da2e3ebdSchin 		{
724da2e3ebdSchin 			if((mp->match[i] -= n) > vsize)
725da2e3ebdSchin 				vsize = mp->match[i];
726da2e3ebdSchin 		}
727da2e3ebdSchin 		v += n;
728da2e3ebdSchin 		if(vsize >= mp->vsize)
729da2e3ebdSchin 		{
730da2e3ebdSchin 			if(mp->vsize)
731da2e3ebdSchin 				mp->val = (char*)realloc(mp->val,vsize+1);
732da2e3ebdSchin 			else
733da2e3ebdSchin 				mp->val = (char*)malloc(vsize+1);
734da2e3ebdSchin 			mp->vsize = vsize;
735da2e3ebdSchin 		}
736da2e3ebdSchin 		memcpy(mp->val,v,vsize);
737da2e3ebdSchin 		mp->val[vsize] = 0;
7387c2fbfb3SApril Chin 		nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL);
739da2e3ebdSchin 		mp->lastsub = -1;
740da2e3ebdSchin 	}
741da2e3ebdSchin }
742da2e3ebdSchin 
743da2e3ebdSchin #define array_scan(np)	((nv_arrayptr(np)->nelem&ARRAY_SCAN))
744da2e3ebdSchin 
get_match(register Namval_t * np,Namfun_t * fp)745da2e3ebdSchin static char* get_match(register Namval_t* np, Namfun_t *fp)
746da2e3ebdSchin {
747da2e3ebdSchin 	struct match *mp = (struct match*)fp;
748da2e3ebdSchin 	int sub,n;
749da2e3ebdSchin 	char *val;
750da2e3ebdSchin 	sub = nv_aindex(np);
751da2e3ebdSchin 	if(sub>=mp->nmatch)
752da2e3ebdSchin 		return(0);
753da2e3ebdSchin 	if(sub==mp->lastsub)
754da2e3ebdSchin 		return(mp->rval);
755da2e3ebdSchin 	if(mp->rval)
756da2e3ebdSchin 	{
757da2e3ebdSchin 		free((void*)mp->rval);
758da2e3ebdSchin 		mp->rval = 0;
759da2e3ebdSchin 	}
760da2e3ebdSchin 	n = mp->match[2*sub+1]-mp->match[2*sub];
761da2e3ebdSchin 	if(n<=0)
762da2e3ebdSchin 		return("");
763da2e3ebdSchin 	val = mp->val+mp->match[2*sub];
764da2e3ebdSchin 	if(mp->val[mp->match[2*sub+1]]==0)
765da2e3ebdSchin 		return(val);
766da2e3ebdSchin 	mp->rval = (char*)malloc(n+1);
767da2e3ebdSchin 	mp->lastsub = sub;
768da2e3ebdSchin 	memcpy(mp->rval,val,n);
769da2e3ebdSchin 	mp->rval[n] = 0;
770da2e3ebdSchin 	return(mp->rval);
771da2e3ebdSchin }
772da2e3ebdSchin 
773da2e3ebdSchin static const Namdisc_t SH_MATCH_disc  = { sizeof(struct match), 0, get_match };
774da2e3ebdSchin 
get_version(register Namval_t * np,Namfun_t * fp)7757c2fbfb3SApril Chin static char* get_version(register Namval_t* np, Namfun_t *fp)
7767c2fbfb3SApril Chin {
7777c2fbfb3SApril Chin 	return(nv_getv(np,fp));
7787c2fbfb3SApril Chin }
7797c2fbfb3SApril Chin 
nget_version(register Namval_t * np,Namfun_t * fp)7807c2fbfb3SApril Chin static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp)
7817c2fbfb3SApril Chin {
7827c2fbfb3SApril Chin 	register const char	*cp = e_version + strlen(e_version)-10;
7837c2fbfb3SApril Chin 	register int		c;
7847c2fbfb3SApril Chin 	Sflong_t		t = 0;
7857c2fbfb3SApril Chin 	NOT_USED(fp);
7867c2fbfb3SApril Chin 
7877c2fbfb3SApril Chin 	while (c = *cp++)
7887c2fbfb3SApril Chin 		if (c >= '0' && c <= '9')
7897c2fbfb3SApril Chin 		{
7907c2fbfb3SApril Chin 			t *= 10;
7917c2fbfb3SApril Chin 			t += c - '0';
7927c2fbfb3SApril Chin 		}
7937c2fbfb3SApril Chin 	return((Sfdouble_t)t);
7947c2fbfb3SApril Chin }
7957c2fbfb3SApril Chin 
7967c2fbfb3SApril Chin static const Namdisc_t SH_VERSION_disc	= {  0, 0, get_version, nget_version };
7977c2fbfb3SApril Chin 
798da2e3ebdSchin #if SHOPT_FS_3D
799da2e3ebdSchin     /*
800da2e3ebdSchin      * set or unset the mappings given a colon separated list of directories
801da2e3ebdSchin      */
vpath_set(char * str,int mode)802da2e3ebdSchin     static void vpath_set(char *str, int mode)
803da2e3ebdSchin     {
804da2e3ebdSchin 	register char *lastp, *oldp=str, *newp=strchr(oldp,':');
805da2e3ebdSchin 	if(!sh.lim.fs3d)
806da2e3ebdSchin 		return;
807da2e3ebdSchin 	while(newp)
808da2e3ebdSchin 	{
809da2e3ebdSchin 		*newp++ = 0;
810da2e3ebdSchin 		if(lastp=strchr(newp,':'))
811da2e3ebdSchin 			*lastp = 0;
812da2e3ebdSchin 		mount((mode?newp:""),oldp,FS3D_VIEW,0);
813da2e3ebdSchin 		newp[-1] = ':';
814da2e3ebdSchin 		oldp = newp;
815da2e3ebdSchin 		newp=lastp;
816da2e3ebdSchin 	}
817da2e3ebdSchin     }
818da2e3ebdSchin 
819da2e3ebdSchin     /* catch vpath assignments */
put_vpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)820da2e3ebdSchin     static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
821da2e3ebdSchin     {
822da2e3ebdSchin 	register char *cp;
823da2e3ebdSchin 	if(cp = nv_getval(np))
824da2e3ebdSchin 		vpath_set(cp,0);
825da2e3ebdSchin 	if(val)
826da2e3ebdSchin 		vpath_set((char*)val,1);
827da2e3ebdSchin 	nv_putv(np,val,flags,fp);
828da2e3ebdSchin     }
829da2e3ebdSchin     static const Namdisc_t VPATH_disc	= { 0, put_vpath  };
830da2e3ebdSchin     static Namfun_t VPATH_init	= { &VPATH_disc, 1  };
831da2e3ebdSchin #endif /* SHOPT_FS_3D */
832da2e3ebdSchin 
833da2e3ebdSchin 
834da2e3ebdSchin static const Namdisc_t IFS_disc		= {  sizeof(struct ifs), put_ifs, get_ifs };
8357c2fbfb3SApril Chin const Namdisc_t RESTRICTED_disc	= {  sizeof(Namfun_t), put_restricted };
8367c2fbfb3SApril Chin static const Namdisc_t CDPATH_disc	= {  sizeof(Namfun_t), put_cdpath };
8377c2fbfb3SApril Chin static const Namdisc_t EDITOR_disc	= {  sizeof(Namfun_t), put_ed };
8387c2fbfb3SApril Chin static const Namdisc_t HISTFILE_disc	= {  sizeof(Namfun_t), put_history };
8397c2fbfb3SApril Chin static const Namdisc_t OPTINDEX_disc	= {  sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
840da2e3ebdSchin static const Namdisc_t SECONDS_disc	= {  sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
841da2e3ebdSchin static const Namdisc_t RAND_disc	= {  sizeof(struct rand), put_rand, get_rand, nget_rand };
8427c2fbfb3SApril Chin static const Namdisc_t LINENO_disc	= {  sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno };
8437c2fbfb3SApril Chin static const Namdisc_t L_ARG_disc	= {  sizeof(Namfun_t), put_lastarg, get_lastarg };
844da2e3ebdSchin 
845da2e3ebdSchin #if SHOPT_NAMESPACE
get_nspace(Namval_t * np,Namfun_t * fp)846da2e3ebdSchin     static char* get_nspace(Namval_t* np, Namfun_t *fp)
847da2e3ebdSchin     {
848da2e3ebdSchin 	if(sh.namespace)
849da2e3ebdSchin 		return(nv_name(sh.namespace));
850da2e3ebdSchin 	return((char*)np->nvalue.cp);
851da2e3ebdSchin     }
852da2e3ebdSchin     static const Namdisc_t NSPACE_disc	= {  0, 0, get_nspace };
853da2e3ebdSchin     static Namfun_t NSPACE_init	= {  &NSPACE_disc, 1};
854da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
855da2e3ebdSchin 
856da2e3ebdSchin #ifdef _hdr_locale
8577c2fbfb3SApril Chin     static const Namdisc_t LC_disc	= {  sizeof(Namfun_t), put_lang };
858da2e3ebdSchin #endif /* _hdr_locale */
859da2e3ebdSchin 
860da2e3ebdSchin /*
861da2e3ebdSchin  * This function will get called whenever a configuration parameter changes
862da2e3ebdSchin  */
newconf(const char * name,const char * path,const char * value)863da2e3ebdSchin static int newconf(const char *name, const char *path, const char *value)
864da2e3ebdSchin {
865da2e3ebdSchin 	register char *arg;
866da2e3ebdSchin 	if(!name)
867da2e3ebdSchin 		setenviron(value);
868da2e3ebdSchin 	else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value))
869da2e3ebdSchin 	{
870da2e3ebdSchin 		sh.universe = 0;
871da2e3ebdSchin 		/* set directory in new universe */
872da2e3ebdSchin 		if(*(arg = path_pwd(0))=='/')
873da2e3ebdSchin 			chdir(arg);
874da2e3ebdSchin 		/* clear out old tracked alias */
875da2e3ebdSchin 		stakseek(0);
876da2e3ebdSchin 		stakputs(nv_getval(PATHNOD));
877da2e3ebdSchin 		stakputc(0);
878da2e3ebdSchin 		nv_putval(PATHNOD,stakseek(0),NV_RDONLY);
879da2e3ebdSchin 	}
880da2e3ebdSchin 	return(1);
881da2e3ebdSchin }
882da2e3ebdSchin 
883da2e3ebdSchin #if	(CC_NATIVE != CC_ASCII)
a2e(char * d,const char * s)884da2e3ebdSchin     static void a2e(char *d, const char *s)
885da2e3ebdSchin     {
886da2e3ebdSchin 	register const unsigned char *t;
887da2e3ebdSchin 	register int i;
888da2e3ebdSchin 	t = CCMAP(CC_ASCII, CC_NATIVE);
889da2e3ebdSchin 	for(i=0; i<(1<<CHAR_BIT); i++)
890da2e3ebdSchin 		d[t[i]] = s[i];
891da2e3ebdSchin     }
892da2e3ebdSchin 
init_ebcdic(void)893da2e3ebdSchin     static void init_ebcdic(void)
894da2e3ebdSchin     {
895da2e3ebdSchin 	int i;
896da2e3ebdSchin 	char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT));
897da2e3ebdSchin 	for(i=0; i < ST_NONE; i++)
898da2e3ebdSchin 	{
899da2e3ebdSchin 		a2e(cp,sh_lexrstates[i]);
900da2e3ebdSchin 		sh_lexstates[i] = cp;
901da2e3ebdSchin 		cp += (1<<CHAR_BIT);
902da2e3ebdSchin 	}
903da2e3ebdSchin     }
904da2e3ebdSchin #endif
905da2e3ebdSchin 
906da2e3ebdSchin /*
907da2e3ebdSchin  * return SH_TYPE_* bitmask for path
908da2e3ebdSchin  * 0 for "not a shell"
909da2e3ebdSchin  */
sh_type(register const char * path)910da2e3ebdSchin int sh_type(register const char *path)
911da2e3ebdSchin {
912da2e3ebdSchin 	register const char*	s;
913da2e3ebdSchin 	register int		t = 0;
914da2e3ebdSchin 
915da2e3ebdSchin 	if (s = (const char*)strrchr(path, '/'))
916da2e3ebdSchin 	{
917da2e3ebdSchin 		if (*path == '-')
918da2e3ebdSchin 			t |= SH_TYPE_LOGIN;
919da2e3ebdSchin 		s++;
920da2e3ebdSchin 	}
921da2e3ebdSchin 	else
922da2e3ebdSchin 		s = path;
923da2e3ebdSchin 	if (*s == '-')
924da2e3ebdSchin 	{
925da2e3ebdSchin 		s++;
926da2e3ebdSchin 		t |= SH_TYPE_LOGIN;
927da2e3ebdSchin 	}
928da2e3ebdSchin 	for (;;)
929da2e3ebdSchin 	{
930da2e3ebdSchin 		if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
931da2e3ebdSchin 		{
932da2e3ebdSchin 			if (*s == 'k')
933da2e3ebdSchin 			{
934da2e3ebdSchin 				s++;
935da2e3ebdSchin 				t |= SH_TYPE_KSH;
936da2e3ebdSchin 				continue;
937da2e3ebdSchin 			}
938da2e3ebdSchin #if SHOPT_BASH
939da2e3ebdSchin 			if (*s == 'b' && *(s+1) == 'a')
940da2e3ebdSchin 			{
941da2e3ebdSchin 				s += 2;
942da2e3ebdSchin 				t |= SH_TYPE_BASH;
943da2e3ebdSchin 				continue;
944da2e3ebdSchin 			}
945da2e3ebdSchin #endif
946da2e3ebdSchin 		}
947da2e3ebdSchin 		if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
948da2e3ebdSchin 		{
949da2e3ebdSchin #if SHOPT_PFSH
950da2e3ebdSchin 			if (*s == 'p' && *(s+1) == 'f')
951da2e3ebdSchin 			{
952da2e3ebdSchin 				s += 2;
953da2e3ebdSchin 				t |= SH_TYPE_PROFILE;
954da2e3ebdSchin 				continue;
955da2e3ebdSchin 			}
956da2e3ebdSchin #endif
957da2e3ebdSchin 			if (*s == 'r')
958da2e3ebdSchin 			{
959da2e3ebdSchin 				s++;
960da2e3ebdSchin 				t |= SH_TYPE_RESTRICTED;
961da2e3ebdSchin 				continue;
962da2e3ebdSchin 			}
963da2e3ebdSchin 		}
964da2e3ebdSchin 		break;
965da2e3ebdSchin 	}
9667c2fbfb3SApril Chin 	if (*s++ == 's' && (*s == 'h' || *s == 'u'))
9677c2fbfb3SApril Chin 	{
9687c2fbfb3SApril Chin 		s++;
969da2e3ebdSchin 		t |= SH_TYPE_SH;
970da2e3ebdSchin 		if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
971da2e3ebdSchin 			s += 2;
972da2e3ebdSchin #if _WINIX
973da2e3ebdSchin 		if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e')
974da2e3ebdSchin 			s += 4;
975da2e3ebdSchin #endif
9767c2fbfb3SApril Chin 		if (!isalnum(*s))
977da2e3ebdSchin 			return t;
978da2e3ebdSchin 	}
9797c2fbfb3SApril Chin 	return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
9807c2fbfb3SApril Chin }
9817c2fbfb3SApril Chin 
9827c2fbfb3SApril Chin 
get_mode(Namval_t * np,Namfun_t * nfp)9837c2fbfb3SApril Chin static char *get_mode(Namval_t* np, Namfun_t* nfp)
9847c2fbfb3SApril Chin {
9857c2fbfb3SApril Chin 	mode_t mode = nv_getn(np,nfp);
9867c2fbfb3SApril Chin 	return(fmtperm(mode));
9877c2fbfb3SApril Chin }
9887c2fbfb3SApril Chin 
put_mode(Namval_t * np,const char * val,int flag,Namfun_t * nfp)9897c2fbfb3SApril Chin static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
9907c2fbfb3SApril Chin {
9917c2fbfb3SApril Chin 	if(val)
9927c2fbfb3SApril Chin 	{
9937c2fbfb3SApril Chin 		mode_t mode;
9947c2fbfb3SApril Chin 		char *last;
9957c2fbfb3SApril Chin 		if(flag&NV_INTEGER)
9967c2fbfb3SApril Chin 		{
9977c2fbfb3SApril Chin 			if(flag&NV_LONG)
9987c2fbfb3SApril Chin 				mode = *(Sfdouble_t*)val;
9997c2fbfb3SApril Chin 			else
10007c2fbfb3SApril Chin 				mode = *(double*)val;
10017c2fbfb3SApril Chin 		}
10027c2fbfb3SApril Chin 		else
10037c2fbfb3SApril Chin 			mode = strperm(val, &last,0);
10047c2fbfb3SApril Chin 		if(*last)
10057c2fbfb3SApril Chin 			errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
10067c2fbfb3SApril Chin 		nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
10077c2fbfb3SApril Chin 	}
10087c2fbfb3SApril Chin 	else
10097c2fbfb3SApril Chin 		nv_putv(np,val,flag,nfp);
10107c2fbfb3SApril Chin }
10117c2fbfb3SApril Chin 
10127c2fbfb3SApril Chin static const Namdisc_t modedisc =
10137c2fbfb3SApril Chin {
10147c2fbfb3SApril Chin 	0,
10157c2fbfb3SApril Chin         put_mode,
10167c2fbfb3SApril Chin         get_mode,
10177c2fbfb3SApril Chin };
10187c2fbfb3SApril Chin 
1019da2e3ebdSchin 
1020da2e3ebdSchin /*
1021da2e3ebdSchin  * initialize the shell
1022da2e3ebdSchin  */
sh_init(register int argc,register char * argv[],Shinit_f userinit)10237c2fbfb3SApril Chin Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
1024da2e3ebdSchin {
10257c2fbfb3SApril Chin 	Shell_t	*shp = &sh;
1026da2e3ebdSchin 	register int n;
1027da2e3ebdSchin 	int type;
1028*3e14f97fSRoger A. Faulkner 	long v;
1029da2e3ebdSchin 	static char *login_files[3];
103034f9b3eeSRoland Mainz 	memfatal();
1031da2e3ebdSchin 	n = strlen(e_version);
1032da2e3ebdSchin 	if(e_version[n-1]=='$' && e_version[n-2]==' ')
1033da2e3ebdSchin 		e_version[n-2]=0;
1034da2e3ebdSchin #if	(CC_NATIVE == CC_ASCII)
1035da2e3ebdSchin 	memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*));
1036da2e3ebdSchin #else
1037da2e3ebdSchin 	init_ebcdic();
1038da2e3ebdSchin #endif
10397c2fbfb3SApril Chin 	umask(shp->mask=umask(0));
10407c2fbfb3SApril Chin 	shp->mac_context = sh_macopen(shp);
10417c2fbfb3SApril Chin 	shp->arg_context = sh_argopen(shp);
10427c2fbfb3SApril Chin 	shp->lex_context = (void*)sh_lexopen(0,shp,1);
10437c2fbfb3SApril Chin 	shp->ed_context = (void*)ed_open(shp);
10447c2fbfb3SApril Chin 	shp->strbuf = sfstropen();
10457c2fbfb3SApril Chin 	shp->stk = stkstd;
10467c2fbfb3SApril Chin 	sfsetbuf(shp->strbuf,(char*)0,64);
1047da2e3ebdSchin 	sh_onstate(SH_INIT);
1048da2e3ebdSchin 	error_info.exit = sh_exit;
1049da2e3ebdSchin 	error_info.id = path_basename(argv[0]);
1050da2e3ebdSchin #if ERROR_VERSION >= 20000102L
1051da2e3ebdSchin 	error_info.catalog = e_dict;
1052da2e3ebdSchin #endif
105334f9b3eeSRoland Mainz #if SHOPT_REGRESS
105434f9b3eeSRoland Mainz 	{
105534f9b3eeSRoland Mainz 		Opt_t*	nopt;
105634f9b3eeSRoland Mainz 		Opt_t*	oopt;
105734f9b3eeSRoland Mainz 		char*	a;
105834f9b3eeSRoland Mainz 		char**	av = argv;
105934f9b3eeSRoland Mainz 		char*	regress[3];
106034f9b3eeSRoland Mainz 
106134f9b3eeSRoland Mainz 		sh_regress_init(shp);
106234f9b3eeSRoland Mainz 		regress[0] = "__regress__";
106334f9b3eeSRoland Mainz 		regress[2] = 0;
106434f9b3eeSRoland Mainz 		/* NOTE: only shp is used by __regress__ at this point */
106534f9b3eeSRoland Mainz 		shp->bltindata.shp = shp;
106634f9b3eeSRoland Mainz 		while ((a = *++av) && a[0] == '-' && (a[1] == 'I' || a[1] == '-' && a[2] == 'r'))
106734f9b3eeSRoland Mainz 		{
106834f9b3eeSRoland Mainz 			if (a[1] == 'I')
106934f9b3eeSRoland Mainz 			{
107034f9b3eeSRoland Mainz 				if (a[2])
107134f9b3eeSRoland Mainz 					regress[1] = a + 2;
107234f9b3eeSRoland Mainz 				else if (!(regress[1] = *++av))
107334f9b3eeSRoland Mainz 					break;
107434f9b3eeSRoland Mainz 			}
107534f9b3eeSRoland Mainz 			else if (strncmp(a+2, "regress", 7))
107634f9b3eeSRoland Mainz 				break;
107734f9b3eeSRoland Mainz 			else if (a[9] == '=')
107834f9b3eeSRoland Mainz 				regress[1] = a + 10;
107934f9b3eeSRoland Mainz 			else if (!(regress[1] = *++av))
108034f9b3eeSRoland Mainz 				break;
108134f9b3eeSRoland Mainz 			nopt = optctx(0, 0);
108234f9b3eeSRoland Mainz 			oopt = optctx(nopt, 0);
108334f9b3eeSRoland Mainz 			b___regress__(2, regress, &shp->bltindata);
108434f9b3eeSRoland Mainz 			optctx(oopt, nopt);
108534f9b3eeSRoland Mainz 		}
108634f9b3eeSRoland Mainz 	}
108734f9b3eeSRoland Mainz #endif
10887c2fbfb3SApril Chin 	shp->cpipe[0] = -1;
10897c2fbfb3SApril Chin 	shp->coutpipe = -1;
10907c2fbfb3SApril Chin 	shp->userid=getuid();
10917c2fbfb3SApril Chin 	shp->euserid=geteuid();
10927c2fbfb3SApril Chin 	shp->groupid=getgid();
10937c2fbfb3SApril Chin 	shp->egroupid=getegid();
1094da2e3ebdSchin 	for(n=0;n < 10; n++)
1095da2e3ebdSchin 	{
1096da2e3ebdSchin 		/* don't use lower bits when rand() generates large numbers */
1097da2e3ebdSchin 		if(rand() > RANDMASK)
1098da2e3ebdSchin 		{
1099da2e3ebdSchin 			rand_shift = 3;
1100da2e3ebdSchin 			break;
1101da2e3ebdSchin 		}
1102da2e3ebdSchin 	}
11037c2fbfb3SApril Chin 	shp->lim.clk_tck = getconf("CLK_TCK");
11047c2fbfb3SApril Chin 	shp->lim.arg_max = getconf("ARG_MAX");
11057c2fbfb3SApril Chin 	shp->lim.open_max = getconf("OPEN_MAX");
11067c2fbfb3SApril Chin 	shp->lim.child_max = getconf("CHILD_MAX");
11077c2fbfb3SApril Chin 	shp->lim.ngroups_max = getconf("NGROUPS_MAX");
11087c2fbfb3SApril Chin 	shp->lim.posix_version = getconf("VERSION");
11097c2fbfb3SApril Chin 	shp->lim.posix_jobcontrol = getconf("JOB_CONTROL");
11107c2fbfb3SApril Chin 	if(shp->lim.arg_max <=0)
11117c2fbfb3SApril Chin 		shp->lim.arg_max = ARG_MAX;
11127c2fbfb3SApril Chin 	if(shp->lim.child_max <=0)
11137c2fbfb3SApril Chin 		shp->lim.child_max = CHILD_MAX;
1114*3e14f97fSRoger A. Faulkner 	if((v = getconf("PID_MAX")) > 0 && shp->lim.child_max > v)
1115*3e14f97fSRoger A. Faulkner 		shp->lim.child_max = v;
11167c2fbfb3SApril Chin 	if(shp->lim.open_max <0)
11177c2fbfb3SApril Chin 		shp->lim.open_max = OPEN_MAX;
11187c2fbfb3SApril Chin 	if(shp->lim.open_max > (SHRT_MAX-2))
11197c2fbfb3SApril Chin 		shp->lim.open_max = SHRT_MAX-2;
11207c2fbfb3SApril Chin 	if(shp->lim.clk_tck <=0)
11217c2fbfb3SApril Chin 		shp->lim.clk_tck = CLK_TCK;
1122da2e3ebdSchin #if SHOPT_FS_3D
1123da2e3ebdSchin 	if(fs3d(FS3D_TEST))
11247c2fbfb3SApril Chin 		shp->lim.fs3d = 1;
1125da2e3ebdSchin #endif /* SHOPT_FS_3D */
11267c2fbfb3SApril Chin 	sh_ioinit(shp);
1127da2e3ebdSchin 	/* initialize signal handling */
11287c2fbfb3SApril Chin 	sh_siginit(shp);
1129da2e3ebdSchin 	stakinstall(NIL(Stak_t*),nospace);
1130da2e3ebdSchin 	/* set up memory for name-value pairs */
11317c2fbfb3SApril Chin 	shp->init_context =  nv_init(shp);
1132da2e3ebdSchin 	/* read the environment */
1133da2e3ebdSchin 	if(argc>0)
1134da2e3ebdSchin 	{
1135da2e3ebdSchin 		type = sh_type(*argv);
1136da2e3ebdSchin 		if(type&SH_TYPE_LOGIN)
11377c2fbfb3SApril Chin 			shp->login_sh = 2;
1138da2e3ebdSchin 	}
11397c2fbfb3SApril Chin 	env_init(shp);
114034f9b3eeSRoland Mainz 	if(!ENVNOD->nvalue.cp)
114134f9b3eeSRoland Mainz 	{
114234f9b3eeSRoland Mainz 		sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME));
114334f9b3eeSRoland Mainz 		nv_putval(ENVNOD,sfstruse(shp->strbuf),NV_RDONLY);
114434f9b3eeSRoland Mainz 	}
11457c2fbfb3SApril Chin 	*SHLVL->nvalue.ip +=1;
1146da2e3ebdSchin #if SHOPT_SPAWN
1147da2e3ebdSchin 	{
1148da2e3ebdSchin 		/*
1149da2e3ebdSchin 		 * try to find the pathname for this interpreter
1150da2e3ebdSchin 		 * try using environment variable _ or argv[0]
1151da2e3ebdSchin 		 */
115234f9b3eeSRoland Mainz 		char *cp=nv_getval(L_ARGNOD);
1153da2e3ebdSchin 		char buff[PATH_MAX+1];
11547c2fbfb3SApril Chin 		shp->shpath = 0;
115534f9b3eeSRoland Mainz #if _AST_VERSION >= 20090202L
115634f9b3eeSRoland Mainz 		if((n = pathprog(NiL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
115734f9b3eeSRoland Mainz 			shp->shpath = strdup(buff);
115834f9b3eeSRoland Mainz #else
11597c2fbfb3SApril Chin 		sfprintf(shp->strbuf,"/proc/%d/exe",getpid());
11607c2fbfb3SApril Chin 		if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0)
1161da2e3ebdSchin 		{
1162da2e3ebdSchin 			buff[n] = 0;
11637c2fbfb3SApril Chin 			shp->shpath = strdup(buff);
1164da2e3ebdSchin 		}
116534f9b3eeSRoland Mainz #endif
1166da2e3ebdSchin 		else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
1167da2e3ebdSchin 		{
1168da2e3ebdSchin 			if(*cp=='/')
11697c2fbfb3SApril Chin 				shp->shpath = strdup(cp);
1170da2e3ebdSchin 			else if(cp = nv_getval(PWDNOD))
1171da2e3ebdSchin 			{
1172da2e3ebdSchin 				int offset = staktell();
1173da2e3ebdSchin 				stakputs(cp);
1174da2e3ebdSchin 				stakputc('/');
1175da2e3ebdSchin 				stakputs(argv[0]);
1176da2e3ebdSchin 				pathcanon(stakptr(offset),PATH_DOTDOT);
11777c2fbfb3SApril Chin 				shp->shpath = strdup(stakptr(offset));
1178da2e3ebdSchin 				stakseek(offset);
1179da2e3ebdSchin 			}
1180da2e3ebdSchin 		}
1181da2e3ebdSchin 	}
1182da2e3ebdSchin #endif
1183da2e3ebdSchin 	nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
1184da2e3ebdSchin #if SHOPT_FS_3D
1185da2e3ebdSchin 	nv_stack(VPATHNOD, &VPATH_init);
1186da2e3ebdSchin #endif /* SHOPT_FS_3D */
1187da2e3ebdSchin 	astconfdisc(newconf);
1188da2e3ebdSchin #if SHOPT_TIMEOUT
11897c2fbfb3SApril Chin 	shp->st.tmout = SHOPT_TIMEOUT;
1190da2e3ebdSchin #endif /* SHOPT_TIMEOUT */
1191da2e3ebdSchin 	/* initialize jobs table */
1192da2e3ebdSchin 	job_clear();
1193da2e3ebdSchin 	if(argc>0)
1194da2e3ebdSchin 	{
1195da2e3ebdSchin 		/* check for restricted shell */
1196da2e3ebdSchin 		if(type&SH_TYPE_RESTRICTED)
1197da2e3ebdSchin 			sh_onoption(SH_RESTRICTED);
1198da2e3ebdSchin #if SHOPT_PFSH
1199da2e3ebdSchin 		/* check for profile shell */
1200da2e3ebdSchin 		else if(type&SH_TYPE_PROFILE)
1201da2e3ebdSchin 			sh_onoption(SH_PFSH);
1202da2e3ebdSchin #endif
1203da2e3ebdSchin #if SHOPT_BASH
1204da2e3ebdSchin 		/* check for invocation as bash */
1205da2e3ebdSchin 		if(type&SH_TYPE_BASH)
1206da2e3ebdSchin 		{
12077c2fbfb3SApril Chin 		        shp->userinit = userinit = bash_init;
1208da2e3ebdSchin 			sh_onoption(SH_BASH);
1209da2e3ebdSchin 			sh_onstate(SH_PREINIT);
12107c2fbfb3SApril Chin 			(*userinit)(shp, 0);
1211da2e3ebdSchin 			sh_offstate(SH_PREINIT);
1212da2e3ebdSchin 		}
1213da2e3ebdSchin #endif
1214da2e3ebdSchin 		/* look for options */
12157c2fbfb3SApril Chin 		/* shp->st.dolc is $#	*/
12167c2fbfb3SApril Chin 		if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0)
1217da2e3ebdSchin 		{
12187c2fbfb3SApril Chin 			shp->exitval = 2;
12197c2fbfb3SApril Chin 			sh_done(shp,0);
1220da2e3ebdSchin 		}
1221da2e3ebdSchin 		opt_info.disc = 0;
12227c2fbfb3SApril Chin 		shp->st.dolv=argv+(argc-1)-shp->st.dolc;
12237c2fbfb3SApril Chin 		shp->st.dolv[0] = argv[0];
12247c2fbfb3SApril Chin 		if(shp->st.dolc < 1)
1225da2e3ebdSchin 			sh_onoption(SH_SFLAG);
1226da2e3ebdSchin 		if(!sh_isoption(SH_SFLAG))
1227da2e3ebdSchin 		{
12287c2fbfb3SApril Chin 			shp->st.dolc--;
12297c2fbfb3SApril Chin 			shp->st.dolv++;
1230da2e3ebdSchin #if _WINIX
1231da2e3ebdSchin 			{
1232da2e3ebdSchin 				char*	name;
12337c2fbfb3SApril Chin 				name = shp->st.dolv[0];
1234da2e3ebdSchin 				if(name[1]==':' && (name[2]=='/' || name[2]=='\\'))
1235da2e3ebdSchin 				{
1236da2e3ebdSchin #if _lib_pathposix
1237da2e3ebdSchin 					char*	p;
1238da2e3ebdSchin 
1239da2e3ebdSchin 					if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n)))
1240da2e3ebdSchin 					{
1241da2e3ebdSchin 						pathposix(name, p, n);
1242da2e3ebdSchin 						name = p;
1243da2e3ebdSchin 					}
1244da2e3ebdSchin 					else
1245da2e3ebdSchin #endif
1246da2e3ebdSchin 					{
1247da2e3ebdSchin 						name[1] = name[0];
1248da2e3ebdSchin 						name[0] = name[2] = '/';
1249da2e3ebdSchin 					}
1250da2e3ebdSchin 				}
1251da2e3ebdSchin 			}
1252da2e3ebdSchin #endif /* _WINIX */
1253da2e3ebdSchin 		}
1254da2e3ebdSchin 	}
1255da2e3ebdSchin #if SHOPT_PFSH
1256da2e3ebdSchin 	if (sh_isoption(SH_PFSH))
1257da2e3ebdSchin 	{
12587c2fbfb3SApril Chin 		struct passwd *pw = getpwuid(shp->userid);
1259da2e3ebdSchin 		if(pw)
12607c2fbfb3SApril Chin 			shp->user = strdup(pw->pw_name);
1261da2e3ebdSchin 
1262da2e3ebdSchin 	}
1263da2e3ebdSchin #endif
1264da2e3ebdSchin 	/* set[ug]id scripts require the -p flag */
12657c2fbfb3SApril Chin 	if(shp->userid!=shp->euserid || shp->groupid!=shp->egroupid)
1266da2e3ebdSchin 	{
126734f9b3eeSRoland Mainz #ifdef SHOPT_P_SUID
1268da2e3ebdSchin 		/* require sh -p to run setuid and/or setgid */
126934f9b3eeSRoland Mainz 		if(!sh_isoption(SH_PRIVILEGED) && shp->userid >= SHOPT_P_SUID)
1270da2e3ebdSchin 		{
12717c2fbfb3SApril Chin 			setuid(shp->euserid=shp->userid);
12727c2fbfb3SApril Chin 			setgid(shp->egroupid=shp->groupid);
1273da2e3ebdSchin 		}
1274da2e3ebdSchin 		else
1275da2e3ebdSchin #endif /* SHOPT_P_SUID */
127634f9b3eeSRoland Mainz 			sh_onoption(SH_PRIVILEGED);
1277da2e3ebdSchin #ifdef SHELLMAGIC
1278da2e3ebdSchin 		/* careful of #! setuid scripts with name beginning with - */
12797c2fbfb3SApril Chin 		if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0)
1280da2e3ebdSchin 			errormsg(SH_DICT,ERROR_exit(1),e_prohibited);
1281da2e3ebdSchin #endif /*SHELLMAGIC*/
1282da2e3ebdSchin 	}
1283da2e3ebdSchin 	else
1284da2e3ebdSchin 		sh_offoption(SH_PRIVILEGED);
1285da2e3ebdSchin 	/* shname for $0 in profiles and . scripts */
1286da2e3ebdSchin 	if(strmatch(argv[1],e_devfdNN))
12877c2fbfb3SApril Chin 		shp->shname = strdup(argv[0]);
1288da2e3ebdSchin 	else
12897c2fbfb3SApril Chin 		shp->shname = strdup(shp->st.dolv[0]);
1290da2e3ebdSchin 	/*
1291da2e3ebdSchin 	 * return here for shell script execution
1292da2e3ebdSchin 	 * but not for parenthesis subshells
1293da2e3ebdSchin 	 */
12947c2fbfb3SApril Chin 	error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */
12957c2fbfb3SApril Chin 	shp->jmpbuffer = (void*)&shp->checkbase;
12967c2fbfb3SApril Chin 	sh_pushcontext(&shp->checkbase,SH_JMPSCRIPT);
12977c2fbfb3SApril Chin 	shp->st.self = &shp->global;
12987c2fbfb3SApril Chin         shp->topscope = (Shscope_t*)shp->st.self;
1299da2e3ebdSchin 	sh_offstate(SH_INIT);
1300da2e3ebdSchin 	login_files[0] = (char*)e_profile;
1301da2e3ebdSchin 	login_files[1] = ".profile";
13027c2fbfb3SApril Chin 	shp->login_files = login_files;
13037c2fbfb3SApril Chin 	shp->bltindata.version = SH_VERSION;
13047c2fbfb3SApril Chin 	shp->bltindata.shp = shp;
13057c2fbfb3SApril Chin 	shp->bltindata.shrun = sh_run;
13067c2fbfb3SApril Chin 	shp->bltindata.shtrap = sh_trap;
13077c2fbfb3SApril Chin 	shp->bltindata.shexit = sh_exit;
13087c2fbfb3SApril Chin 	shp->bltindata.shbltin = sh_addbuiltin;
13097c2fbfb3SApril Chin #if _AST_VERSION >= 20080617L
1310*3e14f97fSRoger A. Faulkner 	shp->bltindata.shgetenv = sh_getenv;
1311*3e14f97fSRoger A. Faulkner 	shp->bltindata.shsetenv = sh_setenviron;
13127c2fbfb3SApril Chin 	astintercept(&shp->bltindata,1);
13137c2fbfb3SApril Chin #endif
13147c2fbfb3SApril Chin #if 0
13157c2fbfb3SApril Chin #define NV_MKINTTYPE(x,y,z)	nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z);
13167c2fbfb3SApril Chin 	NV_MKINTTYPE(pid_t,"process id",0);
13177c2fbfb3SApril Chin 	NV_MKINTTYPE(gid_t,"group id",0);
13187c2fbfb3SApril Chin 	NV_MKINTTYPE(uid_t,"user id",0);
13197c2fbfb3SApril Chin 	NV_MKINTTYPE(size_t,(const char*)0,0);
13207c2fbfb3SApril Chin 	NV_MKINTTYPE(ssize_t,(const char*)0,0);
13217c2fbfb3SApril Chin 	NV_MKINTTYPE(off_t,"offset in bytes",0);
13227c2fbfb3SApril Chin 	NV_MKINTTYPE(ino_t,"\ai-\anode number",0);
13237c2fbfb3SApril Chin 	NV_MKINTTYPE(mode_t,(const char*)0,&modedisc);
13247c2fbfb3SApril Chin 	NV_MKINTTYPE(dev_t,"device id",0);
13257c2fbfb3SApril Chin 	NV_MKINTTYPE(nlink_t,"hard link count",0);
13267c2fbfb3SApril Chin 	NV_MKINTTYPE(blkcnt_t,"block count",0);
13277c2fbfb3SApril Chin 	NV_MKINTTYPE(time_t,"seconds since the epoch",0);
13287c2fbfb3SApril Chin 	nv_mkstat();
13297c2fbfb3SApril Chin #endif
13307c2fbfb3SApril Chin 	if(shp->userinit=userinit)
13317c2fbfb3SApril Chin 		(*userinit)(shp, 0);
13327c2fbfb3SApril Chin 	return(shp);
1333da2e3ebdSchin }
1334da2e3ebdSchin 
sh_getinterp(void)1335da2e3ebdSchin Shell_t *sh_getinterp(void)
1336da2e3ebdSchin {
1337da2e3ebdSchin 	return(&sh);
1338da2e3ebdSchin }
1339da2e3ebdSchin 
1340da2e3ebdSchin /*
1341da2e3ebdSchin  * reinitialize before executing a script
1342da2e3ebdSchin  */
sh_reinit(char * argv[])1343da2e3ebdSchin int sh_reinit(char *argv[])
1344da2e3ebdSchin {
13457c2fbfb3SApril Chin 	Shell_t	*shp = &sh;
1346da2e3ebdSchin 	Shopt_t opt;
13477c2fbfb3SApril Chin 	Namval_t *np,*npnext;
13487c2fbfb3SApril Chin 	Dt_t	*dp;
13497c2fbfb3SApril Chin 	for(np=dtfirst(shp->fun_tree);np;np=npnext)
1350da2e3ebdSchin 	{
13517c2fbfb3SApril Chin 		if((dp=shp->fun_tree)->walk)
13527c2fbfb3SApril Chin 			dp = dp->walk;
13537c2fbfb3SApril Chin 		npnext = (Namval_t*)dtnext(shp->fun_tree,np);
13547c2fbfb3SApril Chin 		if(np>= shp->bltin_cmds && np < &shp->bltin_cmds[nbltins])
13557c2fbfb3SApril Chin 			continue;
13567c2fbfb3SApril Chin 		if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT))
13577c2fbfb3SApril Chin 			continue;
13587c2fbfb3SApril Chin 		if(*np->nvname=='/')
13597c2fbfb3SApril Chin 			continue;
13607c2fbfb3SApril Chin 		nv_delete(np,dp,NV_NOFREE);
13617c2fbfb3SApril Chin 	}
13627c2fbfb3SApril Chin 	dtclose(shp->alias_tree);
13637c2fbfb3SApril Chin 	shp->alias_tree = inittree(shp,shtab_aliases);
13647c2fbfb3SApril Chin 	shp->last_root = shp->var_tree;
13657c2fbfb3SApril Chin 	shp->namespace = 0;
13667c2fbfb3SApril Chin 	shp->inuse_bits = 0;
13677c2fbfb3SApril Chin 	if(shp->userinit)
13687c2fbfb3SApril Chin 		(*shp->userinit)(shp, 1);
13697c2fbfb3SApril Chin 	if(shp->heredocs)
13707c2fbfb3SApril Chin 	{
13717c2fbfb3SApril Chin 		sfclose(shp->heredocs);
13727c2fbfb3SApril Chin 		shp->heredocs = 0;
1373da2e3ebdSchin 	}
1374da2e3ebdSchin 	/* remove locals */
1375da2e3ebdSchin 	sh_onstate(SH_INIT);
13767c2fbfb3SApril Chin 	nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_EXPORT,0);
13777c2fbfb3SApril Chin 	nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_ARRAY,NV_ARRAY);
1378da2e3ebdSchin 	sh_offstate(SH_INIT);
13797c2fbfb3SApril Chin 	memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*));
1380da2e3ebdSchin 	memset((void*)&opt,0,sizeof(opt));
1381da2e3ebdSchin 	if(sh_isoption(SH_TRACKALL))
1382da2e3ebdSchin 		on_option(&opt,SH_TRACKALL);
1383da2e3ebdSchin 	if(sh_isoption(SH_EMACS))
1384da2e3ebdSchin 		on_option(&opt,SH_EMACS);
1385da2e3ebdSchin 	if(sh_isoption(SH_GMACS))
1386da2e3ebdSchin 		on_option(&opt,SH_GMACS);
1387da2e3ebdSchin 	if(sh_isoption(SH_VI))
1388da2e3ebdSchin 		on_option(&opt,SH_VI);
1389da2e3ebdSchin 	if(sh_isoption(SH_VIRAW))
1390da2e3ebdSchin 		on_option(&opt,SH_VIRAW);
13917c2fbfb3SApril Chin 	shp->options = opt;
1392da2e3ebdSchin 	/* set up new args */
1393da2e3ebdSchin 	if(argv)
13947c2fbfb3SApril Chin 		shp->arglist = sh_argcreate(argv);
13957c2fbfb3SApril Chin 	if(shp->arglist)
13967c2fbfb3SApril Chin 		sh_argreset(shp,shp->arglist,NIL(struct dolnod*));
13977c2fbfb3SApril Chin 	shp->envlist=0;
13987c2fbfb3SApril Chin 	shp->curenv = 0;
13997c2fbfb3SApril Chin 	shp->shname = error_info.id = strdup(shp->st.dolv[0]);
1400da2e3ebdSchin 	sh_offstate(SH_FORKED);
14017c2fbfb3SApril Chin 	shp->fn_depth = shp->dot_depth = 0;
1402da2e3ebdSchin 	sh_sigreset(0);
140334f9b3eeSRoland Mainz 	if(!(SHLVL->nvalue.ip))
140434f9b3eeSRoland Mainz 	{
140534f9b3eeSRoland Mainz 		shlvl = 0;
140634f9b3eeSRoland Mainz 		SHLVL->nvalue.ip = &shlvl;
140734f9b3eeSRoland Mainz 		nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
140834f9b3eeSRoland Mainz 	}
14097c2fbfb3SApril Chin 	*SHLVL->nvalue.ip +=1;
141034f9b3eeSRoland Mainz 	shp->st.filename = strdup(shp->lastarg);
1411da2e3ebdSchin 	return(1);
1412da2e3ebdSchin }
1413da2e3ebdSchin 
1414da2e3ebdSchin /*
1415da2e3ebdSchin  * set when creating a local variable of this name
1416da2e3ebdSchin  */
nv_cover(register Namval_t * np)1417da2e3ebdSchin Namfun_t *nv_cover(register Namval_t *np)
1418da2e3ebdSchin {
141934f9b3eeSRoland Mainz 	if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS || np==ENVNOD)
1420da2e3ebdSchin 		return(np->nvfun);
1421da2e3ebdSchin #ifdef _hdr_locale
1422da2e3ebdSchin 	if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD)
1423da2e3ebdSchin 		return(np->nvfun);
1424da2e3ebdSchin #endif
1425da2e3ebdSchin 	 return(0);
1426da2e3ebdSchin }
1427da2e3ebdSchin 
1428da2e3ebdSchin static const char *shdiscnames[] = { "tilde", 0};
1429da2e3ebdSchin 
14307c2fbfb3SApril Chin #ifdef SHOPT_STATS
14317c2fbfb3SApril Chin struct Stats
14327c2fbfb3SApril Chin {
14337c2fbfb3SApril Chin 	Namfun_t	hdr;
14347c2fbfb3SApril Chin 	Shell_t		*sh;
14357c2fbfb3SApril Chin 	char		*nodes;
14367c2fbfb3SApril Chin 	int		numnodes;
14377c2fbfb3SApril Chin 	int		current;
14387c2fbfb3SApril Chin };
14397c2fbfb3SApril Chin 
next_stat(register Namval_t * np,Dt_t * root,Namfun_t * fp)14407c2fbfb3SApril Chin static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp)
14417c2fbfb3SApril Chin {
14427c2fbfb3SApril Chin 	struct Stats *sp = (struct Stats*)fp;
14437c2fbfb3SApril Chin 	if(!root)
14447c2fbfb3SApril Chin 		sp->current = 0;
14457c2fbfb3SApril Chin 	else if(++sp->current>=sp->numnodes)
14467c2fbfb3SApril Chin 		return(0);
14477c2fbfb3SApril Chin 	return(nv_namptr(sp->nodes,sp->current));
14487c2fbfb3SApril Chin }
14497c2fbfb3SApril Chin 
create_stat(Namval_t * np,const char * name,int flag,Namfun_t * fp)14507c2fbfb3SApril Chin static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp)
14517c2fbfb3SApril Chin {
14527c2fbfb3SApril Chin 	struct Stats		*sp = (struct Stats*)fp;
14537c2fbfb3SApril Chin 	register const char	*cp=name;
14547c2fbfb3SApril Chin 	register int		i=0,n;
14557c2fbfb3SApril Chin 	Namval_t		*nq=0;
14567c2fbfb3SApril Chin 	Shell_t			*shp = sp->sh;
14577c2fbfb3SApril Chin 	if(!name)
14587c2fbfb3SApril Chin 		return(SH_STATS);
14597c2fbfb3SApril Chin 	while((i=*cp++) && i != '=' && i != '+' && i!='[');
14607c2fbfb3SApril Chin 	n = (cp-1) -name;
14617c2fbfb3SApril Chin 	for(i=0; i < sp->numnodes; i++)
14627c2fbfb3SApril Chin 	{
14637c2fbfb3SApril Chin 		nq = nv_namptr(sp->nodes,i);
14647c2fbfb3SApril Chin 		if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
14657c2fbfb3SApril Chin 			goto found;
14667c2fbfb3SApril Chin 	}
14677c2fbfb3SApril Chin 	nq = 0;
14687c2fbfb3SApril Chin found:
14697c2fbfb3SApril Chin 	if(nq)
14707c2fbfb3SApril Chin 	{
14717c2fbfb3SApril Chin 		fp->last = (char*)&name[n];
14727c2fbfb3SApril Chin 		shp->last_table = SH_STATS;
14737c2fbfb3SApril Chin 	}
14747c2fbfb3SApril Chin 	else
14757c2fbfb3SApril Chin 		errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
14767c2fbfb3SApril Chin 	return(nq);
14777c2fbfb3SApril Chin }
14787c2fbfb3SApril Chin 
14797c2fbfb3SApril Chin static const Namdisc_t stat_disc =
14807c2fbfb3SApril Chin {
14817c2fbfb3SApril Chin 	0, 0, 0, 0, 0,
14827c2fbfb3SApril Chin 	create_stat,
14837c2fbfb3SApril Chin 	0, 0,
14847c2fbfb3SApril Chin 	next_stat
14857c2fbfb3SApril Chin };
14867c2fbfb3SApril Chin 
name_stat(Namval_t * np,Namfun_t * fp)14877c2fbfb3SApril Chin static char *name_stat(Namval_t *np, Namfun_t *fp)
14887c2fbfb3SApril Chin {
14897c2fbfb3SApril Chin 	Shell_t	*shp = sh_getinterp();
14907c2fbfb3SApril Chin 	sfprintf(shp->strbuf,".sh.stats.%s",np->nvname);
14917c2fbfb3SApril Chin 	return(sfstruse(shp->strbuf));
14927c2fbfb3SApril Chin }
14937c2fbfb3SApril Chin 
14947c2fbfb3SApril Chin static const Namdisc_t	stat_child_disc =
14957c2fbfb3SApril Chin {
14967c2fbfb3SApril Chin 	0,0,0,0,0,0,0,
14977c2fbfb3SApril Chin 	name_stat
14987c2fbfb3SApril Chin };
14997c2fbfb3SApril Chin 
15007c2fbfb3SApril Chin static Namfun_t	 stat_child_fun =
15017c2fbfb3SApril Chin {
15027c2fbfb3SApril Chin 	&stat_child_disc, 1, 0, sizeof(Namfun_t)
15037c2fbfb3SApril Chin };
15047c2fbfb3SApril Chin 
stat_init(Shell_t * shp)15057c2fbfb3SApril Chin static void stat_init(Shell_t *shp)
15067c2fbfb3SApril Chin {
15077c2fbfb3SApril Chin 	int		i,nstat = STAT_SUBSHELL+1;
15087c2fbfb3SApril Chin 	struct Stats	*sp = newof(0,struct Stats,1,nstat*NV_MINSZ);
15097c2fbfb3SApril Chin 	Namval_t	*np;
15107c2fbfb3SApril Chin 	sp->numnodes = nstat;
15117c2fbfb3SApril Chin 	sp->nodes = (char*)(sp+1);
15127c2fbfb3SApril Chin 	shp->stats = (int*)calloc(sizeof(int*),nstat);
15137c2fbfb3SApril Chin 	sp->sh = shp;
15147c2fbfb3SApril Chin 	for(i=0; i < nstat; i++)
15157c2fbfb3SApril Chin 	{
15167c2fbfb3SApril Chin 		np = nv_namptr(sp->nodes,i);
15177c2fbfb3SApril Chin 		np->nvfun = &stat_child_fun;
15187c2fbfb3SApril Chin 		np->nvname = (char*)shtab_stats[i].sh_name;
15197c2fbfb3SApril Chin 		nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER);
15207c2fbfb3SApril Chin 		nv_setsize(np,10);
15217c2fbfb3SApril Chin 		np->nvalue.ip = &shp->stats[i];
15227c2fbfb3SApril Chin 	}
15237c2fbfb3SApril Chin 	sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ);
15247c2fbfb3SApril Chin 	sp->hdr.disc = &stat_disc;
15257c2fbfb3SApril Chin 	nv_stack(SH_STATS,&sp->hdr);
15267c2fbfb3SApril Chin 	sp->hdr.nofree = 1;
15277c2fbfb3SApril Chin 	nv_setvtree(SH_STATS);
15287c2fbfb3SApril Chin }
15297c2fbfb3SApril Chin #else
15307c2fbfb3SApril Chin #   define stat_init(x)
15317c2fbfb3SApril Chin #endif /* SHOPT_STATS */
15327c2fbfb3SApril Chin 
1533da2e3ebdSchin /*
1534da2e3ebdSchin  * Initialize the shell name and alias table
1535da2e3ebdSchin  */
nv_init(Shell_t * shp)1536da2e3ebdSchin static Init_t *nv_init(Shell_t *shp)
1537da2e3ebdSchin {
1538da2e3ebdSchin 	Namval_t *np;
1539da2e3ebdSchin 	register Init_t *ip;
1540da2e3ebdSchin 	double d=0;
1541da2e3ebdSchin 	ip = newof(0,Init_t,1,0);
1542da2e3ebdSchin 	if(!ip)
1543da2e3ebdSchin 		return(0);
15447c2fbfb3SApril Chin 	shp->nvfun.last = (char*)shp;
15457c2fbfb3SApril Chin 	shp->nvfun.nofree = 1;
1546da2e3ebdSchin 	ip->sh = shp;
1547da2e3ebdSchin 	shp->var_base = shp->var_tree = inittree(shp,shtab_variables);
15487c2fbfb3SApril Chin 	SHLVL->nvalue.ip = &shlvl;
1549da2e3ebdSchin 	ip->IFS_init.hdr.disc = &IFS_disc;
1550da2e3ebdSchin 	ip->IFS_init.hdr.nofree = 1;
15517c2fbfb3SApril Chin 	ip->PATH_init.disc = &RESTRICTED_disc;
15527c2fbfb3SApril Chin 	ip->PATH_init.nofree = 1;
15537c2fbfb3SApril Chin 	ip->FPATH_init.disc = &RESTRICTED_disc;
15547c2fbfb3SApril Chin 	ip->FPATH_init.nofree = 1;
15557c2fbfb3SApril Chin 	ip->CDPATH_init.disc = &CDPATH_disc;
15567c2fbfb3SApril Chin 	ip->CDPATH_init.nofree = 1;
15577c2fbfb3SApril Chin 	ip->SHELL_init.disc = &RESTRICTED_disc;
15587c2fbfb3SApril Chin 	ip->SHELL_init.nofree = 1;
15597c2fbfb3SApril Chin 	ip->ENV_init.disc = &RESTRICTED_disc;
15607c2fbfb3SApril Chin 	ip->ENV_init.nofree = 1;
15617c2fbfb3SApril Chin 	ip->VISUAL_init.disc = &EDITOR_disc;
15627c2fbfb3SApril Chin 	ip->VISUAL_init.nofree = 1;
15637c2fbfb3SApril Chin 	ip->EDITOR_init.disc = &EDITOR_disc;
15647c2fbfb3SApril Chin 	ip->EDITOR_init.nofree = 1;
15657c2fbfb3SApril Chin 	ip->HISTFILE_init.disc = &HISTFILE_disc;
15667c2fbfb3SApril Chin 	ip->HISTFILE_init.nofree = 1;
15677c2fbfb3SApril Chin 	ip->HISTSIZE_init.disc = &HISTFILE_disc;
15687c2fbfb3SApril Chin 	ip->HISTSIZE_init.nofree = 1;
15697c2fbfb3SApril Chin 	ip->OPTINDEX_init.disc = &OPTINDEX_disc;
15707c2fbfb3SApril Chin 	ip->OPTINDEX_init.nofree = 1;
1571da2e3ebdSchin 	ip->SECONDS_init.hdr.disc = &SECONDS_disc;
1572da2e3ebdSchin 	ip->SECONDS_init.hdr.nofree = 1;
1573da2e3ebdSchin 	ip->RAND_init.hdr.disc = &RAND_disc;
1574da2e3ebdSchin 	ip->RAND_init.hdr.nofree = 1;
1575da2e3ebdSchin 	ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc;
1576da2e3ebdSchin 	ip->SH_MATCH_init.hdr.nofree = 1;
15777c2fbfb3SApril Chin 	ip->SH_VERSION_init.disc = &SH_VERSION_disc;
15787c2fbfb3SApril Chin 	ip->SH_VERSION_init.nofree = 1;
15797c2fbfb3SApril Chin 	ip->LINENO_init.disc = &LINENO_disc;
15807c2fbfb3SApril Chin 	ip->LINENO_init.nofree = 1;
15817c2fbfb3SApril Chin 	ip->L_ARG_init.disc = &L_ARG_disc;
15827c2fbfb3SApril Chin 	ip->L_ARG_init.nofree = 1;
1583da2e3ebdSchin #ifdef _hdr_locale
15847c2fbfb3SApril Chin 	ip->LC_TYPE_init.disc = &LC_disc;
15857c2fbfb3SApril Chin 	ip->LC_TYPE_init.nofree = 1;
15867c2fbfb3SApril Chin 	ip->LC_NUM_init.disc = &LC_disc;
15877c2fbfb3SApril Chin 	ip->LC_NUM_init.nofree = 1;
15887c2fbfb3SApril Chin 	ip->LC_COLL_init.disc = &LC_disc;
15897c2fbfb3SApril Chin 	ip->LC_COLL_init.nofree = 1;
15907c2fbfb3SApril Chin 	ip->LC_MSG_init.disc = &LC_disc;
15917c2fbfb3SApril Chin 	ip->LC_MSG_init.nofree = 1;
15927c2fbfb3SApril Chin 	ip->LC_ALL_init.disc = &LC_disc;
15937c2fbfb3SApril Chin 	ip->LC_ALL_init.nofree = 1;
15947c2fbfb3SApril Chin 	ip->LANG_init.disc = &LC_disc;
15957c2fbfb3SApril Chin 	ip->LANG_init.nofree = 1;
1596da2e3ebdSchin #endif /* _hdr_locale */
1597da2e3ebdSchin 	nv_stack(IFSNOD, &ip->IFS_init.hdr);
15987c2fbfb3SApril Chin 	nv_stack(PATHNOD, &ip->PATH_init);
15997c2fbfb3SApril Chin 	nv_stack(FPATHNOD, &ip->FPATH_init);
16007c2fbfb3SApril Chin 	nv_stack(CDPNOD, &ip->CDPATH_init);
16017c2fbfb3SApril Chin 	nv_stack(SHELLNOD, &ip->SHELL_init);
16027c2fbfb3SApril Chin 	nv_stack(ENVNOD, &ip->ENV_init);
16037c2fbfb3SApril Chin 	nv_stack(VISINOD, &ip->VISUAL_init);
16047c2fbfb3SApril Chin 	nv_stack(EDITNOD, &ip->EDITOR_init);
16057c2fbfb3SApril Chin 	nv_stack(HISTFILE, &ip->HISTFILE_init);
16067c2fbfb3SApril Chin 	nv_stack(HISTSIZE, &ip->HISTSIZE_init);
16077c2fbfb3SApril Chin 	nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
1608da2e3ebdSchin 	nv_stack(SECONDS, &ip->SECONDS_init.hdr);
16097c2fbfb3SApril Chin 	nv_stack(L_ARGNOD, &ip->L_ARG_init);
16107c2fbfb3SApril Chin 	nv_putval(SECONDS, (char*)&d, NV_DOUBLE);
1611da2e3ebdSchin 	nv_stack(RANDNOD, &ip->RAND_init.hdr);
1612da2e3ebdSchin 	d = (shp->pid&RANDMASK);
16137c2fbfb3SApril Chin 	nv_putval(RANDNOD, (char*)&d, NV_DOUBLE);
16147c2fbfb3SApril Chin 	nv_stack(LINENO, &ip->LINENO_init);
1615da2e3ebdSchin 	nv_putsub(SH_MATCHNOD,(char*)0,10);
1616da2e3ebdSchin 	nv_onattr(SH_MATCHNOD,NV_RDONLY);
1617da2e3ebdSchin 	nv_stack(SH_MATCHNOD, &ip->SH_MATCH_init.hdr);
16187c2fbfb3SApril Chin 	nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init);
1619da2e3ebdSchin #ifdef _hdr_locale
16207c2fbfb3SApril Chin 	nv_stack(LCTYPENOD, &ip->LC_TYPE_init);
16217c2fbfb3SApril Chin 	nv_stack(LCALLNOD, &ip->LC_ALL_init);
16227c2fbfb3SApril Chin 	nv_stack(LCMSGNOD, &ip->LC_MSG_init);
16237c2fbfb3SApril Chin 	nv_stack(LCCOLLNOD, &ip->LC_COLL_init);
16247c2fbfb3SApril Chin 	nv_stack(LCNUMNOD, &ip->LC_NUM_init);
16257c2fbfb3SApril Chin 	nv_stack(LANGNOD, &ip->LANG_init);
1626da2e3ebdSchin #endif /* _hdr_locale */
1627da2e3ebdSchin 	(PPIDNOD)->nvalue.lp = (&shp->ppid);
1628da2e3ebdSchin 	(TMOUTNOD)->nvalue.lp = (&shp->st.tmout);
1629da2e3ebdSchin 	(MCHKNOD)->nvalue.lp = (&sh_mailchk);
1630da2e3ebdSchin 	(OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
1631da2e3ebdSchin 	/* set up the seconds clock */
1632da2e3ebdSchin 	shp->alias_tree = inittree(shp,shtab_aliases);
1633da2e3ebdSchin 	shp->track_tree = dtopen(&_Nvdisc,Dtset);
1634da2e3ebdSchin 	shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
1635da2e3ebdSchin 	shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
1636da2e3ebdSchin 	dtview(shp->fun_tree,shp->bltin_tree);
1637da2e3ebdSchin #if SHOPT_NAMESPACE
1638da2e3ebdSchin 	if(np = nv_mount(DOTSHNOD, "global", shp->var_tree))
1639da2e3ebdSchin 		nv_onattr(np,NV_RDONLY);
1640da2e3ebdSchin 	np = nv_search("namespace",nv_dict(DOTSHNOD),NV_ADD);
1641da2e3ebdSchin 	nv_putval(np,".sh.global",NV_RDONLY|NV_NOFREE);
1642da2e3ebdSchin 	nv_stack(np, &NSPACE_init);
1643da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
16447c2fbfb3SApril Chin 	np = nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
1645da2e3ebdSchin 	nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
16467c2fbfb3SApril Chin 	SH_LINENO->nvalue.ip = &shp->st.lineno;
16477c2fbfb3SApril Chin 	VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0);
16487c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD;
16497c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD);
16507c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->table = DOTSHNOD;
16517c2fbfb3SApril Chin 	nv_onattr(VERSIONNOD,NV_RDONLY|NV_REF);
16527c2fbfb3SApril Chin 	stat_init(shp);
1653da2e3ebdSchin 	return(ip);
1654da2e3ebdSchin }
1655da2e3ebdSchin 
1656da2e3ebdSchin /*
1657da2e3ebdSchin  * initialize name-value pairs
1658da2e3ebdSchin  */
1659da2e3ebdSchin 
inittree(Shell_t * shp,const struct shtable2 * name_vals)1660da2e3ebdSchin static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals)
1661da2e3ebdSchin {
1662da2e3ebdSchin 	register Namval_t *np;
1663da2e3ebdSchin 	register const struct shtable2 *tp;
1664da2e3ebdSchin 	register unsigned n = 0;
1665da2e3ebdSchin 	register Dt_t *treep;
1666da2e3ebdSchin 	Dt_t *base_treep, *dict;
1667da2e3ebdSchin 	for(tp=name_vals;*tp->sh_name;tp++)
1668da2e3ebdSchin 		n++;
1669da2e3ebdSchin 	np = (Namval_t*)calloc(n,sizeof(Namval_t));
1670da2e3ebdSchin 	if(!shp->bltin_nodes)
16717c2fbfb3SApril Chin 	{
1672da2e3ebdSchin 		shp->bltin_nodes = np;
16737c2fbfb3SApril Chin 		shp->bltin_nnodes = n;
16747c2fbfb3SApril Chin 	}
1675da2e3ebdSchin 	else if(name_vals==(const struct shtable2*)shtab_builtins)
16767c2fbfb3SApril Chin 	{
1677da2e3ebdSchin 		shp->bltin_cmds = np;
16787c2fbfb3SApril Chin 		nbltins = n;
16797c2fbfb3SApril Chin 	}
1680da2e3ebdSchin 	base_treep = treep = dtopen(&_Nvdisc,Dtoset);
16817c2fbfb3SApril Chin 	treep->user = (void*)shp;
1682da2e3ebdSchin 	for(tp=name_vals;*tp->sh_name;tp++,np++)
1683da2e3ebdSchin 	{
1684da2e3ebdSchin 		if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name))
1685da2e3ebdSchin 			np->nvname++;
1686da2e3ebdSchin 		else
1687da2e3ebdSchin 		{
1688da2e3ebdSchin 			np->nvname = (char*)tp->sh_name;
1689da2e3ebdSchin 			treep = base_treep;
1690da2e3ebdSchin 		}
1691da2e3ebdSchin 		np->nvenv = 0;
1692da2e3ebdSchin 		if(name_vals==(const struct shtable2*)shtab_builtins)
1693da2e3ebdSchin 			np->nvalue.bfp = ((struct shtable3*)tp)->sh_value;
1694da2e3ebdSchin 		else
16957c2fbfb3SApril Chin 		{
16967c2fbfb3SApril Chin 			if(name_vals == shtab_variables)
16977c2fbfb3SApril Chin 				np->nvfun = &sh.nvfun;
1698da2e3ebdSchin 			np->nvalue.cp = (char*)tp->sh_value;
16997c2fbfb3SApril Chin 		}
1700da2e3ebdSchin 		nv_setattr(np,tp->sh_number);
1701da2e3ebdSchin 		if(nv_istable(np))
1702da2e3ebdSchin 			nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset));
1703da2e3ebdSchin 		if(nv_isattr(np,NV_INTEGER))
1704da2e3ebdSchin 			nv_setsize(np,10);
1705da2e3ebdSchin 		else
1706da2e3ebdSchin 			nv_setsize(np,0);
1707da2e3ebdSchin 		dtinsert(treep,np);
1708da2e3ebdSchin 		if(nv_istable(np))
1709da2e3ebdSchin 			treep = dict;
1710da2e3ebdSchin 	}
1711da2e3ebdSchin 	return(treep);
1712da2e3ebdSchin }
1713da2e3ebdSchin 
1714da2e3ebdSchin /*
1715da2e3ebdSchin  * read in the process environment and set up name-value pairs
1716da2e3ebdSchin  * skip over items that are not name-value pairs
1717da2e3ebdSchin  */
1718da2e3ebdSchin 
env_init(Shell_t * shp)1719da2e3ebdSchin static void env_init(Shell_t *shp)
1720da2e3ebdSchin {
1721da2e3ebdSchin 	register char *cp;
1722da2e3ebdSchin 	register Namval_t	*np;
1723da2e3ebdSchin 	register char **ep=environ;
1724da2e3ebdSchin 	register char *next=0;
1725da2e3ebdSchin #ifdef _ENV_H
1726da2e3ebdSchin 	shp->env = env_open(environ,3);
1727da2e3ebdSchin 	env_delete(shp->env,"_");
1728da2e3ebdSchin #endif
1729da2e3ebdSchin 	if(ep)
1730da2e3ebdSchin 	{
1731da2e3ebdSchin 		while(cp= *ep++)
1732da2e3ebdSchin 		{
1733da2e3ebdSchin 			if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]=='=')
1734da2e3ebdSchin 				next = cp+4;
1735da2e3ebdSchin 			else if(np=nv_open(cp,shp->var_tree,(NV_EXPORT|NV_IDENT|NV_ASSIGN|NV_NOFAIL)))
1736da2e3ebdSchin 			{
1737da2e3ebdSchin 				nv_onattr(np,NV_IMPORT);
1738da2e3ebdSchin 				np->nvenv = cp;
1739da2e3ebdSchin 				nv_close(np);
1740da2e3ebdSchin 			}
1741*3e14f97fSRoger A. Faulkner 			else  /* swap with front */
17427c2fbfb3SApril Chin 			{
17437c2fbfb3SApril Chin 				ep[-1] = environ[shp->nenv];
17447c2fbfb3SApril Chin 				environ[shp->nenv++] = cp;
17457c2fbfb3SApril Chin 			}
1746da2e3ebdSchin 		}
1747da2e3ebdSchin 		while(cp=next)
1748da2e3ebdSchin 		{
1749da2e3ebdSchin 			if(next = strchr(++cp,'='))
1750da2e3ebdSchin 				*next = 0;
1751da2e3ebdSchin 			np = nv_search(cp+2,shp->var_tree,NV_ADD);
1752*3e14f97fSRoger A. Faulkner 			if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
1753da2e3ebdSchin 			{
1754da2e3ebdSchin 				int flag = *(unsigned char*)cp-' ';
1755da2e3ebdSchin 				int size = *(unsigned char*)(cp+1)-' ';
1756da2e3ebdSchin 				if((flag&NV_INTEGER) && size==0)
1757da2e3ebdSchin 				{
1758da2e3ebdSchin 					/* check for floating*/
1759da2e3ebdSchin 					char *ep,*val = nv_getval(np);
1760da2e3ebdSchin 					strtol(val,&ep,10);
1761da2e3ebdSchin 					if(*ep=='.' || *ep=='e' || *ep=='E')
1762da2e3ebdSchin 					{
1763da2e3ebdSchin 						char *lp;
1764da2e3ebdSchin 						flag |= NV_DOUBLE;
1765da2e3ebdSchin 						if(*ep=='.')
1766da2e3ebdSchin 						{
1767da2e3ebdSchin 							strtol(ep+1,&lp,10);
1768da2e3ebdSchin 							if(*lp)
1769da2e3ebdSchin 								ep = lp;
1770da2e3ebdSchin 						}
1771da2e3ebdSchin 						if(*ep && *ep!='.')
1772da2e3ebdSchin 						{
1773da2e3ebdSchin 							flag |= NV_EXPNOTE;
1774da2e3ebdSchin 							size = ep-val;
1775da2e3ebdSchin 						}
1776da2e3ebdSchin 						else
1777da2e3ebdSchin 							size = strlen(ep);
1778da2e3ebdSchin 						size--;
1779da2e3ebdSchin 					}
1780da2e3ebdSchin 				}
1781da2e3ebdSchin 				nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
1782da2e3ebdSchin 			}
1783*3e14f97fSRoger A. Faulkner 			else
1784*3e14f97fSRoger A. Faulkner 				cp += 2;
1785da2e3ebdSchin 		}
1786da2e3ebdSchin 	}
1787da2e3ebdSchin #ifdef _ENV_H
17887c2fbfb3SApril Chin 	env_delete(shp->env,e_envmarker);
1789da2e3ebdSchin #endif
1790da2e3ebdSchin 	if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
1791da2e3ebdSchin 	{
1792da2e3ebdSchin 		nv_offattr(PWDNOD,NV_TAGGED);
1793da2e3ebdSchin 		path_pwd(0);
1794da2e3ebdSchin 	}
1795da2e3ebdSchin 	if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
1796da2e3ebdSchin 		sh_onoption(SH_RESTRICTED); /* restricted shell */
1797da2e3ebdSchin 	return;
1798da2e3ebdSchin }
1799da2e3ebdSchin 
1800da2e3ebdSchin /*
1801da2e3ebdSchin  * terminate shell and free up the space
1802da2e3ebdSchin  */
sh_term(void)1803da2e3ebdSchin int sh_term(void)
1804da2e3ebdSchin {
1805da2e3ebdSchin 	sfdisc(sfstdin,SF_POPDISC);
1806da2e3ebdSchin 	free((char*)sh.outbuff);
1807da2e3ebdSchin 	stakset(NIL(char*),0);
1808da2e3ebdSchin 	return(0);
1809da2e3ebdSchin }
1810da2e3ebdSchin 
1811da2e3ebdSchin /* function versions of these */
1812da2e3ebdSchin 
1813da2e3ebdSchin #define DISABLE	/* proto workaround */
1814da2e3ebdSchin 
DISABLE(int opt)1815da2e3ebdSchin unsigned long sh_isoption DISABLE (int opt)
1816da2e3ebdSchin {
1817da2e3ebdSchin 	return(sh_isoption(opt));
1818da2e3ebdSchin }
1819da2e3ebdSchin 
DISABLE(int opt)1820da2e3ebdSchin unsigned long sh_onoption DISABLE (int opt)
1821da2e3ebdSchin {
1822da2e3ebdSchin 	return(sh_onoption(opt));
1823da2e3ebdSchin }
1824da2e3ebdSchin 
DISABLE(int opt)1825da2e3ebdSchin unsigned long sh_offoption DISABLE (int opt)
1826da2e3ebdSchin {
1827da2e3ebdSchin 	return(sh_offoption(opt));
1828da2e3ebdSchin }
1829da2e3ebdSchin 
DISABLE(void)1830da2e3ebdSchin void	sh_sigcheck DISABLE (void)
1831da2e3ebdSchin {
1832da2e3ebdSchin 	sh_sigcheck();
1833da2e3ebdSchin }
1834da2e3ebdSchin 
DISABLE(void)1835da2e3ebdSchin Dt_t*	sh_bltin_tree DISABLE (void)
1836da2e3ebdSchin {
1837da2e3ebdSchin 	return(sh.bltin_tree);
1838da2e3ebdSchin }
1839