xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/init.c (revision b30d1939)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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>
35*b30d1939SAndy Fiddaman #include        <regex.h>
36da2e3ebdSchin #include        "variables.h"
37da2e3ebdSchin #include        "path.h"
38da2e3ebdSchin #include        "fault.h"
39da2e3ebdSchin #include        "name.h"
40da2e3ebdSchin #include	"edit.h"
41da2e3ebdSchin #include	"jobs.h"
42da2e3ebdSchin #include	"io.h"
43da2e3ebdSchin #include	"shlex.h"
44da2e3ebdSchin #include	"builtins.h"
45da2e3ebdSchin #include	"FEATURE/time"
46da2e3ebdSchin #include	"FEATURE/dynamic"
4734f9b3eeSRoland Mainz #include	"FEATURE/externs"
48da2e3ebdSchin #include	"lexstates.h"
49da2e3ebdSchin #include	"version.h"
50da2e3ebdSchin 
51*b30d1939SAndy Fiddaman #if _hdr_wctype
52*b30d1939SAndy Fiddaman #include	<ast_wchar.h>
53*b30d1939SAndy Fiddaman #include	<wctype.h>
54*b30d1939SAndy Fiddaman #endif
55*b30d1939SAndy Fiddaman #if !_typ_wctrans_t
56*b30d1939SAndy Fiddaman #undef	wctrans_t
57*b30d1939SAndy Fiddaman #define wctrans_t	sh_wctrans_t
58*b30d1939SAndy Fiddaman typedef long wctrans_t;
59*b30d1939SAndy Fiddaman #endif
60*b30d1939SAndy Fiddaman #if !_lib_wctrans
61*b30d1939SAndy Fiddaman #undef	wctrans
62*b30d1939SAndy Fiddaman #define wctrans		sh_wctrans
wctrans(const char * name)63*b30d1939SAndy Fiddaman static wctrans_t wctrans(const char *name)
64*b30d1939SAndy Fiddaman {
65*b30d1939SAndy Fiddaman 	if(strcmp(name,e_tolower)==0)
66*b30d1939SAndy Fiddaman 		return(1);
67*b30d1939SAndy Fiddaman 	else if(strcmp(name,e_toupper)==0)
68*b30d1939SAndy Fiddaman 		return(2);
69*b30d1939SAndy Fiddaman 	return(0);
70*b30d1939SAndy Fiddaman }
71*b30d1939SAndy Fiddaman #endif
72*b30d1939SAndy Fiddaman #if !_lib_towctrans
73*b30d1939SAndy Fiddaman #undef	towctrans
74*b30d1939SAndy Fiddaman #define towctrans	sh_towctrans
towctrans(int c,wctrans_t t)75*b30d1939SAndy Fiddaman static int towctrans(int c, wctrans_t t)
76*b30d1939SAndy Fiddaman {
77*b30d1939SAndy Fiddaman 	if(t==1 && isupper(c))
78*b30d1939SAndy Fiddaman 		c = tolower(c);
79*b30d1939SAndy Fiddaman 	else if(t==2 && islower(c))
80*b30d1939SAndy Fiddaman 		c = toupper(c);
81*b30d1939SAndy Fiddaman 	return(c);
82*b30d1939SAndy Fiddaman }
83*b30d1939SAndy Fiddaman #endif
84*b30d1939SAndy Fiddaman 
857c2fbfb3SApril Chin char e_version[]	= "\n@(#)$Id: Version "
867c2fbfb3SApril Chin #if SHOPT_AUDIT
877c2fbfb3SApril Chin #define ATTRS		1
887c2fbfb3SApril Chin 			"A"
897c2fbfb3SApril Chin #endif
907c2fbfb3SApril Chin #if SHOPT_BASH
917c2fbfb3SApril Chin #define ATTRS		1
927c2fbfb3SApril Chin 			"B"
937c2fbfb3SApril Chin #endif
94*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
9534f9b3eeSRoland Mainz #define ATTRS		1
9634f9b3eeSRoland Mainz 			"J"
97*b30d1939SAndy Fiddaman #else
98*b30d1939SAndy Fiddaman #if SHOPT_BGX
99*b30d1939SAndy Fiddaman #define ATTRS		1
100*b30d1939SAndy Fiddaman 			"j"
101*b30d1939SAndy Fiddaman #endif
10234f9b3eeSRoland Mainz #endif
1037c2fbfb3SApril Chin #if SHOPT_ACCT
1047c2fbfb3SApril Chin #define ATTRS		1
1057c2fbfb3SApril Chin 			"L"
1067c2fbfb3SApril Chin #endif
107da2e3ebdSchin #if SHOPT_MULTIBYTE
1087c2fbfb3SApril Chin #define ATTRS		1
1097c2fbfb3SApril Chin 			"M"
1107c2fbfb3SApril Chin #endif
1117c2fbfb3SApril Chin #if SHOPT_PFSH && _hdr_exec_attr
1127c2fbfb3SApril Chin #define ATTRS		1
1137c2fbfb3SApril Chin 			"P"
1147c2fbfb3SApril Chin #endif
11534f9b3eeSRoland Mainz #if SHOPT_REGRESS
11634f9b3eeSRoland Mainz #define ATTRS		1
11734f9b3eeSRoland Mainz 			"R"
11834f9b3eeSRoland Mainz #endif
1197c2fbfb3SApril Chin #if ATTRS
1207c2fbfb3SApril Chin 			" "
1217c2fbfb3SApril Chin #endif
1227c2fbfb3SApril Chin 			SH_RELEASE " $\0\n";
123da2e3ebdSchin 
124da2e3ebdSchin #if SHOPT_BASH
1257c2fbfb3SApril Chin     extern void bash_init(Shell_t*,int);
126da2e3ebdSchin #endif
127da2e3ebdSchin 
128da2e3ebdSchin #define RANDMASK	0x7fff
1297c2fbfb3SApril Chin 
1307c2fbfb3SApril Chin #ifndef ARG_MAX
1317c2fbfb3SApril Chin #   define ARG_MAX	(1*1024*1024)
1327c2fbfb3SApril Chin #endif
1337c2fbfb3SApril Chin #ifndef CHILD_MAX
1347c2fbfb3SApril Chin #   define CHILD_MAX	(1*1024)
1357c2fbfb3SApril Chin #endif
136da2e3ebdSchin #ifndef CLK_TCK
137da2e3ebdSchin #   define CLK_TCK	60
138da2e3ebdSchin #endif /* CLK_TCK */
139da2e3ebdSchin 
140da2e3ebdSchin #ifndef environ
141da2e3ebdSchin     extern char	**environ;
142da2e3ebdSchin #endif
143da2e3ebdSchin 
144da2e3ebdSchin #undef	getconf
145da2e3ebdSchin #define getconf(x)	strtol(astconf(x,NiL,NiL),NiL,0)
146da2e3ebdSchin 
147da2e3ebdSchin struct seconds
148da2e3ebdSchin {
149da2e3ebdSchin 	Namfun_t	hdr;
150da2e3ebdSchin 	Shell_t		*sh;
151da2e3ebdSchin };
152da2e3ebdSchin 
153da2e3ebdSchin struct rand
154da2e3ebdSchin {
155da2e3ebdSchin 	Namfun_t	hdr;
156*b30d1939SAndy Fiddaman 	Shell_t		*sh;
157da2e3ebdSchin 	int32_t		rand_last;
158da2e3ebdSchin };
159da2e3ebdSchin 
160da2e3ebdSchin struct ifs
161da2e3ebdSchin {
162da2e3ebdSchin 	Namfun_t	hdr;
163da2e3ebdSchin 	Namval_t	*ifsnp;
164da2e3ebdSchin };
165da2e3ebdSchin 
166da2e3ebdSchin struct match
167da2e3ebdSchin {
168da2e3ebdSchin 	Namfun_t	hdr;
169*b30d1939SAndy Fiddaman 	const char	*v;
170da2e3ebdSchin 	char		*val;
171*b30d1939SAndy Fiddaman 	char		*rval[2];
172*b30d1939SAndy Fiddaman 	regoff_t	*match;
173*b30d1939SAndy Fiddaman 	char		node[NV_MINSZ+sizeof(char*)];
174*b30d1939SAndy Fiddaman 	regoff_t	first;
175da2e3ebdSchin 	int		vsize;
176da2e3ebdSchin 	int		nmatch;
177*b30d1939SAndy Fiddaman 	int		index;
178*b30d1939SAndy Fiddaman 	int		lastsub[2];
179da2e3ebdSchin };
180da2e3ebdSchin 
181da2e3ebdSchin typedef struct _init_
182da2e3ebdSchin {
183da2e3ebdSchin 	Shell_t		*sh;
184da2e3ebdSchin #if SHOPT_FS_3D
185da2e3ebdSchin 	Namfun_t	VPATH_init;
186da2e3ebdSchin #endif /* SHOPT_FS_3D */
187da2e3ebdSchin 	struct ifs	IFS_init;
1887c2fbfb3SApril Chin 	Namfun_t	PATH_init;
1897c2fbfb3SApril Chin 	Namfun_t	FPATH_init;
1907c2fbfb3SApril Chin 	Namfun_t	CDPATH_init;
1917c2fbfb3SApril Chin 	Namfun_t	SHELL_init;
1927c2fbfb3SApril Chin 	Namfun_t	ENV_init;
1937c2fbfb3SApril Chin 	Namfun_t	VISUAL_init;
1947c2fbfb3SApril Chin 	Namfun_t	EDITOR_init;
1957c2fbfb3SApril Chin 	Namfun_t	HISTFILE_init;
1967c2fbfb3SApril Chin 	Namfun_t	HISTSIZE_init;
1977c2fbfb3SApril Chin 	Namfun_t	OPTINDEX_init;
198da2e3ebdSchin 	struct seconds	SECONDS_init;
199da2e3ebdSchin 	struct rand	RAND_init;
2007c2fbfb3SApril Chin 	Namfun_t	LINENO_init;
2017c2fbfb3SApril Chin 	Namfun_t	L_ARG_init;
2027c2fbfb3SApril Chin 	Namfun_t	SH_VERSION_init;
203da2e3ebdSchin 	struct match	SH_MATCH_init;
204*b30d1939SAndy Fiddaman 	Namfun_t	SH_MATH_init;
205*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
206*b30d1939SAndy Fiddaman 	Namfun_t	SH_JOBPOOL_init;
207*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
208da2e3ebdSchin #ifdef _hdr_locale
2097c2fbfb3SApril Chin 	Namfun_t	LC_TYPE_init;
2107c2fbfb3SApril Chin 	Namfun_t	LC_NUM_init;
2117c2fbfb3SApril Chin 	Namfun_t	LC_COLL_init;
2127c2fbfb3SApril Chin 	Namfun_t	LC_MSG_init;
2137c2fbfb3SApril Chin 	Namfun_t	LC_ALL_init;
2147c2fbfb3SApril Chin 	Namfun_t	LANG_init;
215da2e3ebdSchin #endif /* _hdr_locale */
216da2e3ebdSchin } Init_t;
217da2e3ebdSchin 
218*b30d1939SAndy Fiddaman static Init_t		*ip;
219*b30d1939SAndy Fiddaman static int		lctype;
2207c2fbfb3SApril Chin static int		nbltins;
221da2e3ebdSchin static void		env_init(Shell_t*);
222da2e3ebdSchin static Init_t		*nv_init(Shell_t*);
223da2e3ebdSchin static Dt_t		*inittree(Shell_t*,const struct shtable2*);
22434f9b3eeSRoland Mainz static int		shlvl;
225da2e3ebdSchin 
226da2e3ebdSchin #ifdef _WINIX
227da2e3ebdSchin #   define EXE	"?(.exe)"
228da2e3ebdSchin #else
229da2e3ebdSchin #   define EXE
230da2e3ebdSchin #endif
231da2e3ebdSchin 
232da2e3ebdSchin static int		rand_shift;
233da2e3ebdSchin 
234da2e3ebdSchin 
235da2e3ebdSchin /*
236da2e3ebdSchin  * Invalidate all path name bindings
237da2e3ebdSchin  */
rehash(register Namval_t * np,void * data)238da2e3ebdSchin static void rehash(register Namval_t *np,void *data)
239da2e3ebdSchin {
240da2e3ebdSchin 	NOT_USED(data);
241da2e3ebdSchin 	nv_onattr(np,NV_NOALIAS);
242da2e3ebdSchin }
243da2e3ebdSchin 
244da2e3ebdSchin /*
245da2e3ebdSchin  * out of memory routine for stak routines
246da2e3ebdSchin  */
nospace(int unused)247da2e3ebdSchin static char *nospace(int unused)
248da2e3ebdSchin {
249da2e3ebdSchin 	NOT_USED(unused);
250da2e3ebdSchin 	errormsg(SH_DICT,ERROR_exit(3),e_nospace);
251da2e3ebdSchin 	return(NIL(char*));
252da2e3ebdSchin }
253da2e3ebdSchin 
254da2e3ebdSchin /* Trap for VISUAL and EDITOR variables */
put_ed(register Namval_t * np,const char * val,int flags,Namfun_t * fp)255da2e3ebdSchin static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
256da2e3ebdSchin {
257da2e3ebdSchin 	register const char *cp, *name=nv_name(np);
25834f9b3eeSRoland Mainz 	register int	newopt=0;
2597c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
2607c2fbfb3SApril Chin 	if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
261da2e3ebdSchin 		goto done;
2627c2fbfb3SApril Chin 	if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
263da2e3ebdSchin 		goto done;
264da2e3ebdSchin 	/* turn on vi or emacs option if editor name is either*/
265da2e3ebdSchin 	cp = path_basename(cp);
266da2e3ebdSchin 	if(strmatch(cp,"*[Vv][Ii]*"))
26734f9b3eeSRoland Mainz 		newopt=SH_VI;
268da2e3ebdSchin 	else if(strmatch(cp,"*gmacs*"))
26934f9b3eeSRoland Mainz 		newopt=SH_GMACS;
270da2e3ebdSchin 	else if(strmatch(cp,"*macs*"))
27134f9b3eeSRoland Mainz 		newopt=SH_EMACS;
27234f9b3eeSRoland Mainz 	if(newopt)
27334f9b3eeSRoland Mainz 	{
27434f9b3eeSRoland Mainz 		sh_offoption(SH_VI);
27534f9b3eeSRoland Mainz 		sh_offoption(SH_EMACS);
27634f9b3eeSRoland Mainz 		sh_offoption(SH_GMACS);
27734f9b3eeSRoland Mainz 		sh_onoption(newopt);
27834f9b3eeSRoland Mainz 	}
279da2e3ebdSchin done:
280da2e3ebdSchin 	nv_putv(np, val, flags, fp);
281da2e3ebdSchin }
282da2e3ebdSchin 
2837c2fbfb3SApril Chin /* Trap for HISTFILE and HISTSIZE variables */
put_history(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2847c2fbfb3SApril Chin static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2857c2fbfb3SApril Chin {
2867c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
287*b30d1939SAndy Fiddaman 	void 	*histopen = NULL;
28834f9b3eeSRoland Mainz 	char	*cp;
289*b30d1939SAndy Fiddaman 	if( shp ) {
290*b30d1939SAndy Fiddaman 	    histopen = shp->gd->hist_ptr;
291*b30d1939SAndy Fiddaman 	}
2927c2fbfb3SApril Chin 	if(val && histopen)
2937c2fbfb3SApril Chin 	{
29434f9b3eeSRoland Mainz 		if(np==HISTFILE && (cp=nv_getval(np)) && strcmp(val,cp)==0)
2957c2fbfb3SApril Chin 			return;
296*b30d1939SAndy Fiddaman 		if(np==HISTSIZE && sh_arith(shp,val)==nv_getnum(HISTSIZE))
2977c2fbfb3SApril Chin 			return;
298*b30d1939SAndy Fiddaman 		hist_close(shp->gd->hist_ptr);
2997c2fbfb3SApril Chin 	}
3007c2fbfb3SApril Chin 	nv_putv(np, val, flags, fp);
3017c2fbfb3SApril Chin 	if(histopen)
3027c2fbfb3SApril Chin 	{
3037c2fbfb3SApril Chin 		if(val)
3047c2fbfb3SApril Chin 			sh_histinit(shp);
3057c2fbfb3SApril Chin 		else
3067c2fbfb3SApril Chin 			hist_close(histopen);
3077c2fbfb3SApril Chin 	}
3087c2fbfb3SApril Chin }
3097c2fbfb3SApril Chin 
310da2e3ebdSchin /* Trap for OPTINDEX */
put_optindex(Namval_t * np,const char * val,int flags,Namfun_t * fp)311da2e3ebdSchin static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
312da2e3ebdSchin {
3137c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
314da2e3ebdSchin 	shp->st.opterror = shp->st.optchar = 0;
315da2e3ebdSchin 	nv_putv(np, val, flags, fp);
3167c2fbfb3SApril Chin 	if(!val)
3177c2fbfb3SApril Chin 		nv_disc(np,fp,NV_POP);
318da2e3ebdSchin }
319da2e3ebdSchin 
nget_optindex(register Namval_t * np,Namfun_t * fp)320da2e3ebdSchin static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp)
321da2e3ebdSchin {
322da2e3ebdSchin 	return((Sfdouble_t)*np->nvalue.lp);
323da2e3ebdSchin }
324da2e3ebdSchin 
clone_optindex(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)3257c2fbfb3SApril Chin static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
3267c2fbfb3SApril Chin {
3277c2fbfb3SApril Chin 	Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t));
3287c2fbfb3SApril Chin 	memcpy((void*)dp,(void*)fp,sizeof(Namfun_t));
3297c2fbfb3SApril Chin 	mp->nvalue.lp = np->nvalue.lp;
3307c2fbfb3SApril Chin 	dp->nofree = 0;
3317c2fbfb3SApril Chin 	return(dp);
3327c2fbfb3SApril Chin }
3337c2fbfb3SApril Chin 
3347c2fbfb3SApril Chin 
335da2e3ebdSchin /* Trap for restricted variables FPATH, PATH, SHELL, ENV */
put_restricted(register Namval_t * np,const char * val,int flags,Namfun_t * fp)336da2e3ebdSchin static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
337da2e3ebdSchin {
3387c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
339*b30d1939SAndy Fiddaman 	int	path_scoped = 0, fpath_scoped=0;
340da2e3ebdSchin 	Pathcomp_t *pp;
341da2e3ebdSchin 	char *name = nv_name(np);
342da2e3ebdSchin 	if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED))
343da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
344da2e3ebdSchin 	if(np==PATHNOD	|| (path_scoped=(strcmp(name,PATHNOD->nvname)==0)))
345da2e3ebdSchin 	{
346da2e3ebdSchin 		nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
347da2e3ebdSchin 		if(path_scoped && !val)
348da2e3ebdSchin 			val = PATHNOD->nvalue.cp;
349da2e3ebdSchin 	}
350da2e3ebdSchin 	if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0)
351da2e3ebdSchin 		 return;
352*b30d1939SAndy Fiddaman 	if(np==FPATHNOD	|| (fpath_scoped=(strcmp(name,FPATHNOD->nvname)==0)))
353*b30d1939SAndy Fiddaman 		shp->pathlist = (void*)path_unsetfpath(shp);
354da2e3ebdSchin 	nv_putv(np, val, flags, fp);
3557c2fbfb3SApril Chin 	shp->universe = 0;
356da2e3ebdSchin 	if(shp->pathlist)
357da2e3ebdSchin 	{
358da2e3ebdSchin 		val = np->nvalue.cp;
359da2e3ebdSchin 		if(np==PATHNOD || path_scoped)
360*b30d1939SAndy Fiddaman 			pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
361*b30d1939SAndy Fiddaman 		else if(val && (np==FPATHNOD || fpath_scoped))
362*b30d1939SAndy Fiddaman 			pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
363da2e3ebdSchin 		else
364da2e3ebdSchin 			return;
365da2e3ebdSchin 		if(shp->pathlist = (void*)pp)
366da2e3ebdSchin 			pp->shp = shp;
367da2e3ebdSchin 		if(!val && (flags&NV_NOSCOPE))
368da2e3ebdSchin 		{
369da2e3ebdSchin 			Namval_t *mp = dtsearch(shp->var_tree,np);
370da2e3ebdSchin 			if(mp && (val=nv_getval(mp)))
371da2e3ebdSchin 				nv_putval(mp,val,NV_RDONLY);
372da2e3ebdSchin 		}
373da2e3ebdSchin #if 0
374da2e3ebdSchin sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val);
375da2e3ebdSchin path_dump((Pathcomp_t*)shp->pathlist);
376da2e3ebdSchin #endif
377da2e3ebdSchin 	}
378da2e3ebdSchin }
379da2e3ebdSchin 
put_cdpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)380da2e3ebdSchin static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
381da2e3ebdSchin {
382da2e3ebdSchin 	Pathcomp_t *pp;
3837c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
384da2e3ebdSchin 	nv_putv(np, val, flags, fp);
385da2e3ebdSchin 	if(!shp->cdpathlist)
386da2e3ebdSchin 		return;
387da2e3ebdSchin 	val = np->nvalue.cp;
388*b30d1939SAndy Fiddaman 	pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH);
389da2e3ebdSchin 	if(shp->cdpathlist = (void*)pp)
390da2e3ebdSchin 		pp->shp = shp;
391da2e3ebdSchin }
392da2e3ebdSchin 
393da2e3ebdSchin #ifdef _hdr_locale
394da2e3ebdSchin     /*
395da2e3ebdSchin      * This function needs to be modified to handle international
396da2e3ebdSchin      * error message translations
397da2e3ebdSchin      */
398da2e3ebdSchin #if ERROR_VERSION >= 20000101L
msg_translate(const char * catalog,const char * message)399da2e3ebdSchin     static char* msg_translate(const char* catalog, const char* message)
400da2e3ebdSchin     {
401da2e3ebdSchin 	NOT_USED(catalog);
402da2e3ebdSchin 	return((char*)message);
403da2e3ebdSchin     }
404da2e3ebdSchin #else
msg_translate(const char * message,int type)405da2e3ebdSchin     static char* msg_translate(const char* message, int type)
406da2e3ebdSchin     {
407da2e3ebdSchin 	NOT_USED(type);
408da2e3ebdSchin 	return((char*)message);
409da2e3ebdSchin     }
410da2e3ebdSchin #endif
411da2e3ebdSchin 
41234f9b3eeSRoland 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)413da2e3ebdSchin     static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
414da2e3ebdSchin     {
4157c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
416da2e3ebdSchin 	int type;
417da2e3ebdSchin 	char *name = nv_name(np);
418da2e3ebdSchin 	if(name==(LCALLNOD)->nvname)
419da2e3ebdSchin 		type = LC_ALL;
420da2e3ebdSchin 	else if(name==(LCTYPENOD)->nvname)
421da2e3ebdSchin 		type = LC_CTYPE;
422da2e3ebdSchin 	else if(name==(LCMSGNOD)->nvname)
423da2e3ebdSchin 		type = LC_MESSAGES;
424da2e3ebdSchin 	else if(name==(LCCOLLNOD)->nvname)
425da2e3ebdSchin 		type = LC_COLLATE;
426da2e3ebdSchin 	else if(name==(LCNUMNOD)->nvname)
427da2e3ebdSchin 		type = LC_NUMERIC;
42834f9b3eeSRoland Mainz #ifdef LC_LANG
42934f9b3eeSRoland Mainz 	else if(name==(LANGNOD)->nvname)
43034f9b3eeSRoland Mainz 		type = LC_LANG;
43134f9b3eeSRoland Mainz #else
43234f9b3eeSRoland Mainz #define LC_LANG		LC_ALL
433*b30d1939SAndy Fiddaman 	else if(name==(LANGNOD)->nvname && (!(name=nv_getval(LCALLNOD)) || !*name))
43434f9b3eeSRoland Mainz 		type = LC_LANG;
43534f9b3eeSRoland Mainz #endif
436da2e3ebdSchin 	else
437da2e3ebdSchin 		type= -1;
4383e14f97fSRoger A. Faulkner 	if(!sh_isstate(SH_INIT) && (type>=0 || type==LC_ALL || type==LC_LANG))
439da2e3ebdSchin 	{
4403e14f97fSRoger A. Faulkner 		char*		r;
4413e14f97fSRoger A. Faulkner #ifdef AST_LC_setenv
4423e14f97fSRoger A. Faulkner 		ast.locale.set |= AST_LC_setenv;
4433e14f97fSRoger A. Faulkner #endif
4443e14f97fSRoger A. Faulkner 		r = setlocale(type,val?val:"");
4453e14f97fSRoger A. Faulkner #ifdef AST_LC_setenv
4463e14f97fSRoger A. Faulkner 		ast.locale.set ^= AST_LC_setenv;
4473e14f97fSRoger A. Faulkner #endif
4483e14f97fSRoger A. Faulkner 		if(!r && val)
449da2e3ebdSchin 		{
4507c2fbfb3SApril Chin 			if(!sh_isstate(SH_INIT) || shp->login_sh==0)
451da2e3ebdSchin 				errormsg(SH_DICT,0,e_badlocale,val);
452da2e3ebdSchin 			return;
453da2e3ebdSchin 		}
454da2e3ebdSchin 	}
4553e14f97fSRoger A. Faulkner 	nv_putv(np, val, flags, fp);
4563e14f97fSRoger A. Faulkner 	if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
457da2e3ebdSchin 	{
458da2e3ebdSchin 		if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
459da2e3ebdSchin 			free((void*)sh_lexstates[ST_BEGIN]);
460*b30d1939SAndy Fiddaman 		lctype++;
461da2e3ebdSchin 		if(ast.locale.set&(1<<AST_LC_CTYPE))
462da2e3ebdSchin 		{
463da2e3ebdSchin 			register int c;
464da2e3ebdSchin 			char *state[4];
465da2e3ebdSchin 			sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT));
466da2e3ebdSchin 			memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT));
467da2e3ebdSchin 			sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT);
468da2e3ebdSchin 			memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT));
469da2e3ebdSchin 			sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT);
470da2e3ebdSchin 			memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT));
471da2e3ebdSchin 			sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT);
472da2e3ebdSchin 			memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT));
473da2e3ebdSchin 			for(c=0; c<(1<<CHAR_BIT); c++)
474da2e3ebdSchin 			{
475da2e3ebdSchin 				if(state[0][c]!=S_REG)
476da2e3ebdSchin 					continue;
477da2e3ebdSchin 				if(state[2][c]!=S_ERR)
478da2e3ebdSchin 					continue;
479da2e3ebdSchin 				if(isblank(c))
480da2e3ebdSchin 				{
481da2e3ebdSchin 					state[0][c]=0;
482da2e3ebdSchin 					state[1][c]=S_BREAK;
483da2e3ebdSchin 					state[2][c]=S_BREAK;
484da2e3ebdSchin 					continue;
485da2e3ebdSchin 				}
486da2e3ebdSchin 				if(!isalpha(c))
487da2e3ebdSchin 					continue;
488da2e3ebdSchin 				state[0][c]=S_NAME;
489da2e3ebdSchin 				if(state[1][c]==S_REG)
490da2e3ebdSchin 					state[1][c]=0;
491da2e3ebdSchin 				state[2][c]=S_ALP;
492da2e3ebdSchin 				if(state[3][c]==S_ERR)
493da2e3ebdSchin 					state[3][c]=0;
494da2e3ebdSchin 			}
495da2e3ebdSchin 		}
496da2e3ebdSchin 		else
497da2e3ebdSchin 		{
498da2e3ebdSchin 			sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN];
499da2e3ebdSchin 			sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME];
500da2e3ebdSchin 			sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL];
501da2e3ebdSchin 			sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE];
502da2e3ebdSchin 		}
503da2e3ebdSchin 	}
504da2e3ebdSchin #if ERROR_VERSION < 20000101L
505da2e3ebdSchin 	if(type==LC_ALL || type==LC_MESSAGES)
506da2e3ebdSchin 		error_info.translate = msg_translate;
507da2e3ebdSchin #endif
508da2e3ebdSchin     }
509da2e3ebdSchin #endif /* _hdr_locale */
510da2e3ebdSchin 
511da2e3ebdSchin /* Trap for IFS assignment and invalidates state table */
put_ifs(register Namval_t * np,const char * val,int flags,Namfun_t * fp)512da2e3ebdSchin static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
513da2e3ebdSchin {
514da2e3ebdSchin 	register struct ifs *ip = (struct ifs*)fp;
515da2e3ebdSchin 	ip->ifsnp = 0;
51634f9b3eeSRoland Mainz 	if(!val)
51734f9b3eeSRoland Mainz 	{
51834f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
51934f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
520*b30d1939SAndy Fiddaman 		{
52134f9b3eeSRoland Mainz 			free((void*)fp);
522*b30d1939SAndy Fiddaman 			fp = 0;
523*b30d1939SAndy Fiddaman 		}
52434f9b3eeSRoland Mainz 	}
525da2e3ebdSchin 	if(val != np->nvalue.cp)
526da2e3ebdSchin 		nv_putv(np, val, flags, fp);
527*b30d1939SAndy Fiddaman 	if(!val)
528*b30d1939SAndy Fiddaman 	{
529*b30d1939SAndy Fiddaman 		if(fp)
530*b30d1939SAndy Fiddaman 			fp->next = np->nvfun;
531*b30d1939SAndy Fiddaman 		np->nvfun = fp;
532*b30d1939SAndy Fiddaman 	}
533da2e3ebdSchin }
534da2e3ebdSchin 
535da2e3ebdSchin /*
536da2e3ebdSchin  * This is the lookup function for IFS
537da2e3ebdSchin  * It keeps the sh.ifstable up to date
538da2e3ebdSchin  */
get_ifs(register Namval_t * np,Namfun_t * fp)539da2e3ebdSchin static char* get_ifs(register Namval_t* np, Namfun_t *fp)
540da2e3ebdSchin {
541da2e3ebdSchin 	register struct ifs *ip = (struct ifs*)fp;
542da2e3ebdSchin 	register char *cp, *value;
543da2e3ebdSchin 	register int c,n;
5447c2fbfb3SApril Chin 	register Shell_t *shp = nv_shell(np);
545da2e3ebdSchin 	value = nv_getv(np,fp);
546da2e3ebdSchin 	if(np!=ip->ifsnp)
547da2e3ebdSchin 	{
548da2e3ebdSchin 		ip->ifsnp = np;
549da2e3ebdSchin 		memset(shp->ifstable,0,(1<<CHAR_BIT));
550da2e3ebdSchin 		if(cp=value)
551da2e3ebdSchin 		{
552da2e3ebdSchin #if SHOPT_MULTIBYTE
553da2e3ebdSchin 			while(n=mbsize(cp),c= *(unsigned char*)cp)
554da2e3ebdSchin #else
555da2e3ebdSchin 			while(c= *(unsigned char*)cp++)
556da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
557da2e3ebdSchin 			{
558da2e3ebdSchin #if SHOPT_MULTIBYTE
559da2e3ebdSchin 				cp++;
560da2e3ebdSchin 				if(n>1)
561da2e3ebdSchin 				{
562da2e3ebdSchin 					cp += (n-1);
563da2e3ebdSchin 					shp->ifstable[c] = S_MBYTE;
564da2e3ebdSchin 					continue;
565da2e3ebdSchin 				}
566da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
567da2e3ebdSchin 				n = S_DELIM;
568da2e3ebdSchin 				if(c== *cp)
569da2e3ebdSchin 					cp++;
570da2e3ebdSchin 				else if(c=='\n')
571da2e3ebdSchin 					n = S_NL;
572da2e3ebdSchin 				else if(isspace(c))
573da2e3ebdSchin 					n = S_SPACE;
574da2e3ebdSchin 				shp->ifstable[c] = n;
575da2e3ebdSchin 			}
576da2e3ebdSchin 		}
577da2e3ebdSchin 		else
578da2e3ebdSchin 		{
579da2e3ebdSchin 			shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
580da2e3ebdSchin 			shp->ifstable['\n'] = S_NL;
581da2e3ebdSchin 		}
582da2e3ebdSchin 	}
583da2e3ebdSchin 	return(value);
584da2e3ebdSchin }
585da2e3ebdSchin 
586da2e3ebdSchin /*
587da2e3ebdSchin  * these functions are used to get and set the SECONDS variable
588da2e3ebdSchin  */
589da2e3ebdSchin #ifdef timeofday
590da2e3ebdSchin #   define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec)))
591da2e3ebdSchin #   define tms	timeval
592da2e3ebdSchin #else
593*b30d1939SAndy Fiddaman #   define dtime(tp)	(((double)times(tp))/shgd->lim.clk_tck)
594da2e3ebdSchin #   define timeofday(a)
595da2e3ebdSchin #endif
596da2e3ebdSchin 
put_seconds(register Namval_t * np,const char * val,int flags,Namfun_t * fp)597da2e3ebdSchin static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
598da2e3ebdSchin {
599da2e3ebdSchin 	double d;
600da2e3ebdSchin 	struct tms tp;
601da2e3ebdSchin 	if(!val)
602da2e3ebdSchin 	{
603*b30d1939SAndy Fiddaman 		nv_putv(np, val, flags, fp);
60434f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
60534f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
60634f9b3eeSRoland Mainz 			free((void*)fp);
607da2e3ebdSchin 		return;
608da2e3ebdSchin 	}
609da2e3ebdSchin 	if(!np->nvalue.dp)
610da2e3ebdSchin 	{
611da2e3ebdSchin 		nv_setsize(np,3);
6127c2fbfb3SApril Chin 		nv_onattr(np,NV_DOUBLE);
613da2e3ebdSchin 		np->nvalue.dp = new_of(double,0);
614da2e3ebdSchin 	}
615da2e3ebdSchin 	nv_putv(np, val, flags, fp);
616da2e3ebdSchin 	d = *np->nvalue.dp;
617da2e3ebdSchin 	timeofday(&tp);
618da2e3ebdSchin 	*np->nvalue.dp = dtime(&tp)-d;
619da2e3ebdSchin }
620da2e3ebdSchin 
get_seconds(register Namval_t * np,Namfun_t * fp)621da2e3ebdSchin static char* get_seconds(register Namval_t* np, Namfun_t *fp)
622da2e3ebdSchin {
6237c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
624da2e3ebdSchin 	register int places = nv_size(np);
625da2e3ebdSchin 	struct tms tp;
626da2e3ebdSchin 	double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
627da2e3ebdSchin 	NOT_USED(fp);
628da2e3ebdSchin 	timeofday(&tp);
629da2e3ebdSchin 	d = dtime(&tp)- offset;
6307c2fbfb3SApril Chin 	sfprintf(shp->strbuf,"%.*f",places,d);
6317c2fbfb3SApril Chin 	return(sfstruse(shp->strbuf));
632da2e3ebdSchin }
633da2e3ebdSchin 
nget_seconds(register Namval_t * np,Namfun_t * fp)634da2e3ebdSchin static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp)
635da2e3ebdSchin {
636da2e3ebdSchin 	struct tms tp;
637da2e3ebdSchin 	double offset = (np->nvalue.dp?*np->nvalue.dp:0);
638da2e3ebdSchin 	NOT_USED(fp);
639da2e3ebdSchin 	timeofday(&tp);
640da2e3ebdSchin 	return(dtime(&tp)- offset);
641da2e3ebdSchin }
642da2e3ebdSchin 
643da2e3ebdSchin /*
644da2e3ebdSchin  * These three functions are used to get and set the RANDOM variable
645da2e3ebdSchin  */
put_rand(register Namval_t * np,const char * val,int flags,Namfun_t * fp)646da2e3ebdSchin static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
647da2e3ebdSchin {
648da2e3ebdSchin 	struct rand *rp = (struct rand*)fp;
649da2e3ebdSchin 	register long n;
650da2e3ebdSchin 	if(!val)
651da2e3ebdSchin 	{
65234f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
65334f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
65434f9b3eeSRoland Mainz 			free((void*)fp);
655*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
656da2e3ebdSchin 		return;
657da2e3ebdSchin 	}
658da2e3ebdSchin 	if(flags&NV_INTEGER)
659da2e3ebdSchin 		n = *(double*)val;
660da2e3ebdSchin 	else
661*b30d1939SAndy Fiddaman 		n = sh_arith(rp->sh,val);
662da2e3ebdSchin 	srand((int)(n&RANDMASK));
663da2e3ebdSchin 	rp->rand_last = -1;
664da2e3ebdSchin 	if(!np->nvalue.lp)
665da2e3ebdSchin 		np->nvalue.lp = &rp->rand_last;
666da2e3ebdSchin }
667da2e3ebdSchin 
668da2e3ebdSchin /*
669da2e3ebdSchin  * get random number in range of 0 - 2**15
670da2e3ebdSchin  * never pick same number twice in a row
671da2e3ebdSchin  */
nget_rand(register Namval_t * np,Namfun_t * fp)672da2e3ebdSchin static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp)
673da2e3ebdSchin {
674da2e3ebdSchin 	register long cur, last= *np->nvalue.lp;
675da2e3ebdSchin 	NOT_USED(fp);
676da2e3ebdSchin 	do
677da2e3ebdSchin 		cur = (rand()>>rand_shift)&RANDMASK;
678da2e3ebdSchin 	while(cur==last);
679da2e3ebdSchin 	*np->nvalue.lp = cur;
680da2e3ebdSchin 	return((Sfdouble_t)cur);
681da2e3ebdSchin }
682da2e3ebdSchin 
get_rand(register Namval_t * np,Namfun_t * fp)683da2e3ebdSchin static char* get_rand(register Namval_t* np, Namfun_t *fp)
684da2e3ebdSchin {
685da2e3ebdSchin 	register long n = nget_rand(np,fp);
686da2e3ebdSchin 	return(fmtbase(n, 10, 0));
687da2e3ebdSchin }
688da2e3ebdSchin 
689da2e3ebdSchin /*
690da2e3ebdSchin  * These three routines are for LINENO
691da2e3ebdSchin  */
nget_lineno(Namval_t * np,Namfun_t * fp)692da2e3ebdSchin static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
693da2e3ebdSchin {
694da2e3ebdSchin 	double d=1;
695da2e3ebdSchin 	if(error_info.line >0)
696da2e3ebdSchin 		d = error_info.line;
697da2e3ebdSchin 	else if(error_info.context && error_info.context->line>0)
698da2e3ebdSchin 		d = error_info.context->line;
699da2e3ebdSchin 	NOT_USED(np);
700da2e3ebdSchin 	NOT_USED(fp);
701da2e3ebdSchin 	return(d);
702da2e3ebdSchin }
703da2e3ebdSchin 
put_lineno(Namval_t * np,const char * val,int flags,Namfun_t * fp)704da2e3ebdSchin static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
705da2e3ebdSchin {
706da2e3ebdSchin 	register long n;
7077c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
708da2e3ebdSchin 	if(!val)
709da2e3ebdSchin 	{
71034f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
71134f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
71234f9b3eeSRoland Mainz 			free((void*)fp);
713*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
714da2e3ebdSchin 		return;
715da2e3ebdSchin 	}
716da2e3ebdSchin 	if(flags&NV_INTEGER)
717da2e3ebdSchin 		n = *(double*)val;
718da2e3ebdSchin 	else
719*b30d1939SAndy Fiddaman 		n = sh_arith(shp,val);
720da2e3ebdSchin 	shp->st.firstline += nget_lineno(np,fp)+1-n;
721da2e3ebdSchin }
722da2e3ebdSchin 
get_lineno(register Namval_t * np,Namfun_t * fp)723da2e3ebdSchin static char* get_lineno(register Namval_t* np, Namfun_t *fp)
724da2e3ebdSchin {
725da2e3ebdSchin 	register long n = nget_lineno(np,fp);
726da2e3ebdSchin 	return(fmtbase(n, 10, 0));
727da2e3ebdSchin }
728da2e3ebdSchin 
get_lastarg(Namval_t * np,Namfun_t * fp)729da2e3ebdSchin static char* get_lastarg(Namval_t* np, Namfun_t *fp)
730da2e3ebdSchin {
73134f9b3eeSRoland Mainz 	Shell_t	*shp = nv_shell(np);
73234f9b3eeSRoland Mainz 	char	*cp;
73334f9b3eeSRoland Mainz 	int	pid;
73434f9b3eeSRoland Mainz         if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
735*b30d1939SAndy Fiddaman 		nv_putval(np,cp+1,0);
7367c2fbfb3SApril Chin 	return(shp->lastarg);
737da2e3ebdSchin }
738da2e3ebdSchin 
put_lastarg(Namval_t * np,const char * val,int flags,Namfun_t * fp)739da2e3ebdSchin static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
740da2e3ebdSchin {
7417c2fbfb3SApril Chin 	Shell_t *shp = nv_shell(np);
742da2e3ebdSchin 	if(flags&NV_INTEGER)
743da2e3ebdSchin 	{
7447c2fbfb3SApril Chin 		sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
7457c2fbfb3SApril Chin 		val = sfstruse(shp->strbuf);
746da2e3ebdSchin 	}
74734f9b3eeSRoland Mainz 	if(val)
74834f9b3eeSRoland Mainz 		val = strdup(val);
7497c2fbfb3SApril Chin 	if(shp->lastarg && !nv_isattr(np,NV_NOFREE))
7507c2fbfb3SApril Chin 		free((void*)shp->lastarg);
751da2e3ebdSchin 	else
752da2e3ebdSchin 		nv_offattr(np,NV_NOFREE);
75334f9b3eeSRoland Mainz 	shp->lastarg = (char*)val;
75434f9b3eeSRoland Mainz 	nv_offattr(np,NV_EXPORT);
75534f9b3eeSRoland Mainz 	np->nvenv = 0;
756da2e3ebdSchin }
757da2e3ebdSchin 
hasgetdisc(register Namfun_t * fp)758da2e3ebdSchin static int hasgetdisc(register Namfun_t *fp)
759da2e3ebdSchin {
760da2e3ebdSchin         while(fp && !fp->disc->getnum && !fp->disc->getval)
761da2e3ebdSchin                 fp = fp->next;
762da2e3ebdSchin 	return(fp!=0);
763da2e3ebdSchin }
764da2e3ebdSchin 
765da2e3ebdSchin /*
766da2e3ebdSchin  * store the most recent value for use in .sh.match
767*b30d1939SAndy Fiddaman  * treat .sh.match as a two dimensional array
768da2e3ebdSchin  */
sh_setmatch(Shell_t * shp,const char * v,int vsize,int nmatch,regoff_t match[],int index)769*b30d1939SAndy Fiddaman void sh_setmatch(Shell_t *shp,const char *v, int vsize, int nmatch, regoff_t match[],int index)
770da2e3ebdSchin {
771*b30d1939SAndy Fiddaman 	struct match	*mp = &ip->SH_MATCH_init;
772*b30d1939SAndy Fiddaman 	Namval_t	*np = nv_namptr(mp->node,0);
773*b30d1939SAndy Fiddaman 	register int	i,n,x, savesub=shp->subshell;
774*b30d1939SAndy Fiddaman 	Namarr_t	*ap = nv_arrayptr(SH_MATCHNOD);
775*b30d1939SAndy Fiddaman 	shp->subshell = 0;
776*b30d1939SAndy Fiddaman #ifndef SHOPT_2DMATCH
777*b30d1939SAndy Fiddaman 	index = 0;
778*b30d1939SAndy Fiddaman #else
779*b30d1939SAndy Fiddaman 	if(index==0)
780*b30d1939SAndy Fiddaman #endif /* SHOPT_2DMATCH */
781da2e3ebdSchin 	{
782*b30d1939SAndy Fiddaman 		if(ap->hdr.next != &mp->hdr)
783da2e3ebdSchin 		{
784*b30d1939SAndy Fiddaman 			free((void*)ap);
785*b30d1939SAndy Fiddaman 			ap = nv_arrayptr(np);
786*b30d1939SAndy Fiddaman 			SH_MATCHNOD->nvfun = &ap->hdr;
787da2e3ebdSchin 		}
788*b30d1939SAndy Fiddaman 		if(ap)
789da2e3ebdSchin 		{
790*b30d1939SAndy Fiddaman 			ap->nelem &= ~ARRAY_SCAN;
791*b30d1939SAndy Fiddaman 			i = array_elem(ap);
792*b30d1939SAndy Fiddaman 			ap->nelem++;
793*b30d1939SAndy Fiddaman 			while(--i>= 0)
794*b30d1939SAndy Fiddaman 			{
795*b30d1939SAndy Fiddaman 				nv_putsub(SH_MATCHNOD, (char*)0,i);
796*b30d1939SAndy Fiddaman 				_nv_unset(SH_MATCHNOD,NV_RDONLY);
797*b30d1939SAndy Fiddaman 			}
798*b30d1939SAndy Fiddaman 			ap->nelem--;
799da2e3ebdSchin 		}
800*b30d1939SAndy Fiddaman 		if(!nv_hasdisc(SH_MATCHNOD,mp->hdr.disc))
801*b30d1939SAndy Fiddaman 			nv_disc(SH_MATCHNOD,&mp->hdr,NV_LAST);
802*b30d1939SAndy Fiddaman 		if(nmatch)
803*b30d1939SAndy Fiddaman 			nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL|ARRAY_SETSUB);
804*b30d1939SAndy Fiddaman 		ap = nv_arrayptr(SH_MATCHNOD);
805*b30d1939SAndy Fiddaman 		ap->nelem = mp->nmatch = nmatch;
806*b30d1939SAndy Fiddaman 		mp->v = v;
807*b30d1939SAndy Fiddaman 		mp->first = match[0];
808*b30d1939SAndy Fiddaman 	}
809*b30d1939SAndy Fiddaman #ifdef SHOPT_2DMATCH
810*b30d1939SAndy Fiddaman 	else
811*b30d1939SAndy Fiddaman 	{
812*b30d1939SAndy Fiddaman 		if(index==1)
813*b30d1939SAndy Fiddaman 		{
814*b30d1939SAndy Fiddaman 			np->nvalue.cp = Empty;
815*b30d1939SAndy Fiddaman 			np->nvfun = SH_MATCHNOD->nvfun;
816*b30d1939SAndy Fiddaman 			nv_onattr(np,NV_NOFREE|NV_ARRAY);
817*b30d1939SAndy Fiddaman 			SH_MATCHNOD->nvfun = 0;
818*b30d1939SAndy Fiddaman 			for(i=0; i < mp->nmatch; i++)
819*b30d1939SAndy Fiddaman 			{
820*b30d1939SAndy Fiddaman 				nv_putsub(SH_MATCHNOD, (char*)0, i);
821*b30d1939SAndy Fiddaman 				nv_arraychild(SH_MATCHNOD, np,0);
822*b30d1939SAndy Fiddaman 			}
823*b30d1939SAndy Fiddaman 			if(ap = nv_arrayptr(SH_MATCHNOD))
824*b30d1939SAndy Fiddaman 				ap->nelem = mp->nmatch;
825*b30d1939SAndy Fiddaman 		}
826*b30d1939SAndy Fiddaman 		ap = nv_arrayptr(np);
827*b30d1939SAndy Fiddaman 		nv_putsub(np, NIL(char*), index|ARRAY_FILL|ARRAY_SETSUB);
828*b30d1939SAndy Fiddaman 	}
829*b30d1939SAndy Fiddaman #endif /* SHOPT_2DMATCH */
830*b30d1939SAndy Fiddaman 	shp->subshell = savesub;
831*b30d1939SAndy Fiddaman 	index *= 2*mp->nmatch;
832*b30d1939SAndy Fiddaman 	if(mp->nmatch)
833*b30d1939SAndy Fiddaman 	{
834*b30d1939SAndy Fiddaman 		for(n=mp->first+(mp->v-v),vsize=0,i=0; i < 2*nmatch; i++)
835*b30d1939SAndy Fiddaman 		{
836*b30d1939SAndy Fiddaman 			if(match[i]>=0 && (match[i] - n) > vsize)
837*b30d1939SAndy Fiddaman 				vsize = match[i] -n;
838*b30d1939SAndy Fiddaman 		}
839*b30d1939SAndy Fiddaman 		i = (index+2*mp->nmatch)*sizeof(match[0]);
840*b30d1939SAndy Fiddaman 		if((i+vsize) >= mp->vsize)
841da2e3ebdSchin 		{
842da2e3ebdSchin 			if(mp->vsize)
843*b30d1939SAndy Fiddaman 				mp->match = (int*)realloc(mp->match,i+vsize+1);
844da2e3ebdSchin 			else
845*b30d1939SAndy Fiddaman 				mp->match = (int*)malloc(i+vsize+1);
846*b30d1939SAndy Fiddaman 			mp->vsize = i+vsize+1;
847da2e3ebdSchin 		}
848*b30d1939SAndy Fiddaman 		mp->val =  ((char*)mp->match)+i;
849*b30d1939SAndy Fiddaman 		memcpy(mp->match+index,match,nmatch*2*sizeof(match[0]));
850*b30d1939SAndy Fiddaman 		for(x=0,i=0; i < 2*nmatch; i++)
851*b30d1939SAndy Fiddaman 		{
852*b30d1939SAndy Fiddaman 			if(match[i]>=0)
853*b30d1939SAndy Fiddaman 				mp->match[index+i] -= n;
854*b30d1939SAndy Fiddaman 			else
855*b30d1939SAndy Fiddaman 				x=1;
856*b30d1939SAndy Fiddaman 
857*b30d1939SAndy Fiddaman 		}
858*b30d1939SAndy Fiddaman 		ap->nelem -= x;
859*b30d1939SAndy Fiddaman 		while(i < 2*mp->nmatch)
860*b30d1939SAndy Fiddaman 			mp->match[index+i++] = -1;
861*b30d1939SAndy Fiddaman 		memcpy(mp->val,v+n,vsize);
862da2e3ebdSchin 		mp->val[vsize] = 0;
863*b30d1939SAndy Fiddaman 		mp->lastsub[0] = mp->lastsub[1] = -1;
864da2e3ebdSchin 	}
865da2e3ebdSchin }
866da2e3ebdSchin 
867da2e3ebdSchin #define array_scan(np)	((nv_arrayptr(np)->nelem&ARRAY_SCAN))
868da2e3ebdSchin 
get_match(register Namval_t * np,Namfun_t * fp)869da2e3ebdSchin static char* get_match(register Namval_t* np, Namfun_t *fp)
870da2e3ebdSchin {
871*b30d1939SAndy Fiddaman 	struct match	*mp = (struct match*)fp;
872*b30d1939SAndy Fiddaman 	int		sub,sub2=0,n,i =!mp->index;
873*b30d1939SAndy Fiddaman 	char		*val;
874*b30d1939SAndy Fiddaman 	sub = nv_aindex(SH_MATCHNOD);
875*b30d1939SAndy Fiddaman 	if(np!=SH_MATCHNOD)
876*b30d1939SAndy Fiddaman 		sub2 = nv_aindex(np);
877da2e3ebdSchin 	if(sub>=mp->nmatch)
878da2e3ebdSchin 		return(0);
879*b30d1939SAndy Fiddaman 	if(sub2>0)
880*b30d1939SAndy Fiddaman 		sub += sub2*mp->nmatch;
881*b30d1939SAndy Fiddaman 	if(sub==mp->lastsub[!i])
882*b30d1939SAndy Fiddaman 		return(mp->rval[!i]);
883*b30d1939SAndy Fiddaman 	else if(sub==mp->lastsub[i])
884*b30d1939SAndy Fiddaman 		return(mp->rval[i]);
885da2e3ebdSchin 	n = mp->match[2*sub+1]-mp->match[2*sub];
886da2e3ebdSchin 	if(n<=0)
887*b30d1939SAndy Fiddaman 		return(mp->match[2*sub]<0?Empty:"");
888da2e3ebdSchin 	val = mp->val+mp->match[2*sub];
889da2e3ebdSchin 	if(mp->val[mp->match[2*sub+1]]==0)
890da2e3ebdSchin 		return(val);
891*b30d1939SAndy Fiddaman 	mp->index = i;
892*b30d1939SAndy Fiddaman 	if(mp->rval[i])
893*b30d1939SAndy Fiddaman 	{
894*b30d1939SAndy Fiddaman 		free((void*)mp->rval[i]);
895*b30d1939SAndy Fiddaman 		mp->rval[i] = 0;
896*b30d1939SAndy Fiddaman 	}
897*b30d1939SAndy Fiddaman 	mp->rval[i] = (char*)malloc(n+1);
898*b30d1939SAndy Fiddaman 	mp->lastsub[i] = sub;
899*b30d1939SAndy Fiddaman 	memcpy(mp->rval[i],val,n);
900*b30d1939SAndy Fiddaman 	mp->rval[i][n] = 0;
901*b30d1939SAndy Fiddaman 	return(mp->rval[i]);
902da2e3ebdSchin }
903da2e3ebdSchin 
9047c2fbfb3SApril Chin static const Namdisc_t SH_MATCH_disc  = { sizeof(struct match), 0, get_match };
9057c2fbfb3SApril Chin 
get_version(register Namval_t * np,Namfun_t * fp)9067c2fbfb3SApril Chin static char* get_version(register Namval_t* np, Namfun_t *fp)
9077c2fbfb3SApril Chin {
9087c2fbfb3SApril Chin 	return(nv_getv(np,fp));
9097c2fbfb3SApril Chin }
9107c2fbfb3SApril Chin 
nget_version(register Namval_t * np,Namfun_t * fp)9117c2fbfb3SApril Chin static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp)
9127c2fbfb3SApril Chin {
9137c2fbfb3SApril Chin 	register const char	*cp = e_version + strlen(e_version)-10;
9147c2fbfb3SApril Chin 	register int		c;
9157c2fbfb3SApril Chin 	Sflong_t		t = 0;
9167c2fbfb3SApril Chin 	NOT_USED(fp);
9177c2fbfb3SApril Chin 
9187c2fbfb3SApril Chin 	while (c = *cp++)
9197c2fbfb3SApril Chin 		if (c >= '0' && c <= '9')
9207c2fbfb3SApril Chin 		{
9217c2fbfb3SApril Chin 			t *= 10;
9227c2fbfb3SApril Chin 			t += c - '0';
9237c2fbfb3SApril Chin 		}
9247c2fbfb3SApril Chin 	return((Sfdouble_t)t);
9257c2fbfb3SApril Chin }
9267c2fbfb3SApril Chin 
9277c2fbfb3SApril Chin static const Namdisc_t SH_VERSION_disc	= {  0, 0, get_version, nget_version };
928da2e3ebdSchin 
929da2e3ebdSchin #if SHOPT_FS_3D
930da2e3ebdSchin     /*
931da2e3ebdSchin      * set or unset the mappings given a colon separated list of directories
932da2e3ebdSchin      */
vpath_set(char * str,int mode)933da2e3ebdSchin     static void vpath_set(char *str, int mode)
934da2e3ebdSchin     {
935da2e3ebdSchin 	register char *lastp, *oldp=str, *newp=strchr(oldp,':');
936*b30d1939SAndy Fiddaman 	if(!shgd->lim.fs3d)
937da2e3ebdSchin 		return;
938da2e3ebdSchin 	while(newp)
939da2e3ebdSchin 	{
940da2e3ebdSchin 		*newp++ = 0;
941da2e3ebdSchin 		if(lastp=strchr(newp,':'))
942da2e3ebdSchin 			*lastp = 0;
943da2e3ebdSchin 		mount((mode?newp:""),oldp,FS3D_VIEW,0);
944da2e3ebdSchin 		newp[-1] = ':';
945da2e3ebdSchin 		oldp = newp;
946da2e3ebdSchin 		newp=lastp;
947da2e3ebdSchin 	}
948da2e3ebdSchin     }
949da2e3ebdSchin 
950da2e3ebdSchin     /* catch vpath assignments */
put_vpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)951da2e3ebdSchin     static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
952da2e3ebdSchin     {
953da2e3ebdSchin 	register char *cp;
954da2e3ebdSchin 	if(cp = nv_getval(np))
955da2e3ebdSchin 		vpath_set(cp,0);
956da2e3ebdSchin 	if(val)
957da2e3ebdSchin 		vpath_set((char*)val,1);
958da2e3ebdSchin 	nv_putv(np,val,flags,fp);
959da2e3ebdSchin     }
960da2e3ebdSchin     static const Namdisc_t VPATH_disc	= { 0, put_vpath  };
961da2e3ebdSchin     static Namfun_t VPATH_init	= { &VPATH_disc, 1  };
962da2e3ebdSchin #endif /* SHOPT_FS_3D */
963da2e3ebdSchin 
964da2e3ebdSchin 
965da2e3ebdSchin static const Namdisc_t IFS_disc		= {  sizeof(struct ifs), put_ifs, get_ifs };
9667c2fbfb3SApril Chin const Namdisc_t RESTRICTED_disc	= {  sizeof(Namfun_t), put_restricted };
9677c2fbfb3SApril Chin static const Namdisc_t CDPATH_disc	= {  sizeof(Namfun_t), put_cdpath };
9687c2fbfb3SApril Chin static const Namdisc_t EDITOR_disc	= {  sizeof(Namfun_t), put_ed };
9697c2fbfb3SApril Chin static const Namdisc_t HISTFILE_disc	= {  sizeof(Namfun_t), put_history };
9707c2fbfb3SApril Chin static const Namdisc_t OPTINDEX_disc	= {  sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
971da2e3ebdSchin static const Namdisc_t SECONDS_disc	= {  sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
972da2e3ebdSchin static const Namdisc_t RAND_disc	= {  sizeof(struct rand), put_rand, get_rand, nget_rand };
9737c2fbfb3SApril Chin static const Namdisc_t LINENO_disc	= {  sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno };
9747c2fbfb3SApril Chin static const Namdisc_t L_ARG_disc	= {  sizeof(Namfun_t), put_lastarg, get_lastarg };
975da2e3ebdSchin 
976*b30d1939SAndy Fiddaman 
977*b30d1939SAndy Fiddaman #define MAX_MATH_ARGS	3
978*b30d1939SAndy Fiddaman 
name_math(Namval_t * np,Namfun_t * fp)979*b30d1939SAndy Fiddaman static char *name_math(Namval_t *np, Namfun_t *fp)
980*b30d1939SAndy Fiddaman {
981*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
982*b30d1939SAndy Fiddaman 	sfprintf(shp->strbuf,".sh.math.%s",np->nvname);
983*b30d1939SAndy Fiddaman 	return(sfstruse(shp->strbuf));
984*b30d1939SAndy Fiddaman }
985*b30d1939SAndy Fiddaman 
986*b30d1939SAndy Fiddaman static const Namdisc_t	math_child_disc =
987*b30d1939SAndy Fiddaman {
988*b30d1939SAndy Fiddaman 	0,0,0,0,0,0,0,
989*b30d1939SAndy Fiddaman 	name_math
990*b30d1939SAndy Fiddaman };
991*b30d1939SAndy Fiddaman 
992*b30d1939SAndy Fiddaman static Namfun_t	 math_child_fun =
993*b30d1939SAndy Fiddaman {
994*b30d1939SAndy Fiddaman 	&math_child_disc, 1, 0, sizeof(Namfun_t)
995*b30d1939SAndy Fiddaman };
996*b30d1939SAndy Fiddaman 
math_init(Shell_t * shp)997*b30d1939SAndy Fiddaman static void math_init(Shell_t *shp)
998*b30d1939SAndy Fiddaman {
999*b30d1939SAndy Fiddaman 	Namval_t	*np;
1000*b30d1939SAndy Fiddaman 	char		*name;
1001*b30d1939SAndy Fiddaman 	int		i;
1002*b30d1939SAndy Fiddaman 	shp->mathnodes = (char*)calloc(1,MAX_MATH_ARGS*(NV_MINSZ+5));
1003*b30d1939SAndy Fiddaman 	name = shp->mathnodes+MAX_MATH_ARGS*NV_MINSZ;
1004*b30d1939SAndy Fiddaman 	for(i=0; i < MAX_MATH_ARGS; i++)
1005*b30d1939SAndy Fiddaman 	{
1006*b30d1939SAndy Fiddaman 		np = nv_namptr(shp->mathnodes,i);
1007*b30d1939SAndy Fiddaman 		np->nvfun = &math_child_fun;
1008*b30d1939SAndy Fiddaman 		memcpy(name,"arg",3);
1009*b30d1939SAndy Fiddaman 		name[3] = '1'+i;
1010*b30d1939SAndy Fiddaman 		np->nvname = name;
1011*b30d1939SAndy Fiddaman 		name+=5;
1012*b30d1939SAndy Fiddaman 		nv_onattr(np,NV_MINIMAL|NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
1013*b30d1939SAndy Fiddaman 	}
1014*b30d1939SAndy Fiddaman }
1015*b30d1939SAndy Fiddaman 
create_math(Namval_t * np,const char * name,int flag,Namfun_t * fp)1016*b30d1939SAndy Fiddaman static Namval_t *create_math(Namval_t *np,const char *name,int flag,Namfun_t *fp)
1017*b30d1939SAndy Fiddaman {
1018*b30d1939SAndy Fiddaman 	Shell_t		*shp = nv_shell(np);
1019*b30d1939SAndy Fiddaman 	if(!name)
1020*b30d1939SAndy Fiddaman 		return(SH_MATHNOD);
1021*b30d1939SAndy Fiddaman 	if(name[0]!='a' || name[1]!='r' || name[2]!='g' || name[4] || !isdigit(name[3]) || (name[3]=='0' || (name[3]-'0')>MAX_MATH_ARGS))
1022*b30d1939SAndy Fiddaman 		return(0);
1023*b30d1939SAndy Fiddaman 	fp->last = (char*)&name[4];
1024*b30d1939SAndy Fiddaman 	return(nv_namptr(shp->mathnodes,name[3]-'1'));
1025*b30d1939SAndy Fiddaman }
1026*b30d1939SAndy Fiddaman 
get_math(register Namval_t * np,Namfun_t * fp)1027*b30d1939SAndy Fiddaman static char* get_math(register Namval_t* np, Namfun_t *fp)
1028*b30d1939SAndy Fiddaman {
1029*b30d1939SAndy Fiddaman 	Shell_t		*shp = nv_shell(np);
1030*b30d1939SAndy Fiddaman 	Namval_t	*mp,fake;
1031*b30d1939SAndy Fiddaman 	char		*val;
1032*b30d1939SAndy Fiddaman 	int		first=0;
1033*b30d1939SAndy Fiddaman 	fake.nvname = ".sh.math.";
1034*b30d1939SAndy Fiddaman 	mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
1035*b30d1939SAndy Fiddaman 	while(mp=(Namval_t*)dtnext(shp->fun_tree,mp))
1036*b30d1939SAndy Fiddaman 	{
1037*b30d1939SAndy Fiddaman 		if(memcmp(mp->nvname,".sh.math.",9))
1038*b30d1939SAndy Fiddaman 			break;
1039*b30d1939SAndy Fiddaman 		if(first++)
1040*b30d1939SAndy Fiddaman 			sfputc(shp->strbuf,' ');
1041*b30d1939SAndy Fiddaman 		sfputr(shp->strbuf,mp->nvname+9,-1);
1042*b30d1939SAndy Fiddaman 	}
1043*b30d1939SAndy Fiddaman 	val = sfstruse(shp->strbuf);
1044*b30d1939SAndy Fiddaman 	return(val);
1045*b30d1939SAndy Fiddaman 
1046*b30d1939SAndy Fiddaman }
1047*b30d1939SAndy Fiddaman 
setdisc_any(Namval_t * np,const char * event,Namval_t * action,Namfun_t * fp)1048*b30d1939SAndy Fiddaman static char *setdisc_any(Namval_t *np, const char *event, Namval_t *action, Namfun_t *fp)
1049*b30d1939SAndy Fiddaman {
1050*b30d1939SAndy Fiddaman 	Shell_t		*shp=nv_shell(np);
1051*b30d1939SAndy Fiddaman 	Namval_t	*mp,fake;
1052*b30d1939SAndy Fiddaman 	char		*name;
1053*b30d1939SAndy Fiddaman 	int		getname=0, off=staktell();
1054*b30d1939SAndy Fiddaman 	fake.nvname = nv_name(np);
1055*b30d1939SAndy Fiddaman 	if(!event)
1056*b30d1939SAndy Fiddaman 	{
1057*b30d1939SAndy Fiddaman 		if(!action)
1058*b30d1939SAndy Fiddaman 		{
1059*b30d1939SAndy Fiddaman 			mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
1060*b30d1939SAndy Fiddaman 			return((char*)dtnext(shp->fun_tree,mp));
1061*b30d1939SAndy Fiddaman 		}
1062*b30d1939SAndy Fiddaman 		getname = 1;
1063*b30d1939SAndy Fiddaman 	}
1064*b30d1939SAndy Fiddaman 	stakputs(fake.nvname);
1065*b30d1939SAndy Fiddaman 	stakputc('.');
1066*b30d1939SAndy Fiddaman 	stakputs(event);
1067*b30d1939SAndy Fiddaman 	stakputc(0);
1068*b30d1939SAndy Fiddaman 	name  = stakptr(off);
1069*b30d1939SAndy Fiddaman 	mp = nv_search(name, shp->fun_tree, action?NV_ADD:0);
1070*b30d1939SAndy Fiddaman 	stakseek(off);
1071*b30d1939SAndy Fiddaman 	if(getname)
1072*b30d1939SAndy Fiddaman 		return(mp?(char*)dtnext(shp->fun_tree,mp):0);
1073*b30d1939SAndy Fiddaman 	if(action==np)
1074*b30d1939SAndy Fiddaman 		action = mp;
1075*b30d1939SAndy Fiddaman 	return(action?(char*)action:"");
1076*b30d1939SAndy Fiddaman }
1077*b30d1939SAndy Fiddaman 
1078*b30d1939SAndy Fiddaman static const Namdisc_t SH_MATH_disc  = { 0, 0, get_math, 0, setdisc_any, create_math, };
1079*b30d1939SAndy Fiddaman 
1080*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1081*b30d1939SAndy Fiddaman static const Namdisc_t SH_JOBPOOL_disc  = { 0, 0, 0, 0, setdisc_any, 0, };
1082*b30d1939SAndy Fiddaman #endif /*  SHOPT_COSHELL */
1083*b30d1939SAndy Fiddaman 
1084da2e3ebdSchin #if SHOPT_NAMESPACE
get_nspace(Namval_t * np,Namfun_t * fp)1085da2e3ebdSchin     static char* get_nspace(Namval_t* np, Namfun_t *fp)
1086da2e3ebdSchin     {
1087da2e3ebdSchin 	if(sh.namespace)
1088da2e3ebdSchin 		return(nv_name(sh.namespace));
1089da2e3ebdSchin 	return((char*)np->nvalue.cp);
1090da2e3ebdSchin     }
1091da2e3ebdSchin     static const Namdisc_t NSPACE_disc	= {  0, 0, get_nspace };
1092da2e3ebdSchin     static Namfun_t NSPACE_init	= {  &NSPACE_disc, 1};
1093da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
1094da2e3ebdSchin 
1095da2e3ebdSchin #ifdef _hdr_locale
10967c2fbfb3SApril Chin     static const Namdisc_t LC_disc	= {  sizeof(Namfun_t), put_lang };
1097da2e3ebdSchin #endif /* _hdr_locale */
1098da2e3ebdSchin 
1099da2e3ebdSchin /*
1100da2e3ebdSchin  * This function will get called whenever a configuration parameter changes
1101da2e3ebdSchin  */
newconf(const char * name,const char * path,const char * value)1102da2e3ebdSchin static int newconf(const char *name, const char *path, const char *value)
1103da2e3ebdSchin {
1104*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1105da2e3ebdSchin 	register char *arg;
1106da2e3ebdSchin 	if(!name)
1107da2e3ebdSchin 		setenviron(value);
1108da2e3ebdSchin 	else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value))
1109da2e3ebdSchin 	{
1110*b30d1939SAndy Fiddaman 		shp->universe = 0;
1111da2e3ebdSchin 		/* set directory in new universe */
1112*b30d1939SAndy Fiddaman 		if(*(arg = path_pwd(shp,0))=='/')
1113da2e3ebdSchin 			chdir(arg);
1114da2e3ebdSchin 		/* clear out old tracked alias */
1115da2e3ebdSchin 		stakseek(0);
1116da2e3ebdSchin 		stakputs(nv_getval(PATHNOD));
1117da2e3ebdSchin 		stakputc(0);
1118da2e3ebdSchin 		nv_putval(PATHNOD,stakseek(0),NV_RDONLY);
1119da2e3ebdSchin 	}
1120da2e3ebdSchin 	return(1);
1121da2e3ebdSchin }
1122da2e3ebdSchin 
1123da2e3ebdSchin #if	(CC_NATIVE != CC_ASCII)
a2e(char * d,const char * s)1124da2e3ebdSchin     static void a2e(char *d, const char *s)
1125da2e3ebdSchin     {
1126da2e3ebdSchin 	register const unsigned char *t;
1127da2e3ebdSchin 	register int i;
1128da2e3ebdSchin 	t = CCMAP(CC_ASCII, CC_NATIVE);
1129da2e3ebdSchin 	for(i=0; i<(1<<CHAR_BIT); i++)
1130da2e3ebdSchin 		d[t[i]] = s[i];
1131da2e3ebdSchin     }
1132da2e3ebdSchin 
init_ebcdic(void)1133da2e3ebdSchin     static void init_ebcdic(void)
1134da2e3ebdSchin     {
1135da2e3ebdSchin 	int i;
1136da2e3ebdSchin 	char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT));
1137da2e3ebdSchin 	for(i=0; i < ST_NONE; i++)
1138da2e3ebdSchin 	{
1139da2e3ebdSchin 		a2e(cp,sh_lexrstates[i]);
1140da2e3ebdSchin 		sh_lexstates[i] = cp;
1141da2e3ebdSchin 		cp += (1<<CHAR_BIT);
1142da2e3ebdSchin 	}
1143da2e3ebdSchin     }
1144da2e3ebdSchin #endif
1145da2e3ebdSchin 
1146da2e3ebdSchin /*
1147da2e3ebdSchin  * return SH_TYPE_* bitmask for path
1148da2e3ebdSchin  * 0 for "not a shell"
1149da2e3ebdSchin  */
sh_type(register const char * path)1150da2e3ebdSchin int sh_type(register const char *path)
1151da2e3ebdSchin {
1152da2e3ebdSchin 	register const char*	s;
1153da2e3ebdSchin 	register int		t = 0;
1154da2e3ebdSchin 
1155da2e3ebdSchin 	if (s = (const char*)strrchr(path, '/'))
1156da2e3ebdSchin 	{
1157da2e3ebdSchin 		if (*path == '-')
1158da2e3ebdSchin 			t |= SH_TYPE_LOGIN;
1159da2e3ebdSchin 		s++;
1160da2e3ebdSchin 	}
1161da2e3ebdSchin 	else
1162da2e3ebdSchin 		s = path;
1163da2e3ebdSchin 	if (*s == '-')
1164da2e3ebdSchin 	{
1165da2e3ebdSchin 		s++;
1166da2e3ebdSchin 		t |= SH_TYPE_LOGIN;
1167da2e3ebdSchin 	}
1168da2e3ebdSchin 	for (;;)
1169da2e3ebdSchin 	{
1170da2e3ebdSchin 		if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
1171da2e3ebdSchin 		{
1172da2e3ebdSchin 			if (*s == 'k')
1173da2e3ebdSchin 			{
1174da2e3ebdSchin 				s++;
1175da2e3ebdSchin 				t |= SH_TYPE_KSH;
1176da2e3ebdSchin 				continue;
1177da2e3ebdSchin 			}
1178da2e3ebdSchin #if SHOPT_BASH
1179da2e3ebdSchin 			if (*s == 'b' && *(s+1) == 'a')
1180da2e3ebdSchin 			{
1181da2e3ebdSchin 				s += 2;
1182da2e3ebdSchin 				t |= SH_TYPE_BASH;
1183da2e3ebdSchin 				continue;
1184da2e3ebdSchin 			}
1185da2e3ebdSchin #endif
1186da2e3ebdSchin 		}
1187da2e3ebdSchin 		if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
1188da2e3ebdSchin 		{
1189da2e3ebdSchin #if SHOPT_PFSH
1190da2e3ebdSchin 			if (*s == 'p' && *(s+1) == 'f')
1191da2e3ebdSchin 			{
1192da2e3ebdSchin 				s += 2;
1193da2e3ebdSchin 				t |= SH_TYPE_PROFILE;
1194da2e3ebdSchin 				continue;
1195da2e3ebdSchin 			}
1196da2e3ebdSchin #endif
1197da2e3ebdSchin 			if (*s == 'r')
1198da2e3ebdSchin 			{
1199da2e3ebdSchin 				s++;
1200da2e3ebdSchin 				t |= SH_TYPE_RESTRICTED;
1201da2e3ebdSchin 				continue;
1202da2e3ebdSchin 			}
1203da2e3ebdSchin 		}
1204da2e3ebdSchin 		break;
1205da2e3ebdSchin 	}
12067c2fbfb3SApril Chin 	if (*s++ == 's' && (*s == 'h' || *s == 'u'))
12077c2fbfb3SApril Chin 	{
12087c2fbfb3SApril Chin 		s++;
12097c2fbfb3SApril Chin 		t |= SH_TYPE_SH;
12107c2fbfb3SApril Chin 		if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
12117c2fbfb3SApril Chin 			s += 2;
1212da2e3ebdSchin #if _WINIX
12137c2fbfb3SApril Chin 		if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e')
12147c2fbfb3SApril Chin 			s += 4;
1215da2e3ebdSchin #endif
12167c2fbfb3SApril Chin 		if (!isalnum(*s))
12177c2fbfb3SApril Chin 			return t;
12187c2fbfb3SApril Chin 	}
12197c2fbfb3SApril Chin 	return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
12207c2fbfb3SApril Chin }
12217c2fbfb3SApril Chin 
12227c2fbfb3SApril Chin 
get_mode(Namval_t * np,Namfun_t * nfp)12237c2fbfb3SApril Chin static char *get_mode(Namval_t* np, Namfun_t* nfp)
12247c2fbfb3SApril Chin {
12257c2fbfb3SApril Chin 	mode_t mode = nv_getn(np,nfp);
12267c2fbfb3SApril Chin 	return(fmtperm(mode));
12277c2fbfb3SApril Chin }
12287c2fbfb3SApril Chin 
put_mode(Namval_t * np,const char * val,int flag,Namfun_t * nfp)12297c2fbfb3SApril Chin static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
12307c2fbfb3SApril Chin {
12317c2fbfb3SApril Chin 	if(val)
12327c2fbfb3SApril Chin 	{
12337c2fbfb3SApril Chin 		mode_t mode;
1234*b30d1939SAndy Fiddaman 		char *last=0;
12357c2fbfb3SApril Chin 		if(flag&NV_INTEGER)
12367c2fbfb3SApril Chin 		{
12377c2fbfb3SApril Chin 			if(flag&NV_LONG)
12387c2fbfb3SApril Chin 				mode = *(Sfdouble_t*)val;
12397c2fbfb3SApril Chin 			else
12407c2fbfb3SApril Chin 				mode = *(double*)val;
12417c2fbfb3SApril Chin 		}
12427c2fbfb3SApril Chin 		else
12437c2fbfb3SApril Chin 			mode = strperm(val, &last,0);
12447c2fbfb3SApril Chin 		if(*last)
12457c2fbfb3SApril Chin 			errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
12467c2fbfb3SApril Chin 		nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
12477c2fbfb3SApril Chin 	}
12487c2fbfb3SApril Chin 	else
12497c2fbfb3SApril Chin 		nv_putv(np,val,flag,nfp);
1250da2e3ebdSchin }
1251da2e3ebdSchin 
12527c2fbfb3SApril Chin static const Namdisc_t modedisc =
12537c2fbfb3SApril Chin {
12547c2fbfb3SApril Chin 	0,
12557c2fbfb3SApril Chin         put_mode,
12567c2fbfb3SApril Chin         get_mode,
12577c2fbfb3SApril Chin };
12587c2fbfb3SApril Chin 
12597c2fbfb3SApril Chin 
1260da2e3ebdSchin /*
1261da2e3ebdSchin  * initialize the shell
1262da2e3ebdSchin  */
sh_init(register int argc,register char * argv[],Shinit_f userinit)12637c2fbfb3SApril Chin Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
1264da2e3ebdSchin {
1265*b30d1939SAndy Fiddaman 	static int beenhere;
1266*b30d1939SAndy Fiddaman 	Shell_t	*shp;
1267da2e3ebdSchin 	register int n;
1268da2e3ebdSchin 	int type;
1269da2e3ebdSchin 	static char *login_files[3];
127034f9b3eeSRoland Mainz 	memfatal();
1271da2e3ebdSchin 	n = strlen(e_version);
1272da2e3ebdSchin 	if(e_version[n-1]=='$' && e_version[n-2]==' ')
1273da2e3ebdSchin 		e_version[n-2]=0;
1274da2e3ebdSchin #if	(CC_NATIVE == CC_ASCII)
1275da2e3ebdSchin 	memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*));
1276da2e3ebdSchin #else
1277da2e3ebdSchin 	init_ebcdic();
1278da2e3ebdSchin #endif
1279*b30d1939SAndy Fiddaman 	if(!beenhere)
1280*b30d1939SAndy Fiddaman 	{
1281*b30d1939SAndy Fiddaman 		beenhere = 1;
1282*b30d1939SAndy Fiddaman 		shp = &sh;
1283*b30d1939SAndy Fiddaman 		shgd = newof(0,struct shared,1,0);
1284*b30d1939SAndy Fiddaman 		shgd->pid = getpid();
1285*b30d1939SAndy Fiddaman 		shgd->ppid = getppid();
1286*b30d1939SAndy Fiddaman 		shgd->userid=getuid();
1287*b30d1939SAndy Fiddaman 		shgd->euserid=geteuid();
1288*b30d1939SAndy Fiddaman 		shgd->groupid=getgid();
1289*b30d1939SAndy Fiddaman 		shgd->egroupid=getegid();
1290*b30d1939SAndy Fiddaman 		shgd->lim.clk_tck = getconf("CLK_TCK");
1291*b30d1939SAndy Fiddaman 		shgd->lim.arg_max = getconf("ARG_MAX");
1292*b30d1939SAndy Fiddaman 		shgd->lim.child_max = getconf("CHILD_MAX");
1293*b30d1939SAndy Fiddaman 		shgd->lim.ngroups_max = getconf("NGROUPS_MAX");
1294*b30d1939SAndy Fiddaman 		shgd->lim.posix_version = getconf("VERSION");
1295*b30d1939SAndy Fiddaman 		shgd->lim.posix_jobcontrol = getconf("JOB_CONTROL");
1296*b30d1939SAndy Fiddaman 		if(shgd->lim.arg_max <=0)
1297*b30d1939SAndy Fiddaman 			shgd->lim.arg_max = ARG_MAX;
1298*b30d1939SAndy Fiddaman 		if(shgd->lim.child_max <=0)
1299*b30d1939SAndy Fiddaman 			shgd->lim.child_max = CHILD_MAX;
1300*b30d1939SAndy Fiddaman 		if(shgd->lim.clk_tck <=0)
1301*b30d1939SAndy Fiddaman 			shgd->lim.clk_tck = CLK_TCK;
1302*b30d1939SAndy Fiddaman #if SHOPT_FS_3D
1303*b30d1939SAndy Fiddaman 		if(fs3d(FS3D_TEST))
1304*b30d1939SAndy Fiddaman 			shgd->lim.fs3d = 1;
1305*b30d1939SAndy Fiddaman #endif /* SHOPT_FS_3D */
1306*b30d1939SAndy Fiddaman 		shgd->ed_context = (void*)ed_open(shp);
1307*b30d1939SAndy Fiddaman 		error_info.exit = sh_exit;
1308*b30d1939SAndy Fiddaman 		error_info.id = path_basename(argv[0]);
1309*b30d1939SAndy Fiddaman 	}
1310*b30d1939SAndy Fiddaman 	else
1311*b30d1939SAndy Fiddaman 		shp = newof(0,Shell_t,1,0);
13127c2fbfb3SApril Chin 	umask(shp->mask=umask(0));
1313*b30d1939SAndy Fiddaman 	shp->gd = shgd;
13147c2fbfb3SApril Chin 	shp->mac_context = sh_macopen(shp);
13157c2fbfb3SApril Chin 	shp->arg_context = sh_argopen(shp);
13167c2fbfb3SApril Chin 	shp->lex_context = (void*)sh_lexopen(0,shp,1);
13177c2fbfb3SApril Chin 	shp->strbuf = sfstropen();
13187c2fbfb3SApril Chin 	shp->stk = stkstd;
13197c2fbfb3SApril Chin 	sfsetbuf(shp->strbuf,(char*)0,64);
1320da2e3ebdSchin 	sh_onstate(SH_INIT);
1321da2e3ebdSchin #if ERROR_VERSION >= 20000102L
1322da2e3ebdSchin 	error_info.catalog = e_dict;
132334f9b3eeSRoland Mainz #endif
132434f9b3eeSRoland Mainz #if SHOPT_REGRESS
132534f9b3eeSRoland Mainz 	{
132634f9b3eeSRoland Mainz 		Opt_t*	nopt;
132734f9b3eeSRoland Mainz 		Opt_t*	oopt;
132834f9b3eeSRoland Mainz 		char*	a;
132934f9b3eeSRoland Mainz 		char**	av = argv;
133034f9b3eeSRoland Mainz 		char*	regress[3];
133134f9b3eeSRoland Mainz 
133234f9b3eeSRoland Mainz 		sh_regress_init(shp);
133334f9b3eeSRoland Mainz 		regress[0] = "__regress__";
133434f9b3eeSRoland Mainz 		regress[2] = 0;
133534f9b3eeSRoland Mainz 		/* NOTE: only shp is used by __regress__ at this point */
133634f9b3eeSRoland Mainz 		shp->bltindata.shp = shp;
133734f9b3eeSRoland Mainz 		while ((a = *++av) && a[0] == '-' && (a[1] == 'I' || a[1] == '-' && a[2] == 'r'))
133834f9b3eeSRoland Mainz 		{
133934f9b3eeSRoland Mainz 			if (a[1] == 'I')
134034f9b3eeSRoland Mainz 			{
134134f9b3eeSRoland Mainz 				if (a[2])
134234f9b3eeSRoland Mainz 					regress[1] = a + 2;
134334f9b3eeSRoland Mainz 				else if (!(regress[1] = *++av))
134434f9b3eeSRoland Mainz 					break;
134534f9b3eeSRoland Mainz 			}
134634f9b3eeSRoland Mainz 			else if (strncmp(a+2, "regress", 7))
134734f9b3eeSRoland Mainz 				break;
134834f9b3eeSRoland Mainz 			else if (a[9] == '=')
134934f9b3eeSRoland Mainz 				regress[1] = a + 10;
135034f9b3eeSRoland Mainz 			else if (!(regress[1] = *++av))
135134f9b3eeSRoland Mainz 				break;
135234f9b3eeSRoland Mainz 			nopt = optctx(0, 0);
135334f9b3eeSRoland Mainz 			oopt = optctx(nopt, 0);
135434f9b3eeSRoland Mainz 			b___regress__(2, regress, &shp->bltindata);
135534f9b3eeSRoland Mainz 			optctx(oopt, nopt);
135634f9b3eeSRoland Mainz 		}
135734f9b3eeSRoland Mainz 	}
1358da2e3ebdSchin #endif
13597c2fbfb3SApril Chin 	shp->cpipe[0] = -1;
13607c2fbfb3SApril Chin 	shp->coutpipe = -1;
1361da2e3ebdSchin 	for(n=0;n < 10; n++)
1362da2e3ebdSchin 	{
1363da2e3ebdSchin 		/* don't use lower bits when rand() generates large numbers */
1364da2e3ebdSchin 		if(rand() > RANDMASK)
1365da2e3ebdSchin 		{
1366da2e3ebdSchin 			rand_shift = 3;
1367da2e3ebdSchin 			break;
1368da2e3ebdSchin 		}
1369da2e3ebdSchin 	}
13707c2fbfb3SApril Chin 	sh_ioinit(shp);
1371da2e3ebdSchin 	/* initialize signal handling */
13727c2fbfb3SApril Chin 	sh_siginit(shp);
1373da2e3ebdSchin 	stakinstall(NIL(Stak_t*),nospace);
1374da2e3ebdSchin 	/* set up memory for name-value pairs */
13757c2fbfb3SApril Chin 	shp->init_context =  nv_init(shp);
1376da2e3ebdSchin 	/* read the environment */
1377da2e3ebdSchin 	if(argc>0)
1378da2e3ebdSchin 	{
1379da2e3ebdSchin 		type = sh_type(*argv);
1380da2e3ebdSchin 		if(type&SH_TYPE_LOGIN)
13817c2fbfb3SApril Chin 			shp->login_sh = 2;
1382da2e3ebdSchin 	}
13837c2fbfb3SApril Chin 	env_init(shp);
138434f9b3eeSRoland Mainz 	if(!ENVNOD->nvalue.cp)
138534f9b3eeSRoland Mainz 	{
138634f9b3eeSRoland Mainz 		sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME));
138734f9b3eeSRoland Mainz 		nv_putval(ENVNOD,sfstruse(shp->strbuf),NV_RDONLY);
138834f9b3eeSRoland Mainz 	}
13897c2fbfb3SApril Chin 	*SHLVL->nvalue.ip +=1;
1390*b30d1939SAndy Fiddaman 	nv_offattr(SHLVL,NV_IMPORT);
1391da2e3ebdSchin #if SHOPT_SPAWN
1392da2e3ebdSchin 	{
1393da2e3ebdSchin 		/*
1394da2e3ebdSchin 		 * try to find the pathname for this interpreter
1395da2e3ebdSchin 		 * try using environment variable _ or argv[0]
1396da2e3ebdSchin 		 */
139734f9b3eeSRoland Mainz 		char *cp=nv_getval(L_ARGNOD);
1398da2e3ebdSchin 		char buff[PATH_MAX+1];
1399*b30d1939SAndy Fiddaman 		shp->gd->shpath = 0;
140034f9b3eeSRoland Mainz #if _AST_VERSION >= 20090202L
140134f9b3eeSRoland Mainz 		if((n = pathprog(NiL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
1402*b30d1939SAndy Fiddaman 			shp->gd->shpath = strdup(buff);
140334f9b3eeSRoland Mainz #else
14047c2fbfb3SApril Chin 		sfprintf(shp->strbuf,"/proc/%d/exe",getpid());
14057c2fbfb3SApril Chin 		if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0)
1406da2e3ebdSchin 		{
1407da2e3ebdSchin 			buff[n] = 0;
1408*b30d1939SAndy Fiddaman 			shp->gd->shpath = strdup(buff);
1409da2e3ebdSchin 		}
141034f9b3eeSRoland Mainz #endif
1411da2e3ebdSchin 		else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
1412da2e3ebdSchin 		{
1413da2e3ebdSchin 			if(*cp=='/')
1414*b30d1939SAndy Fiddaman 				shp->gd->shpath = strdup(cp);
1415da2e3ebdSchin 			else if(cp = nv_getval(PWDNOD))
1416da2e3ebdSchin 			{
1417da2e3ebdSchin 				int offset = staktell();
1418da2e3ebdSchin 				stakputs(cp);
1419da2e3ebdSchin 				stakputc('/');
1420da2e3ebdSchin 				stakputs(argv[0]);
1421da2e3ebdSchin 				pathcanon(stakptr(offset),PATH_DOTDOT);
1422*b30d1939SAndy Fiddaman 				shp->gd->shpath = strdup(stakptr(offset));
1423da2e3ebdSchin 				stakseek(offset);
1424da2e3ebdSchin 			}
1425da2e3ebdSchin 		}
1426da2e3ebdSchin 	}
1427da2e3ebdSchin #endif
1428da2e3ebdSchin 	nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
1429da2e3ebdSchin #if SHOPT_FS_3D
1430da2e3ebdSchin 	nv_stack(VPATHNOD, &VPATH_init);
1431da2e3ebdSchin #endif /* SHOPT_FS_3D */
1432da2e3ebdSchin 	astconfdisc(newconf);
1433da2e3ebdSchin #if SHOPT_TIMEOUT
14347c2fbfb3SApril Chin 	shp->st.tmout = SHOPT_TIMEOUT;
1435da2e3ebdSchin #endif /* SHOPT_TIMEOUT */
1436da2e3ebdSchin 	/* initialize jobs table */
1437da2e3ebdSchin 	job_clear();
1438*b30d1939SAndy Fiddaman 	sh_onoption(SH_MULTILINE);
1439da2e3ebdSchin 	if(argc>0)
1440da2e3ebdSchin 	{
1441*b30d1939SAndy Fiddaman 		int dolv_index = -1;
1442da2e3ebdSchin 		/* check for restricted shell */
1443da2e3ebdSchin 		if(type&SH_TYPE_RESTRICTED)
1444da2e3ebdSchin 			sh_onoption(SH_RESTRICTED);
1445da2e3ebdSchin #if SHOPT_PFSH
1446da2e3ebdSchin 		/* check for profile shell */
1447da2e3ebdSchin 		else if(type&SH_TYPE_PROFILE)
1448da2e3ebdSchin 			sh_onoption(SH_PFSH);
1449da2e3ebdSchin #endif
1450da2e3ebdSchin #if SHOPT_BASH
1451da2e3ebdSchin 		/* check for invocation as bash */
1452da2e3ebdSchin 		if(type&SH_TYPE_BASH)
1453da2e3ebdSchin 		{
1454*b30d1939SAndy Fiddaman 		        shp>userinit = userinit = bash_init;
1455da2e3ebdSchin 			sh_onoption(SH_BASH);
1456da2e3ebdSchin 			sh_onstate(SH_PREINIT);
14577c2fbfb3SApril Chin 			(*userinit)(shp, 0);
1458da2e3ebdSchin 			sh_offstate(SH_PREINIT);
1459da2e3ebdSchin 		}
1460da2e3ebdSchin #endif
1461da2e3ebdSchin 		/* look for options */
14627c2fbfb3SApril Chin 		/* shp->st.dolc is $#	*/
14637c2fbfb3SApril Chin 		if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0)
1464da2e3ebdSchin 		{
14657c2fbfb3SApril Chin 			shp->exitval = 2;
14667c2fbfb3SApril Chin 			sh_done(shp,0);
1467da2e3ebdSchin 		}
1468da2e3ebdSchin 		opt_info.disc = 0;
1469*b30d1939SAndy Fiddaman 		dolv_index = (argc-1)-shp->st.dolc;
1470*b30d1939SAndy Fiddaman 		shp->st.dolv=argv+dolv_index;
1471*b30d1939SAndy Fiddaman 		shp->st.repl_index = dolv_index;
1472*b30d1939SAndy Fiddaman 		shp->st.repl_arg = argv[dolv_index];
14737c2fbfb3SApril Chin 		shp->st.dolv[0] = argv[0];
14747c2fbfb3SApril Chin 		if(shp->st.dolc < 1)
1475da2e3ebdSchin 			sh_onoption(SH_SFLAG);
1476da2e3ebdSchin 		if(!sh_isoption(SH_SFLAG))
1477da2e3ebdSchin 		{
14787c2fbfb3SApril Chin 			shp->st.dolc--;
14797c2fbfb3SApril Chin 			shp->st.dolv++;
1480da2e3ebdSchin #if _WINIX
1481da2e3ebdSchin 			{
1482da2e3ebdSchin 				char*	name;
14837c2fbfb3SApril Chin 				name = shp->st.dolv[0];
1484da2e3ebdSchin 				if(name[1]==':' && (name[2]=='/' || name[2]=='\\'))
1485da2e3ebdSchin 				{
1486da2e3ebdSchin #if _lib_pathposix
1487da2e3ebdSchin 					char*	p;
1488da2e3ebdSchin 
1489da2e3ebdSchin 					if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n)))
1490da2e3ebdSchin 					{
1491da2e3ebdSchin 						pathposix(name, p, n);
1492da2e3ebdSchin 						name = p;
1493da2e3ebdSchin 					}
1494da2e3ebdSchin 					else
1495da2e3ebdSchin #endif
1496da2e3ebdSchin 					{
1497da2e3ebdSchin 						name[1] = name[0];
1498da2e3ebdSchin 						name[0] = name[2] = '/';
1499da2e3ebdSchin 					}
1500da2e3ebdSchin 				}
1501da2e3ebdSchin 			}
1502da2e3ebdSchin #endif /* _WINIX */
1503da2e3ebdSchin 		}
1504*b30d1939SAndy Fiddaman 		if(beenhere==1)
1505*b30d1939SAndy Fiddaman 		{
1506*b30d1939SAndy Fiddaman 			struct lconv*	lc;
1507*b30d1939SAndy Fiddaman 			shp->decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
1508*b30d1939SAndy Fiddaman 			beenhere = 2;
1509*b30d1939SAndy Fiddaman 		}
1510da2e3ebdSchin 	}
1511da2e3ebdSchin #if SHOPT_PFSH
1512da2e3ebdSchin 	if (sh_isoption(SH_PFSH))
1513da2e3ebdSchin 	{
1514*b30d1939SAndy Fiddaman 		struct passwd *pw = getpwuid(shp->gd->userid);
1515da2e3ebdSchin 		if(pw)
1516*b30d1939SAndy Fiddaman 			shp->gd->user = strdup(pw->pw_name);
1517da2e3ebdSchin 
1518da2e3ebdSchin 	}
1519da2e3ebdSchin #endif
1520da2e3ebdSchin 	/* set[ug]id scripts require the -p flag */
1521*b30d1939SAndy Fiddaman 	if(shp->gd->userid!=shp->gd->euserid || shp->gd->groupid!=shp->gd->egroupid)
1522da2e3ebdSchin 	{
152334f9b3eeSRoland Mainz #ifdef SHOPT_P_SUID
1524da2e3ebdSchin 		/* require sh -p to run setuid and/or setgid */
1525*b30d1939SAndy Fiddaman 		if(!sh_isoption(SH_PRIVILEGED) && shp->gd->userid >= SHOPT_P_SUID)
1526da2e3ebdSchin 		{
1527*b30d1939SAndy Fiddaman 			setuid(shp->gd->euserid=shp->gd->userid);
1528*b30d1939SAndy Fiddaman 			setgid(shp->gd->egroupid=shp->gd->groupid);
1529da2e3ebdSchin 		}
1530da2e3ebdSchin 		else
1531da2e3ebdSchin #endif /* SHOPT_P_SUID */
153234f9b3eeSRoland Mainz 			sh_onoption(SH_PRIVILEGED);
1533da2e3ebdSchin #ifdef SHELLMAGIC
1534da2e3ebdSchin 		/* careful of #! setuid scripts with name beginning with - */
15357c2fbfb3SApril Chin 		if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0)
1536da2e3ebdSchin 			errormsg(SH_DICT,ERROR_exit(1),e_prohibited);
1537da2e3ebdSchin #endif /*SHELLMAGIC*/
1538da2e3ebdSchin 	}
1539da2e3ebdSchin 	else
1540da2e3ebdSchin 		sh_offoption(SH_PRIVILEGED);
1541da2e3ebdSchin 	/* shname for $0 in profiles and . scripts */
1542*b30d1939SAndy Fiddaman 	if(sh_isdevfd(argv[1]))
15437c2fbfb3SApril Chin 		shp->shname = strdup(argv[0]);
1544da2e3ebdSchin 	else
15457c2fbfb3SApril Chin 		shp->shname = strdup(shp->st.dolv[0]);
1546da2e3ebdSchin 	/*
1547da2e3ebdSchin 	 * return here for shell script execution
1548da2e3ebdSchin 	 * but not for parenthesis subshells
1549da2e3ebdSchin 	 */
15507c2fbfb3SApril Chin 	error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */
15517c2fbfb3SApril Chin 	shp->jmpbuffer = (void*)&shp->checkbase;
1552*b30d1939SAndy Fiddaman 	sh_pushcontext(shp,&shp->checkbase,SH_JMPSCRIPT);
15537c2fbfb3SApril Chin 	shp->st.self = &shp->global;
15547c2fbfb3SApril Chin         shp->topscope = (Shscope_t*)shp->st.self;
1555da2e3ebdSchin 	sh_offstate(SH_INIT);
1556da2e3ebdSchin 	login_files[0] = (char*)e_profile;
1557da2e3ebdSchin 	login_files[1] = ".profile";
1558*b30d1939SAndy Fiddaman 	shp->gd->login_files = login_files;
15597c2fbfb3SApril Chin 	shp->bltindata.version = SH_VERSION;
15607c2fbfb3SApril Chin 	shp->bltindata.shp = shp;
15617c2fbfb3SApril Chin 	shp->bltindata.shrun = sh_run;
15627c2fbfb3SApril Chin 	shp->bltindata.shtrap = sh_trap;
15637c2fbfb3SApril Chin 	shp->bltindata.shexit = sh_exit;
15647c2fbfb3SApril Chin 	shp->bltindata.shbltin = sh_addbuiltin;
15657c2fbfb3SApril Chin #if _AST_VERSION >= 20080617L
15663e14f97fSRoger A. Faulkner 	shp->bltindata.shgetenv = sh_getenv;
15673e14f97fSRoger A. Faulkner 	shp->bltindata.shsetenv = sh_setenviron;
15687c2fbfb3SApril Chin 	astintercept(&shp->bltindata,1);
15697c2fbfb3SApril Chin #endif
15707c2fbfb3SApril Chin #if 0
15717c2fbfb3SApril Chin #define NV_MKINTTYPE(x,y,z)	nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z);
15727c2fbfb3SApril Chin 	NV_MKINTTYPE(pid_t,"process id",0);
15737c2fbfb3SApril Chin 	NV_MKINTTYPE(gid_t,"group id",0);
15747c2fbfb3SApril Chin 	NV_MKINTTYPE(uid_t,"user id",0);
15757c2fbfb3SApril Chin 	NV_MKINTTYPE(size_t,(const char*)0,0);
15767c2fbfb3SApril Chin 	NV_MKINTTYPE(ssize_t,(const char*)0,0);
15777c2fbfb3SApril Chin 	NV_MKINTTYPE(off_t,"offset in bytes",0);
15787c2fbfb3SApril Chin 	NV_MKINTTYPE(ino_t,"\ai-\anode number",0);
15797c2fbfb3SApril Chin 	NV_MKINTTYPE(mode_t,(const char*)0,&modedisc);
15807c2fbfb3SApril Chin 	NV_MKINTTYPE(dev_t,"device id",0);
15817c2fbfb3SApril Chin 	NV_MKINTTYPE(nlink_t,"hard link count",0);
15827c2fbfb3SApril Chin 	NV_MKINTTYPE(blkcnt_t,"block count",0);
15837c2fbfb3SApril Chin 	NV_MKINTTYPE(time_t,"seconds since the epoch",0);
15847c2fbfb3SApril Chin 	nv_mkstat();
15857c2fbfb3SApril Chin #endif
15867c2fbfb3SApril Chin 	if(shp->userinit=userinit)
15877c2fbfb3SApril Chin 		(*userinit)(shp, 0);
1588*b30d1939SAndy Fiddaman 	shp->exittrap = 0;
1589*b30d1939SAndy Fiddaman 	shp->errtrap = 0;
1590*b30d1939SAndy Fiddaman 	shp->end_fn = 0;
15917c2fbfb3SApril Chin 	return(shp);
1592da2e3ebdSchin }
1593da2e3ebdSchin 
sh_getinterp(void)1594da2e3ebdSchin Shell_t *sh_getinterp(void)
1595da2e3ebdSchin {
1596da2e3ebdSchin 	return(&sh);
1597da2e3ebdSchin }
1598da2e3ebdSchin 
1599da2e3ebdSchin /*
1600da2e3ebdSchin  * reinitialize before executing a script
1601da2e3ebdSchin  */
sh_reinit(char * argv[])1602da2e3ebdSchin int sh_reinit(char *argv[])
1603da2e3ebdSchin {
1604*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1605da2e3ebdSchin 	Shopt_t opt;
16067c2fbfb3SApril Chin 	Namval_t *np,*npnext;
16077c2fbfb3SApril Chin 	Dt_t	*dp;
1608*b30d1939SAndy Fiddaman 	struct adata
1609*b30d1939SAndy Fiddaman 	{
1610*b30d1939SAndy Fiddaman 		Shell_t		*sh;
1611*b30d1939SAndy Fiddaman 		void		*extra[2];
1612*b30d1939SAndy Fiddaman 	} data;
16137c2fbfb3SApril Chin 	for(np=dtfirst(shp->fun_tree);np;np=npnext)
1614da2e3ebdSchin 	{
16157c2fbfb3SApril Chin 		if((dp=shp->fun_tree)->walk)
16167c2fbfb3SApril Chin 			dp = dp->walk;
16177c2fbfb3SApril Chin 		npnext = (Namval_t*)dtnext(shp->fun_tree,np);
1618*b30d1939SAndy Fiddaman 		if(np>= shgd->bltin_cmds && np < &shgd->bltin_cmds[nbltins])
16197c2fbfb3SApril Chin 			continue;
16207c2fbfb3SApril Chin 		if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT))
16217c2fbfb3SApril Chin 			continue;
16227c2fbfb3SApril Chin 		if(*np->nvname=='/')
16237c2fbfb3SApril Chin 			continue;
16247c2fbfb3SApril Chin 		nv_delete(np,dp,NV_NOFREE);
16257c2fbfb3SApril Chin 	}
16267c2fbfb3SApril Chin 	dtclose(shp->alias_tree);
16277c2fbfb3SApril Chin 	shp->alias_tree = inittree(shp,shtab_aliases);
16287c2fbfb3SApril Chin 	shp->last_root = shp->var_tree;
16297c2fbfb3SApril Chin 	shp->inuse_bits = 0;
16307c2fbfb3SApril Chin 	if(shp->userinit)
16317c2fbfb3SApril Chin 		(*shp->userinit)(shp, 1);
16327c2fbfb3SApril Chin 	if(shp->heredocs)
16337c2fbfb3SApril Chin 	{
16347c2fbfb3SApril Chin 		sfclose(shp->heredocs);
16357c2fbfb3SApril Chin 		shp->heredocs = 0;
1636da2e3ebdSchin 	}
1637da2e3ebdSchin 	/* remove locals */
1638da2e3ebdSchin 	sh_onstate(SH_INIT);
1639*b30d1939SAndy Fiddaman 	memset(&data,0,sizeof(data));
1640*b30d1939SAndy Fiddaman 	data.sh = shp;
1641*b30d1939SAndy Fiddaman 	nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_EXPORT,0);
1642*b30d1939SAndy Fiddaman 	nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_ARRAY,NV_ARRAY);
1643da2e3ebdSchin 	sh_offstate(SH_INIT);
16447c2fbfb3SApril Chin 	memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*));
1645da2e3ebdSchin 	memset((void*)&opt,0,sizeof(opt));
1646*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1647*b30d1939SAndy Fiddaman 	if(shp->namespace)
1648*b30d1939SAndy Fiddaman 	{
1649*b30d1939SAndy Fiddaman 		dp=nv_dict(shp->namespace);
1650*b30d1939SAndy Fiddaman 		if(dp==shp->var_tree)
1651*b30d1939SAndy Fiddaman 			shp->var_tree = dtview(dp,0);
1652*b30d1939SAndy Fiddaman 		_nv_unset(shp->namespace,NV_RDONLY);
1653*b30d1939SAndy Fiddaman 		shp->namespace = 0;
1654*b30d1939SAndy Fiddaman 	}
1655*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1656da2e3ebdSchin 	if(sh_isoption(SH_TRACKALL))
1657da2e3ebdSchin 		on_option(&opt,SH_TRACKALL);
1658da2e3ebdSchin 	if(sh_isoption(SH_EMACS))
1659da2e3ebdSchin 		on_option(&opt,SH_EMACS);
1660da2e3ebdSchin 	if(sh_isoption(SH_GMACS))
1661da2e3ebdSchin 		on_option(&opt,SH_GMACS);
1662da2e3ebdSchin 	if(sh_isoption(SH_VI))
1663da2e3ebdSchin 		on_option(&opt,SH_VI);
1664da2e3ebdSchin 	if(sh_isoption(SH_VIRAW))
1665da2e3ebdSchin 		on_option(&opt,SH_VIRAW);
16667c2fbfb3SApril Chin 	shp->options = opt;
1667da2e3ebdSchin 	/* set up new args */
1668da2e3ebdSchin 	if(argv)
16697c2fbfb3SApril Chin 		shp->arglist = sh_argcreate(argv);
16707c2fbfb3SApril Chin 	if(shp->arglist)
16717c2fbfb3SApril Chin 		sh_argreset(shp,shp->arglist,NIL(struct dolnod*));
16727c2fbfb3SApril Chin 	shp->envlist=0;
16737c2fbfb3SApril Chin 	shp->curenv = 0;
16747c2fbfb3SApril Chin 	shp->shname = error_info.id = strdup(shp->st.dolv[0]);
1675da2e3ebdSchin 	sh_offstate(SH_FORKED);
16767c2fbfb3SApril Chin 	shp->fn_depth = shp->dot_depth = 0;
1677da2e3ebdSchin 	sh_sigreset(0);
167834f9b3eeSRoland Mainz 	if(!(SHLVL->nvalue.ip))
167934f9b3eeSRoland Mainz 	{
168034f9b3eeSRoland Mainz 		shlvl = 0;
168134f9b3eeSRoland Mainz 		SHLVL->nvalue.ip = &shlvl;
168234f9b3eeSRoland Mainz 		nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
168334f9b3eeSRoland Mainz 	}
16847c2fbfb3SApril Chin 	*SHLVL->nvalue.ip +=1;
1685*b30d1939SAndy Fiddaman 	nv_offattr(SHLVL,NV_IMPORT);
168634f9b3eeSRoland Mainz 	shp->st.filename = strdup(shp->lastarg);
1687*b30d1939SAndy Fiddaman 	nv_delete((Namval_t*)0, (Dt_t*)0, 0);
1688*b30d1939SAndy Fiddaman 	job.exitval = 0;
1689*b30d1939SAndy Fiddaman 	shp->inpipe = shp->outpipe = 0;
1690*b30d1939SAndy Fiddaman 	job_clear();
1691*b30d1939SAndy Fiddaman 	job.in_critical = 0;
1692*b30d1939SAndy Fiddaman 	shp->exittrap = 0;
1693*b30d1939SAndy Fiddaman 	shp->errtrap = 0;
1694*b30d1939SAndy Fiddaman 	shp->end_fn = 0;
1695da2e3ebdSchin 	return(1);
1696da2e3ebdSchin }
1697da2e3ebdSchin 
1698da2e3ebdSchin /*
1699da2e3ebdSchin  * set when creating a local variable of this name
1700da2e3ebdSchin  */
nv_cover(register Namval_t * np)1701da2e3ebdSchin Namfun_t *nv_cover(register Namval_t *np)
1702da2e3ebdSchin {
1703*b30d1939SAndy Fiddaman 	if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS || np==ENVNOD || np==LINENO)
1704da2e3ebdSchin 		return(np->nvfun);
1705da2e3ebdSchin #ifdef _hdr_locale
1706da2e3ebdSchin 	if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD)
1707da2e3ebdSchin 		return(np->nvfun);
1708da2e3ebdSchin #endif
1709da2e3ebdSchin 	 return(0);
1710da2e3ebdSchin }
1711da2e3ebdSchin 
1712da2e3ebdSchin static const char *shdiscnames[] = { "tilde", 0};
1713da2e3ebdSchin 
17147c2fbfb3SApril Chin #ifdef SHOPT_STATS
17157c2fbfb3SApril Chin struct Stats
17167c2fbfb3SApril Chin {
17177c2fbfb3SApril Chin 	Namfun_t	hdr;
17187c2fbfb3SApril Chin 	Shell_t		*sh;
17197c2fbfb3SApril Chin 	char		*nodes;
17207c2fbfb3SApril Chin 	int		numnodes;
17217c2fbfb3SApril Chin 	int		current;
17227c2fbfb3SApril Chin };
17237c2fbfb3SApril Chin 
next_stat(register Namval_t * np,Dt_t * root,Namfun_t * fp)17247c2fbfb3SApril Chin static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp)
17257c2fbfb3SApril Chin {
17267c2fbfb3SApril Chin 	struct Stats *sp = (struct Stats*)fp;
17277c2fbfb3SApril Chin 	if(!root)
17287c2fbfb3SApril Chin 		sp->current = 0;
17297c2fbfb3SApril Chin 	else if(++sp->current>=sp->numnodes)
17307c2fbfb3SApril Chin 		return(0);
17317c2fbfb3SApril Chin 	return(nv_namptr(sp->nodes,sp->current));
17327c2fbfb3SApril Chin }
17337c2fbfb3SApril Chin 
create_stat(Namval_t * np,const char * name,int flag,Namfun_t * fp)17347c2fbfb3SApril Chin static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp)
17357c2fbfb3SApril Chin {
17367c2fbfb3SApril Chin 	struct Stats		*sp = (struct Stats*)fp;
17377c2fbfb3SApril Chin 	register const char	*cp=name;
17387c2fbfb3SApril Chin 	register int		i=0,n;
17397c2fbfb3SApril Chin 	Namval_t		*nq=0;
17407c2fbfb3SApril Chin 	Shell_t			*shp = sp->sh;
17417c2fbfb3SApril Chin 	if(!name)
17427c2fbfb3SApril Chin 		return(SH_STATS);
17437c2fbfb3SApril Chin 	while((i=*cp++) && i != '=' && i != '+' && i!='[');
17447c2fbfb3SApril Chin 	n = (cp-1) -name;
17457c2fbfb3SApril Chin 	for(i=0; i < sp->numnodes; i++)
17467c2fbfb3SApril Chin 	{
17477c2fbfb3SApril Chin 		nq = nv_namptr(sp->nodes,i);
17487c2fbfb3SApril Chin 		if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
17497c2fbfb3SApril Chin 			goto found;
17507c2fbfb3SApril Chin 	}
17517c2fbfb3SApril Chin 	nq = 0;
17527c2fbfb3SApril Chin found:
17537c2fbfb3SApril Chin 	if(nq)
17547c2fbfb3SApril Chin 	{
17557c2fbfb3SApril Chin 		fp->last = (char*)&name[n];
17567c2fbfb3SApril Chin 		shp->last_table = SH_STATS;
17577c2fbfb3SApril Chin 	}
17587c2fbfb3SApril Chin 	else
17597c2fbfb3SApril Chin 		errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
17607c2fbfb3SApril Chin 	return(nq);
17617c2fbfb3SApril Chin }
17627c2fbfb3SApril Chin 
17637c2fbfb3SApril Chin static const Namdisc_t stat_disc =
17647c2fbfb3SApril Chin {
17657c2fbfb3SApril Chin 	0, 0, 0, 0, 0,
17667c2fbfb3SApril Chin 	create_stat,
17677c2fbfb3SApril Chin 	0, 0,
17687c2fbfb3SApril Chin 	next_stat
17697c2fbfb3SApril Chin };
17707c2fbfb3SApril Chin 
name_stat(Namval_t * np,Namfun_t * fp)17717c2fbfb3SApril Chin static char *name_stat(Namval_t *np, Namfun_t *fp)
17727c2fbfb3SApril Chin {
17737c2fbfb3SApril Chin 	Shell_t	*shp = sh_getinterp();
17747c2fbfb3SApril Chin 	sfprintf(shp->strbuf,".sh.stats.%s",np->nvname);
17757c2fbfb3SApril Chin 	return(sfstruse(shp->strbuf));
17767c2fbfb3SApril Chin }
17777c2fbfb3SApril Chin 
17787c2fbfb3SApril Chin static const Namdisc_t	stat_child_disc =
17797c2fbfb3SApril Chin {
17807c2fbfb3SApril Chin 	0,0,0,0,0,0,0,
17817c2fbfb3SApril Chin 	name_stat
17827c2fbfb3SApril Chin };
17837c2fbfb3SApril Chin 
17847c2fbfb3SApril Chin static Namfun_t	 stat_child_fun =
17857c2fbfb3SApril Chin {
17867c2fbfb3SApril Chin 	&stat_child_disc, 1, 0, sizeof(Namfun_t)
17877c2fbfb3SApril Chin };
17887c2fbfb3SApril Chin 
stat_init(Shell_t * shp)17897c2fbfb3SApril Chin static void stat_init(Shell_t *shp)
17907c2fbfb3SApril Chin {
17917c2fbfb3SApril Chin 	int		i,nstat = STAT_SUBSHELL+1;
17927c2fbfb3SApril Chin 	struct Stats	*sp = newof(0,struct Stats,1,nstat*NV_MINSZ);
17937c2fbfb3SApril Chin 	Namval_t	*np;
17947c2fbfb3SApril Chin 	sp->numnodes = nstat;
17957c2fbfb3SApril Chin 	sp->nodes = (char*)(sp+1);
1796*b30d1939SAndy Fiddaman 	shgd->stats = (int*)calloc(sizeof(int),nstat);
17977c2fbfb3SApril Chin 	sp->sh = shp;
17987c2fbfb3SApril Chin 	for(i=0; i < nstat; i++)
17997c2fbfb3SApril Chin 	{
18007c2fbfb3SApril Chin 		np = nv_namptr(sp->nodes,i);
18017c2fbfb3SApril Chin 		np->nvfun = &stat_child_fun;
18027c2fbfb3SApril Chin 		np->nvname = (char*)shtab_stats[i].sh_name;
18037c2fbfb3SApril Chin 		nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER);
18047c2fbfb3SApril Chin 		nv_setsize(np,10);
1805*b30d1939SAndy Fiddaman 		np->nvalue.ip = &shgd->stats[i];
18067c2fbfb3SApril Chin 	}
18077c2fbfb3SApril Chin 	sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ);
18087c2fbfb3SApril Chin 	sp->hdr.disc = &stat_disc;
18097c2fbfb3SApril Chin 	nv_stack(SH_STATS,&sp->hdr);
18107c2fbfb3SApril Chin 	sp->hdr.nofree = 1;
18117c2fbfb3SApril Chin 	nv_setvtree(SH_STATS);
18127c2fbfb3SApril Chin }
18137c2fbfb3SApril Chin #else
18147c2fbfb3SApril Chin #   define stat_init(x)
18157c2fbfb3SApril Chin #endif /* SHOPT_STATS */
18167c2fbfb3SApril Chin 
1817da2e3ebdSchin /*
1818da2e3ebdSchin  * Initialize the shell name and alias table
1819da2e3ebdSchin  */
nv_init(Shell_t * shp)1820da2e3ebdSchin static Init_t *nv_init(Shell_t *shp)
1821da2e3ebdSchin {
1822da2e3ebdSchin 	double d=0;
1823da2e3ebdSchin 	ip = newof(0,Init_t,1,0);
1824da2e3ebdSchin 	if(!ip)
1825da2e3ebdSchin 		return(0);
18267c2fbfb3SApril Chin 	shp->nvfun.last = (char*)shp;
18277c2fbfb3SApril Chin 	shp->nvfun.nofree = 1;
1828da2e3ebdSchin 	ip->sh = shp;
1829da2e3ebdSchin 	shp->var_base = shp->var_tree = inittree(shp,shtab_variables);
18307c2fbfb3SApril Chin 	SHLVL->nvalue.ip = &shlvl;
1831da2e3ebdSchin 	ip->IFS_init.hdr.disc = &IFS_disc;
18327c2fbfb3SApril Chin 	ip->PATH_init.disc = &RESTRICTED_disc;
18337c2fbfb3SApril Chin 	ip->PATH_init.nofree = 1;
18347c2fbfb3SApril Chin 	ip->FPATH_init.disc = &RESTRICTED_disc;
18357c2fbfb3SApril Chin 	ip->FPATH_init.nofree = 1;
18367c2fbfb3SApril Chin 	ip->CDPATH_init.disc = &CDPATH_disc;
18377c2fbfb3SApril Chin 	ip->CDPATH_init.nofree = 1;
18387c2fbfb3SApril Chin 	ip->SHELL_init.disc = &RESTRICTED_disc;
18397c2fbfb3SApril Chin 	ip->SHELL_init.nofree = 1;
18407c2fbfb3SApril Chin 	ip->ENV_init.disc = &RESTRICTED_disc;
18417c2fbfb3SApril Chin 	ip->ENV_init.nofree = 1;
18427c2fbfb3SApril Chin 	ip->VISUAL_init.disc = &EDITOR_disc;
18437c2fbfb3SApril Chin 	ip->VISUAL_init.nofree = 1;
18447c2fbfb3SApril Chin 	ip->EDITOR_init.disc = &EDITOR_disc;
18457c2fbfb3SApril Chin 	ip->EDITOR_init.nofree = 1;
18467c2fbfb3SApril Chin 	ip->HISTFILE_init.disc = &HISTFILE_disc;
18477c2fbfb3SApril Chin 	ip->HISTFILE_init.nofree = 1;
18487c2fbfb3SApril Chin 	ip->HISTSIZE_init.disc = &HISTFILE_disc;
18497c2fbfb3SApril Chin 	ip->HISTSIZE_init.nofree = 1;
18507c2fbfb3SApril Chin 	ip->OPTINDEX_init.disc = &OPTINDEX_disc;
18517c2fbfb3SApril Chin 	ip->OPTINDEX_init.nofree = 1;
1852da2e3ebdSchin 	ip->SECONDS_init.hdr.disc = &SECONDS_disc;
1853da2e3ebdSchin 	ip->SECONDS_init.hdr.nofree = 1;
1854da2e3ebdSchin 	ip->RAND_init.hdr.disc = &RAND_disc;
1855da2e3ebdSchin 	ip->RAND_init.hdr.nofree = 1;
1856*b30d1939SAndy Fiddaman 	ip->RAND_init.sh = shp;
1857da2e3ebdSchin 	ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc;
1858da2e3ebdSchin 	ip->SH_MATCH_init.hdr.nofree = 1;
1859*b30d1939SAndy Fiddaman 	ip->SH_MATH_init.disc = &SH_MATH_disc;
1860*b30d1939SAndy Fiddaman 	ip->SH_MATH_init.nofree = 1;
1861*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1862*b30d1939SAndy Fiddaman 	ip->SH_JOBPOOL_init.disc = &SH_JOBPOOL_disc;
1863*b30d1939SAndy Fiddaman 	ip->SH_JOBPOOL_init.nofree = 1;
1864*b30d1939SAndy Fiddaman 	nv_stack(SH_JOBPOOL, &ip->SH_JOBPOOL_init);
1865*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
18667c2fbfb3SApril Chin 	ip->SH_VERSION_init.disc = &SH_VERSION_disc;
18677c2fbfb3SApril Chin 	ip->SH_VERSION_init.nofree = 1;
18687c2fbfb3SApril Chin 	ip->LINENO_init.disc = &LINENO_disc;
18697c2fbfb3SApril Chin 	ip->LINENO_init.nofree = 1;
18707c2fbfb3SApril Chin 	ip->L_ARG_init.disc = &L_ARG_disc;
18717c2fbfb3SApril Chin 	ip->L_ARG_init.nofree = 1;
1872da2e3ebdSchin #ifdef _hdr_locale
18737c2fbfb3SApril Chin 	ip->LC_TYPE_init.disc = &LC_disc;
18747c2fbfb3SApril Chin 	ip->LC_TYPE_init.nofree = 1;
18757c2fbfb3SApril Chin 	ip->LC_NUM_init.disc = &LC_disc;
18767c2fbfb3SApril Chin 	ip->LC_NUM_init.nofree = 1;
18777c2fbfb3SApril Chin 	ip->LC_COLL_init.disc = &LC_disc;
18787c2fbfb3SApril Chin 	ip->LC_COLL_init.nofree = 1;
18797c2fbfb3SApril Chin 	ip->LC_MSG_init.disc = &LC_disc;
18807c2fbfb3SApril Chin 	ip->LC_MSG_init.nofree = 1;
18817c2fbfb3SApril Chin 	ip->LC_ALL_init.disc = &LC_disc;
18827c2fbfb3SApril Chin 	ip->LC_ALL_init.nofree = 1;
18837c2fbfb3SApril Chin 	ip->LANG_init.disc = &LC_disc;
18847c2fbfb3SApril Chin 	ip->LANG_init.nofree = 1;
1885da2e3ebdSchin #endif /* _hdr_locale */
1886da2e3ebdSchin 	nv_stack(IFSNOD, &ip->IFS_init.hdr);
1887*b30d1939SAndy Fiddaman 	ip->IFS_init.hdr.nofree = 1;
18887c2fbfb3SApril Chin 	nv_stack(PATHNOD, &ip->PATH_init);
18897c2fbfb3SApril Chin 	nv_stack(FPATHNOD, &ip->FPATH_init);
18907c2fbfb3SApril Chin 	nv_stack(CDPNOD, &ip->CDPATH_init);
18917c2fbfb3SApril Chin 	nv_stack(SHELLNOD, &ip->SHELL_init);
18927c2fbfb3SApril Chin 	nv_stack(ENVNOD, &ip->ENV_init);
18937c2fbfb3SApril Chin 	nv_stack(VISINOD, &ip->VISUAL_init);
18947c2fbfb3SApril Chin 	nv_stack(EDITNOD, &ip->EDITOR_init);
18957c2fbfb3SApril Chin 	nv_stack(HISTFILE, &ip->HISTFILE_init);
18967c2fbfb3SApril Chin 	nv_stack(HISTSIZE, &ip->HISTSIZE_init);
18977c2fbfb3SApril Chin 	nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
1898da2e3ebdSchin 	nv_stack(SECONDS, &ip->SECONDS_init.hdr);
18997c2fbfb3SApril Chin 	nv_stack(L_ARGNOD, &ip->L_ARG_init);
19007c2fbfb3SApril Chin 	nv_putval(SECONDS, (char*)&d, NV_DOUBLE);
1901da2e3ebdSchin 	nv_stack(RANDNOD, &ip->RAND_init.hdr);
1902*b30d1939SAndy Fiddaman 	d = (shp->gd->pid&RANDMASK);
19037c2fbfb3SApril Chin 	nv_putval(RANDNOD, (char*)&d, NV_DOUBLE);
19047c2fbfb3SApril Chin 	nv_stack(LINENO, &ip->LINENO_init);
1905*b30d1939SAndy Fiddaman 	SH_MATCHNOD->nvfun =  &ip->SH_MATCH_init.hdr;
1906da2e3ebdSchin 	nv_putsub(SH_MATCHNOD,(char*)0,10);
1907*b30d1939SAndy Fiddaman 	nv_stack(SH_MATHNOD, &ip->SH_MATH_init);
19087c2fbfb3SApril Chin 	nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init);
1909da2e3ebdSchin #ifdef _hdr_locale
19107c2fbfb3SApril Chin 	nv_stack(LCTYPENOD, &ip->LC_TYPE_init);
19117c2fbfb3SApril Chin 	nv_stack(LCALLNOD, &ip->LC_ALL_init);
19127c2fbfb3SApril Chin 	nv_stack(LCMSGNOD, &ip->LC_MSG_init);
19137c2fbfb3SApril Chin 	nv_stack(LCCOLLNOD, &ip->LC_COLL_init);
19147c2fbfb3SApril Chin 	nv_stack(LCNUMNOD, &ip->LC_NUM_init);
19157c2fbfb3SApril Chin 	nv_stack(LANGNOD, &ip->LANG_init);
1916da2e3ebdSchin #endif /* _hdr_locale */
1917*b30d1939SAndy Fiddaman 	(PPIDNOD)->nvalue.lp = (&shp->gd->ppid);
1918da2e3ebdSchin 	(TMOUTNOD)->nvalue.lp = (&shp->st.tmout);
1919da2e3ebdSchin 	(MCHKNOD)->nvalue.lp = (&sh_mailchk);
1920da2e3ebdSchin 	(OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
1921da2e3ebdSchin 	/* set up the seconds clock */
1922da2e3ebdSchin 	shp->alias_tree = inittree(shp,shtab_aliases);
1923da2e3ebdSchin 	shp->track_tree = dtopen(&_Nvdisc,Dtset);
1924da2e3ebdSchin 	shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
1925da2e3ebdSchin 	shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
1926da2e3ebdSchin 	dtview(shp->fun_tree,shp->bltin_tree);
1927*b30d1939SAndy Fiddaman 	nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
1928da2e3ebdSchin 	nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
1929*b30d1939SAndy Fiddaman 	DOTSHNOD->nvalue.cp = Empty;
1930*b30d1939SAndy Fiddaman 	nv_onattr(DOTSHNOD,NV_RDONLY);
19317c2fbfb3SApril Chin 	SH_LINENO->nvalue.ip = &shp->st.lineno;
19327c2fbfb3SApril Chin 	VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0);
19337c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD;
19347c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD);
19357c2fbfb3SApril Chin         VERSIONNOD->nvalue.nrp->table = DOTSHNOD;
1936*b30d1939SAndy Fiddaman 	nv_onattr(VERSIONNOD,NV_REF);
1937*b30d1939SAndy Fiddaman 	math_init(shp);
1938*b30d1939SAndy Fiddaman 	if(!shgd->stats)
1939*b30d1939SAndy Fiddaman 		stat_init(shp);
1940da2e3ebdSchin 	return(ip);
1941da2e3ebdSchin }
1942da2e3ebdSchin 
1943da2e3ebdSchin /*
1944da2e3ebdSchin  * initialize name-value pairs
1945da2e3ebdSchin  */
1946da2e3ebdSchin 
inittree(Shell_t * shp,const struct shtable2 * name_vals)1947da2e3ebdSchin static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals)
1948da2e3ebdSchin {
1949da2e3ebdSchin 	register Namval_t *np;
1950da2e3ebdSchin 	register const struct shtable2 *tp;
1951da2e3ebdSchin 	register unsigned n = 0;
1952da2e3ebdSchin 	register Dt_t *treep;
1953da2e3ebdSchin 	Dt_t *base_treep, *dict;
1954da2e3ebdSchin 	for(tp=name_vals;*tp->sh_name;tp++)
1955da2e3ebdSchin 		n++;
1956da2e3ebdSchin 	np = (Namval_t*)calloc(n,sizeof(Namval_t));
1957*b30d1939SAndy Fiddaman 	if(!shgd->bltin_nodes)
19587c2fbfb3SApril Chin 	{
1959*b30d1939SAndy Fiddaman 		shgd->bltin_nodes = np;
1960*b30d1939SAndy Fiddaman 		shgd->bltin_nnodes = n;
19617c2fbfb3SApril Chin 	}
1962da2e3ebdSchin 	else if(name_vals==(const struct shtable2*)shtab_builtins)
19637c2fbfb3SApril Chin 	{
1964*b30d1939SAndy Fiddaman 		shgd->bltin_cmds = np;
19657c2fbfb3SApril Chin 		nbltins = n;
19667c2fbfb3SApril Chin 	}
1967da2e3ebdSchin 	base_treep = treep = dtopen(&_Nvdisc,Dtoset);
19687c2fbfb3SApril Chin 	treep->user = (void*)shp;
1969da2e3ebdSchin 	for(tp=name_vals;*tp->sh_name;tp++,np++)
1970da2e3ebdSchin 	{
1971da2e3ebdSchin 		if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name))
1972da2e3ebdSchin 			np->nvname++;
1973da2e3ebdSchin 		else
1974da2e3ebdSchin 		{
1975da2e3ebdSchin 			np->nvname = (char*)tp->sh_name;
1976da2e3ebdSchin 			treep = base_treep;
1977da2e3ebdSchin 		}
1978da2e3ebdSchin 		np->nvenv = 0;
1979da2e3ebdSchin 		if(name_vals==(const struct shtable2*)shtab_builtins)
1980*b30d1939SAndy Fiddaman 			np->nvalue.bfp = (Nambfp_f)((struct shtable3*)tp)->sh_value;
1981da2e3ebdSchin 		else
19827c2fbfb3SApril Chin 		{
19837c2fbfb3SApril Chin 			if(name_vals == shtab_variables)
1984*b30d1939SAndy Fiddaman 				np->nvfun = &shp->nvfun;
1985da2e3ebdSchin 			np->nvalue.cp = (char*)tp->sh_value;
19867c2fbfb3SApril Chin 		}
1987da2e3ebdSchin 		nv_setattr(np,tp->sh_number);
1988*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_TABLE))
1989da2e3ebdSchin 			nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset));
1990da2e3ebdSchin 		if(nv_isattr(np,NV_INTEGER))
1991da2e3ebdSchin 			nv_setsize(np,10);
1992da2e3ebdSchin 		else
1993da2e3ebdSchin 			nv_setsize(np,0);
1994da2e3ebdSchin 		dtinsert(treep,np);
1995da2e3ebdSchin 		if(nv_istable(np))
1996da2e3ebdSchin 			treep = dict;
1997da2e3ebdSchin 	}
1998da2e3ebdSchin 	return(treep);
1999da2e3ebdSchin }
2000da2e3ebdSchin 
2001da2e3ebdSchin /*
2002da2e3ebdSchin  * read in the process environment and set up name-value pairs
2003da2e3ebdSchin  * skip over items that are not name-value pairs
2004da2e3ebdSchin  */
2005da2e3ebdSchin 
env_init(Shell_t * shp)2006da2e3ebdSchin static void env_init(Shell_t *shp)
2007da2e3ebdSchin {
2008*b30d1939SAndy Fiddaman 	register char		*cp;
2009*b30d1939SAndy Fiddaman 	register Namval_t	*np,*mp;
2010*b30d1939SAndy Fiddaman 	register char		**ep=environ;
2011*b30d1939SAndy Fiddaman 	char			*dp,*next=0;
2012*b30d1939SAndy Fiddaman 	int			nenv=0,k=0,size=0;
2013*b30d1939SAndy Fiddaman 	Namval_t		*np0;
2014da2e3ebdSchin #ifdef _ENV_H
2015da2e3ebdSchin 	shp->env = env_open(environ,3);
2016da2e3ebdSchin 	env_delete(shp->env,"_");
2017da2e3ebdSchin #endif
2018*b30d1939SAndy Fiddaman 	if(!ep)
2019*b30d1939SAndy Fiddaman 		goto skip;
2020*b30d1939SAndy Fiddaman 	while(*ep++)
2021*b30d1939SAndy Fiddaman 		nenv++;
2022*b30d1939SAndy Fiddaman 	np = newof(0,Namval_t,nenv,0);
2023*b30d1939SAndy Fiddaman 	for(np0=np,ep=environ;cp= *ep; ep++)
2024da2e3ebdSchin 	{
2025*b30d1939SAndy Fiddaman 		dp = strchr(cp,'=');
2026*b30d1939SAndy Fiddaman 		if(!dp)
2027*b30d1939SAndy Fiddaman 			continue;
2028*b30d1939SAndy Fiddaman 		*dp++ = 0;
2029*b30d1939SAndy Fiddaman 		if(mp = dtmatch(shp->var_base,cp))
2030da2e3ebdSchin 		{
2031*b30d1939SAndy Fiddaman                         if(strcmp(cp,VERSIONNOD->nvname)==0)
2032*b30d1939SAndy Fiddaman                         {
2033*b30d1939SAndy Fiddaman                                 dp[-1] = '=';
2034*b30d1939SAndy Fiddaman                                 continue;
2035*b30d1939SAndy Fiddaman                         }
2036*b30d1939SAndy Fiddaman 			mp->nvenv = (char*)cp;
2037*b30d1939SAndy Fiddaman 			dp[-1] = '=';
2038da2e3ebdSchin 		}
2039*b30d1939SAndy Fiddaman 		else if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]==0)
2040*b30d1939SAndy Fiddaman 		{
2041*b30d1939SAndy Fiddaman 			dp[-1] = '=';
2042*b30d1939SAndy Fiddaman 			next = cp+4;
2043*b30d1939SAndy Fiddaman 			continue;
2044*b30d1939SAndy Fiddaman 		}
2045*b30d1939SAndy Fiddaman 		else
2046*b30d1939SAndy Fiddaman 		{
2047*b30d1939SAndy Fiddaman 			k++;
2048*b30d1939SAndy Fiddaman 			mp = np++;
2049*b30d1939SAndy Fiddaman 			mp->nvname = cp;
2050*b30d1939SAndy Fiddaman 			size += strlen(cp);
2051*b30d1939SAndy Fiddaman 		}
2052*b30d1939SAndy Fiddaman 			nv_onattr(mp,NV_IMPORT);
2053*b30d1939SAndy Fiddaman 		if(mp->nvfun || nv_isattr(mp,NV_INTEGER))
2054*b30d1939SAndy Fiddaman 			nv_putval(mp,dp,0);
2055*b30d1939SAndy Fiddaman 		else
2056*b30d1939SAndy Fiddaman 		{
2057*b30d1939SAndy Fiddaman 			mp->nvalue.cp = dp;
2058*b30d1939SAndy Fiddaman 			nv_onattr(mp,NV_NOFREE);
2059*b30d1939SAndy Fiddaman 		}
2060*b30d1939SAndy Fiddaman 		nv_onattr(mp,NV_EXPORT|NV_IMPORT);
2061*b30d1939SAndy Fiddaman 	}
2062*b30d1939SAndy Fiddaman 	np =  (Namval_t*)realloc((void*)np0,k*sizeof(Namval_t));
2063*b30d1939SAndy Fiddaman 	dp = (char*)malloc(size+k);
2064*b30d1939SAndy Fiddaman 	while(k-->0)
2065*b30d1939SAndy Fiddaman 	{
2066*b30d1939SAndy Fiddaman 		size = strlen(np->nvname);
2067*b30d1939SAndy Fiddaman 		memcpy(dp,np->nvname,size+1);
2068*b30d1939SAndy Fiddaman 		np->nvname[size] = '=';
2069*b30d1939SAndy Fiddaman 		np->nvenv = np->nvname;
2070*b30d1939SAndy Fiddaman 		np->nvname = dp;
2071*b30d1939SAndy Fiddaman 		dp += size+1;
2072*b30d1939SAndy Fiddaman 		dtinsert(shp->var_base,np++);
2073*b30d1939SAndy Fiddaman 	}
2074*b30d1939SAndy Fiddaman 	while(cp=next)
2075*b30d1939SAndy Fiddaman 	{
2076*b30d1939SAndy Fiddaman 		if(next = strchr(++cp,'='))
2077*b30d1939SAndy Fiddaman 			*next = 0;
2078*b30d1939SAndy Fiddaman 		np = nv_search(cp+2,shp->var_tree,NV_ADD);
2079*b30d1939SAndy Fiddaman 		if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
2080da2e3ebdSchin 		{
2081*b30d1939SAndy Fiddaman 			int flag = *(unsigned char*)cp-' ';
2082*b30d1939SAndy Fiddaman 			int size = *(unsigned char*)(cp+1)-' ';
2083*b30d1939SAndy Fiddaman 			if((flag&NV_INTEGER) && size==0)
2084da2e3ebdSchin 			{
2085*b30d1939SAndy Fiddaman 				/* check for floating*/
2086*b30d1939SAndy Fiddaman 				char *val = nv_getval(np);
2087*b30d1939SAndy Fiddaman 				strtol(val,&dp,10);
2088*b30d1939SAndy Fiddaman 				if(*dp=='.' || *dp=='e' || *dp=='E')
2089da2e3ebdSchin 				{
2090*b30d1939SAndy Fiddaman 					char *lp;
2091*b30d1939SAndy Fiddaman 					flag |= NV_DOUBLE;
2092*b30d1939SAndy Fiddaman 					if(*dp=='.')
2093*b30d1939SAndy Fiddaman 					{
2094*b30d1939SAndy Fiddaman 						strtol(dp+1,&lp,10);
2095*b30d1939SAndy Fiddaman 						if(*lp)
2096*b30d1939SAndy Fiddaman 							dp = lp;
2097*b30d1939SAndy Fiddaman 					}
2098*b30d1939SAndy Fiddaman 					if(*dp && *dp!='.')
2099da2e3ebdSchin 					{
2100*b30d1939SAndy Fiddaman 						flag |= NV_EXPNOTE;
2101*b30d1939SAndy Fiddaman 						size = dp-val;
2102da2e3ebdSchin 					}
2103*b30d1939SAndy Fiddaman 					else
2104*b30d1939SAndy Fiddaman 						size = strlen(dp);
2105*b30d1939SAndy Fiddaman 					size--;
2106da2e3ebdSchin 				}
2107da2e3ebdSchin 			}
2108*b30d1939SAndy Fiddaman 			nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
2109*b30d1939SAndy Fiddaman 			if((flag&(NV_INTEGER|NV_UTOL|NV_LTOU))==(NV_UTOL|NV_LTOU))
2110*b30d1939SAndy Fiddaman 				nv_mapchar(np,(flag&NV_UTOL)?e_tolower:e_toupper);
2111da2e3ebdSchin 		}
2112*b30d1939SAndy Fiddaman 		else
2113*b30d1939SAndy Fiddaman 			cp += 2;
2114da2e3ebdSchin 	}
2115*b30d1939SAndy Fiddaman skip:
2116da2e3ebdSchin #ifdef _ENV_H
21177c2fbfb3SApril Chin 	env_delete(shp->env,e_envmarker);
2118da2e3ebdSchin #endif
2119da2e3ebdSchin 	if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
2120da2e3ebdSchin 	{
2121da2e3ebdSchin 		nv_offattr(PWDNOD,NV_TAGGED);
2122*b30d1939SAndy Fiddaman 		path_pwd(shp,0);
2123da2e3ebdSchin 	}
2124da2e3ebdSchin 	if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
2125da2e3ebdSchin 		sh_onoption(SH_RESTRICTED); /* restricted shell */
2126da2e3ebdSchin 	return;
2127da2e3ebdSchin }
2128da2e3ebdSchin 
2129da2e3ebdSchin /*
2130da2e3ebdSchin  * terminate shell and free up the space
2131da2e3ebdSchin  */
sh_term(void)2132da2e3ebdSchin int sh_term(void)
2133da2e3ebdSchin {
2134da2e3ebdSchin 	sfdisc(sfstdin,SF_POPDISC);
2135da2e3ebdSchin 	free((char*)sh.outbuff);
2136da2e3ebdSchin 	stakset(NIL(char*),0);
2137da2e3ebdSchin 	return(0);
2138da2e3ebdSchin }
2139da2e3ebdSchin 
2140da2e3ebdSchin /* function versions of these */
2141da2e3ebdSchin 
2142da2e3ebdSchin #define DISABLE	/* proto workaround */
2143da2e3ebdSchin 
DISABLE(int opt)2144da2e3ebdSchin unsigned long sh_isoption DISABLE (int opt)
2145da2e3ebdSchin {
2146da2e3ebdSchin 	return(sh_isoption(opt));
2147da2e3ebdSchin }
2148da2e3ebdSchin 
DISABLE(int opt)2149da2e3ebdSchin unsigned long sh_onoption DISABLE (int opt)
2150da2e3ebdSchin {
2151da2e3ebdSchin 	return(sh_onoption(opt));
2152da2e3ebdSchin }
2153da2e3ebdSchin 
DISABLE(int opt)2154da2e3ebdSchin unsigned long sh_offoption DISABLE (int opt)
2155da2e3ebdSchin {
2156da2e3ebdSchin 	return(sh_offoption(opt));
2157da2e3ebdSchin }
2158da2e3ebdSchin 
DISABLE(Shell_t * shp)2159*b30d1939SAndy Fiddaman void	sh_sigcheck DISABLE (Shell_t *shp)
2160da2e3ebdSchin {
2161*b30d1939SAndy Fiddaman 	if(!shp)
2162*b30d1939SAndy Fiddaman 		shp = sh_getinterp();
2163*b30d1939SAndy Fiddaman 	sh_sigcheck(shp);
2164da2e3ebdSchin }
2165da2e3ebdSchin 
DISABLE(void)2166da2e3ebdSchin Dt_t*	sh_bltin_tree DISABLE (void)
2167da2e3ebdSchin {
2168da2e3ebdSchin 	return(sh.bltin_tree);
2169da2e3ebdSchin }
2170*b30d1939SAndy Fiddaman 
2171*b30d1939SAndy Fiddaman /*
2172*b30d1939SAndy Fiddaman  * This code is for character mapped variables with wctrans()
2173*b30d1939SAndy Fiddaman  */
2174*b30d1939SAndy Fiddaman struct Mapchar
2175*b30d1939SAndy Fiddaman {
2176*b30d1939SAndy Fiddaman 	Namfun_t	hdr;
2177*b30d1939SAndy Fiddaman 	const char	*name;
2178*b30d1939SAndy Fiddaman 	wctrans_t	trans;
2179*b30d1939SAndy Fiddaman 	int		lctype;
2180*b30d1939SAndy Fiddaman };
2181*b30d1939SAndy Fiddaman 
put_trans(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2182*b30d1939SAndy Fiddaman static void put_trans(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2183*b30d1939SAndy Fiddaman {
2184*b30d1939SAndy Fiddaman 	struct Mapchar *mp = (struct Mapchar*)fp;
2185*b30d1939SAndy Fiddaman 	int	c,offset = staktell(),off=offset;
2186*b30d1939SAndy Fiddaman 	if(val)
2187*b30d1939SAndy Fiddaman 	{
2188*b30d1939SAndy Fiddaman 		if(mp->lctype!=lctype)
2189*b30d1939SAndy Fiddaman 		{
2190*b30d1939SAndy Fiddaman 			mp->lctype = lctype;
2191*b30d1939SAndy Fiddaman 			mp->trans = wctrans(mp->name);
2192*b30d1939SAndy Fiddaman 		}
2193*b30d1939SAndy Fiddaman 		if(!mp->trans || (flags&NV_INTEGER))
2194*b30d1939SAndy Fiddaman 			goto skip;
2195*b30d1939SAndy Fiddaman 		while(c = mbchar(val))
2196*b30d1939SAndy Fiddaman 		{
2197*b30d1939SAndy Fiddaman 			c = towctrans(c,mp->trans);
2198*b30d1939SAndy Fiddaman 			stakseek(off+c);
2199*b30d1939SAndy Fiddaman 			stakseek(off);
2200*b30d1939SAndy Fiddaman 			c  = mbconv(stakptr(off),c);
2201*b30d1939SAndy Fiddaman 			off += c;
2202*b30d1939SAndy Fiddaman 			stakseek(off);
2203*b30d1939SAndy Fiddaman 		}
2204*b30d1939SAndy Fiddaman 		stakputc(0);
2205*b30d1939SAndy Fiddaman 		val = stakptr(offset);
2206*b30d1939SAndy Fiddaman 	}
2207*b30d1939SAndy Fiddaman 	else
2208*b30d1939SAndy Fiddaman 	{
2209*b30d1939SAndy Fiddaman 		nv_putv(np,val,flags,fp);
2210*b30d1939SAndy Fiddaman 		nv_disc(np,fp,NV_POP);
2211*b30d1939SAndy Fiddaman 		if(!(fp->nofree&1))
2212*b30d1939SAndy Fiddaman 			free((void*)fp);
2213*b30d1939SAndy Fiddaman 		stakseek(offset);
2214*b30d1939SAndy Fiddaman 		return;
2215*b30d1939SAndy Fiddaman 	}
2216*b30d1939SAndy Fiddaman skip:
2217*b30d1939SAndy Fiddaman 	nv_putv(np,val,flags,fp);
2218*b30d1939SAndy Fiddaman 	stakseek(offset);
2219*b30d1939SAndy Fiddaman }
2220*b30d1939SAndy Fiddaman 
2221*b30d1939SAndy Fiddaman static const Namdisc_t TRANS_disc      = {  sizeof(struct Mapchar), put_trans };
2222*b30d1939SAndy Fiddaman 
nv_mapchar(Namval_t * np,const char * name)2223*b30d1939SAndy Fiddaman Namfun_t	*nv_mapchar(Namval_t *np,const char *name)
2224*b30d1939SAndy Fiddaman {
2225*b30d1939SAndy Fiddaman 	wctrans_t	trans = name?wctrans(name):0;
2226*b30d1939SAndy Fiddaman 	struct Mapchar	*mp=0;
2227*b30d1939SAndy Fiddaman 	int		n=0,low;
2228*b30d1939SAndy Fiddaman 	if(np)
2229*b30d1939SAndy Fiddaman 		mp = (struct Mapchar*)nv_hasdisc(np,&TRANS_disc);
2230*b30d1939SAndy Fiddaman 	if(!name)
2231*b30d1939SAndy Fiddaman 		return(mp?(Namfun_t*)mp->name:0);
2232*b30d1939SAndy Fiddaman 	if(!trans)
2233*b30d1939SAndy Fiddaman 		return(0);
2234*b30d1939SAndy Fiddaman 	if(!np)
2235*b30d1939SAndy Fiddaman 		return(((Namfun_t*)0)+1);
2236*b30d1939SAndy Fiddaman 	if((low=strcmp(name,e_tolower)) && strcmp(name,e_toupper))
2237*b30d1939SAndy Fiddaman 		n += strlen(name)+1;
2238*b30d1939SAndy Fiddaman 	if(mp)
2239*b30d1939SAndy Fiddaman 	{
2240*b30d1939SAndy Fiddaman 		if(strcmp(name,mp->name)==0)
2241*b30d1939SAndy Fiddaman 			return(&mp->hdr);
2242*b30d1939SAndy Fiddaman 		nv_disc(np,&mp->hdr,NV_POP);
2243*b30d1939SAndy Fiddaman 		if(!(mp->hdr.nofree&1))
2244*b30d1939SAndy Fiddaman 			free((void*)mp);
2245*b30d1939SAndy Fiddaman 	}
2246*b30d1939SAndy Fiddaman 	mp = newof(0,struct Mapchar,1,n);
2247*b30d1939SAndy Fiddaman 	mp->trans = trans;
2248*b30d1939SAndy Fiddaman 	mp->lctype = lctype;
2249*b30d1939SAndy Fiddaman 	if(low==0)
2250*b30d1939SAndy Fiddaman 		mp->name = e_tolower;
2251*b30d1939SAndy Fiddaman 	else if(n==0)
2252*b30d1939SAndy Fiddaman 		mp->name = e_toupper;
2253*b30d1939SAndy Fiddaman 	else
2254*b30d1939SAndy Fiddaman 	{
2255*b30d1939SAndy Fiddaman 		mp->name = (char*)(mp+1);
2256*b30d1939SAndy Fiddaman 		strcpy((char*)mp->name,name);
2257*b30d1939SAndy Fiddaman 	}
2258*b30d1939SAndy Fiddaman 	mp->hdr.disc =  &TRANS_disc;
2259*b30d1939SAndy Fiddaman 	return(&mp->hdr);
2260*b30d1939SAndy Fiddaman }
2261