xref: /csrg-svn/local/toolchest/ksh/sh/name.c (revision 35157)
1*35157Smarc /*
2*35157Smarc 
3*35157Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35157Smarc  *      All Rights Reserved
5*35157Smarc 
6*35157Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35157Smarc  *      CODE OF AT&T.
8*35157Smarc  *      The copyright notice above does not
9*35157Smarc  *      evidence any actual or intended
10*35157Smarc  *      publication of such source code.
11*35157Smarc 
12*35157Smarc  */
13*35157Smarc /*
14*35157Smarc  * AT&T Bell Laboratories
15*35157Smarc  *
16*35157Smarc  */
17*35157Smarc 
18*35157Smarc #include	"defs.h"
19*35157Smarc #include	"io.h"
20*35157Smarc #include	"flags.h"
21*35157Smarc #include	"name.h"
22*35157Smarc #include	"shtype.h"
23*35157Smarc #include	"sym.h"
24*35157Smarc #include	"stak.h"
25*35157Smarc #include	"brkincr.h"
26*35157Smarc #include	"builtins.h"
27*35157Smarc #include	"history.h"
28*35157Smarc #include	"timeout.h"
29*35157Smarc 
30*35157Smarc /* This module defines the following routines */
31*35157Smarc NAMPTR	checkfor();
32*35157Smarc void	do_whence();
33*35157Smarc #ifdef ECHO_N
34*35157Smarc char	*echo_mode();
35*35157Smarc #endif	/* ECHO_N */
36*35157Smarc #ifdef apollo
37*35157Smarc void	ev_$set_var();
38*35157Smarc #endif	/* apollo */
39*35157Smarc int	genenv();
40*35157Smarc char	*heap();
41*35157Smarc void	meminit();
42*35157Smarc void	mem_scope();
43*35157Smarc void	mem_unscope();
44*35157Smarc char	*movstr();
45*35157Smarc void	name_unscope();
46*35157Smarc char	*qvalup();
47*35157Smarc void	prinscan();
48*35157Smarc int	printnam();
49*35157Smarc void	printflg();
50*35157Smarc int	readvar();
51*35157Smarc void	rmlocal();
52*35157Smarc char	**setenv();
53*35157Smarc void	setlist();
54*35157Smarc NAMPTR	setname();
55*35157Smarc int	syslook();
56*35157Smarc 
57*35157Smarc /* This module references the following external routines */
58*35157Smarc extern void	assign();
59*35157Smarc extern char	*bracket_match();
60*35157Smarc extern unsigned	chkid();
61*35157Smarc #ifdef ECHO_N
62*35157Smarc extern MSG	echo_bin;
63*35157Smarc extern MSG	echo_opt;
64*35157Smarc #endif	/* ECHO_N */
65*35157Smarc extern char	**environ;
66*35157Smarc extern void	exitsh();
67*35157Smarc extern void	failed();
68*35157Smarc extern void	free();
69*35157Smarc extern NAMPTR	findnod();
70*35157Smarc extern char	*fullname();
71*35157Smarc extern char	*getstak();
72*35157Smarc extern struct Amemory *gettree();
73*35157Smarc extern void	gsort();
74*35157Smarc extern long	hist_list();
75*35157Smarc extern void	hist_flush();
76*35157Smarc extern void	initf();
77*35157Smarc extern void	gscan_all();
78*35157Smarc extern void	gscan_some();
79*35157Smarc extern NAMPTR	lookup();
80*35157Smarc extern void	linknod();
81*35157Smarc extern char	*mactrim();
82*35157Smarc extern char	*malloc();
83*35157Smarc extern char	*movstr();
84*35157Smarc extern unsigned	rand();
85*35157Smarc extern void	p_num();
86*35157Smarc extern void	p_str();
87*35157Smarc extern void	p_sub();
88*35157Smarc extern void	p_setout();
89*35157Smarc extern void	scan_all();
90*35157Smarc extern char	*simple();
91*35157Smarc extern int	srand();
92*35157Smarc extern char	*strchr();
93*35157Smarc extern char	*strcpy();
94*35157Smarc extern void	rmnval();
95*35157Smarc extern void	unassign();
96*35157Smarc extern long	time();
97*35157Smarc extern char	*utos();
98*35157Smarc extern char	*valup();
99*35157Smarc 
100*35157Smarc static void	countnam();
101*35157Smarc #ifdef ECHO_N
102*35157Smarc static char	*echo_arg;
103*35157Smarc #endif	/* ECHO_N */
104*35157Smarc static long	get_rand();
105*35157Smarc static long	get_second();
106*35157Smarc static struct Amemory *inittree();
107*35157Smarc static void	no_export();
108*35157Smarc static void	pr_name();
109*35157Smarc static void	pushnam();
110*35157Smarc static void	pushnid();
111*35157Smarc static void	rehash();
112*35157Smarc static void	rm_node();
113*35157Smarc static int	set_second();
114*35157Smarc static int	set_rand();
115*35157Smarc static char	*staknam();
116*35157Smarc 
117*35157Smarc 
118*35157Smarc static rsflag;	/* used to see if "SHELL" has been set in the environment */
119*35157Smarc static int	namec;
120*35157Smarc static char	**argnam;
121*35157Smarc static struct Amemory	*namebase;
122*35157Smarc 
123*35157Smarc struct Bfunction seconds = { get_second, set_second};
124*35157Smarc struct Bfunction randnum = { get_rand, set_rand};
125*35157Smarc 
126*35157Smarc 
127*35157Smarc 
128*35157Smarc /* ========	variable and string handling	======== */
129*35157Smarc 
130*35157Smarc /*
131*35157Smarc  *  Table lookup routine
132*35157Smarc  *  The table <syswds> is searched for string <w> and corresponding value is returned
133*35157Smarc  */
syslook(w,syswds)134*35157Smarc syslook(w,syswds)
135*35157Smarc register char *w;
136*35157Smarc SYSTAB		syswds;
137*35157Smarc {
138*35157Smarc 	register int first;
139*35157Smarc 	register SYSPTR	syscan;
140*35157Smarc 	register int c;
141*35157Smarc 	if(w==0 || (first= *w)==0)
142*35157Smarc 		return(0);
143*35157Smarc 	syscan=syswds;
144*35157Smarc 	while((c= *syscan->sysnam) && c <= first)
145*35157Smarc 	{
146*35157Smarc 		if(first == c && eq(w,syscan->sysnam))
147*35157Smarc 			return(syscan->sysval);
148*35157Smarc 		syscan++;
149*35157Smarc 	}
150*35157Smarc 	return(0);
151*35157Smarc }
152*35157Smarc 
153*35157Smarc /*
154*35157Smarc  * perform parameter assignment on an argument list
155*35157Smarc  */
156*35157Smarc 
setlist(arg,xp)157*35157Smarc void setlist(arg,xp)
158*35157Smarc register ARGPTR	arg;
159*35157Smarc register int xp;
160*35157Smarc {
161*35157Smarc 	if(is_option(ALLEXP))
162*35157Smarc 		xp |= N_EXPORT;
163*35157Smarc 	while(arg)
164*35157Smarc 	{
165*35157Smarc 		register char *s;
166*35157Smarc 		if(arg->argflag&A_MAC)
167*35157Smarc 			s=mactrim(arg->argval,0);
168*35157Smarc 		else
169*35157Smarc 			s = arg->argval;
170*35157Smarc 		setname(s, xp);
171*35157Smarc 		arg=arg->argnxt;
172*35157Smarc 		if(is_option(EXECPR))
173*35157Smarc 		{
174*35157Smarc 			p_setout(stderr);
175*35157Smarc 			p_str(s,arg?SP:NL);
176*35157Smarc 		}
177*35157Smarc 	}
178*35157Smarc }
179*35157Smarc 
180*35157Smarc /*
181*35157Smarc  * Put <arg> into associative memory.
182*35157Smarc  * If <xp> & V_FLAG then the alias list is used instead
183*35157Smarc  * If <xp> & S_FLAG then use the current scope only
184*35157Smarc  */
185*35157Smarc 
186*35157Smarc 
setname(argi,xp)187*35157Smarc NAMPTR	setname(argi, xp)
188*35157Smarc char *argi;
189*35157Smarc int 	xp;
190*35157Smarc {
191*35157Smarc 	register char *argscan=argi;
192*35157Smarc 	register NAMPTR	n;
193*35157Smarc 	register int sep = *argscan;
194*35157Smarc 	char *sim;
195*35157Smarc 	if(isalpha(sep) || ((xp&V_FLAG) && !expchar(sep)))
196*35157Smarc 	{
197*35157Smarc 		do
198*35157Smarc 		{
199*35157Smarc 			sep = *++argscan;
200*35157Smarc 		}
201*35157Smarc 		while(isalnum(sep));
202*35157Smarc 		/* check for subscript*/
203*35157Smarc 		if(sep=='[')
204*35157Smarc 		{
205*35157Smarc 			argscan = bracket_match(argscan)+1;
206*35157Smarc 		}
207*35157Smarc 		if((sep = *argscan) && sep!='=')
208*35157Smarc 			failed(argi,notid);
209*35157Smarc 		*argscan = 0;
210*35157Smarc 		if(xp&V_FLAG)
211*35157Smarc 		{
212*35157Smarc 			n = findnod(argi,alias,1);
213*35157Smarc 			if(attest(n,T_FLAG|NO_ALIAS))
214*35157Smarc 				pattrib(n,~(NO_ALIAS|T_FLAG|N_EXPORT));
215*35157Smarc 		}
216*35157Smarc 		else if(xp&S_FLAG)
217*35157Smarc 			/* scoped name must be in first tree */
218*35157Smarc 			n = findnod(argi,namep,1);
219*35157Smarc 		else
220*35157Smarc 			n = lookup(argi);
221*35157Smarc 		*argscan++ = sep;
222*35157Smarc 		if(sep == '=')
223*35157Smarc 		{
224*35157Smarc 			if(n==PATHNOD || n==ENVNOD || n==SHELLNOD)
225*35157Smarc 			{
226*35157Smarc 				if(is_option(RSHFLG))
227*35157Smarc 					failed(argi,restricted);
228*35157Smarc 				if(n==SHELLNOD)
229*35157Smarc 				{
230*35157Smarc 					sim = simple(argscan);
231*35157Smarc 					if(strchr(sim,'r') != NULL)
232*35157Smarc 						rsflag = 0;	/* restricted shell */
233*35157Smarc 				}
234*35157Smarc 			}
235*35157Smarc 			assign (n, argscan);
236*35157Smarc 			attrib(n, xp&~(S_FLAG|V_FLAG));
237*35157Smarc #ifdef apollo
238*35157Smarc 			if(attest(n,N_EXPORT) && attest(n,N_IMPORT)==0
239*35157Smarc 				&& (xp&(S_FLAG|V_FLAG))==0)
240*35157Smarc 			{
241*35157Smarc 				short namlen,vallen;
242*35157Smarc 				namlen =strlen(n->namid);
243*35157Smarc 				vallen = strlen(argscan);
244*35157Smarc 				ev_$set_var(n->namid,&namlen,argscan,&vallen);
245*35157Smarc 			}
246*35157Smarc #endif /* apollo */
247*35157Smarc 			if(n==PATHNOD)
248*35157Smarc 			{
249*35157Smarc 				gscan_some(rehash,alias,T_FLAG,T_FLAG);
250*35157Smarc #ifdef ECHO_N
251*35157Smarc 				echo_arg = NIL;
252*35157Smarc #endif	/* ECHO_N */
253*35157Smarc 			}
254*35157Smarc 			if(n==VISINOD || ((n==EDITNOD)&&isnull(VISINOD)))
255*35157Smarc 			{
256*35157Smarc 				/* turn on vi or emacs option if editor name is either*/
257*35157Smarc 				argscan = simple(argscan);
258*35157Smarc 				if(gmatch(argscan,"*vi"))
259*35157Smarc 				{
260*35157Smarc 					off_option(EDITVI|EMACS|GMACS);
261*35157Smarc 					on_option(EDITVI);
262*35157Smarc 				}
263*35157Smarc 				if(gmatch(argscan,"*macs"))
264*35157Smarc 				{
265*35157Smarc 					off_option(EDITVI|EMACS|GMACS);
266*35157Smarc 					if(*argscan=='g')
267*35157Smarc 						on_option(GMACS);
268*35157Smarc 					else
269*35157Smarc 						on_option(EMACS);
270*35157Smarc 				}
271*35157Smarc 			}
272*35157Smarc 		}
273*35157Smarc 		return(n);
274*35157Smarc 	}
275*35157Smarc 	failed (argi, notid);
276*35157Smarc 	/* NOTREACHED */
277*35157Smarc }
278*35157Smarc 
279*35157Smarc /*
280*35157Smarc  * Mark each node is invalid
281*35157Smarc  */
282*35157Smarc 
rehash(np)283*35157Smarc static void rehash(np)
284*35157Smarc register NAMPTR np;
285*35157Smarc {
286*35157Smarc 	attrib(np,NO_ALIAS);
287*35157Smarc }
288*35157Smarc 
289*35157Smarc /*
290*35157Smarc  *  alias each name to full path name
291*35157Smarc  *  realias returns the pathname or NULL if not found
292*35157Smarc  */
293*35157Smarc 
realias(np)294*35157Smarc char *realias(np)
295*35157Smarc register NAMPTR np;
296*35157Smarc {
297*35157Smarc 	register char *sp;
298*35157Smarc 	register char *vp = np->value.namval.cp;
299*35157Smarc 	int flag = namflag(np)&(N_EXPORT|NO_ALIAS|T_FLAG);
300*35157Smarc 	/* turn of T_FLAG to avoid recursion */
301*35157Smarc 	pattrib(np,~(NO_ALIAS|T_FLAG));
302*35157Smarc 	sp = fullname(np->namid);
303*35157Smarc 	if(sp==NIL)
304*35157Smarc 	{
305*35157Smarc 		unassign(np);
306*35157Smarc 		return(NIL);
307*35157Smarc 	}
308*35157Smarc 	else if(*sp!= '/')
309*35157Smarc 	{
310*35157Smarc 		sattrib(np,flag);
311*35157Smarc 		return(NIL);
312*35157Smarc 	}
313*35157Smarc 	if(vp==0 || strcmp(sp,vp)!=0)
314*35157Smarc 		assign(np,sp);
315*35157Smarc 	/* turn T_FLAG back on */
316*35157Smarc 	attrib(np,T_FLAG|N_EXPORT);
317*35157Smarc 	return(sp);
318*35157Smarc }
319*35157Smarc 
320*35157Smarc 
readvar(names,fd,raw)321*35157Smarc int readvar(names,fd,raw)
322*35157Smarc register char **names;
323*35157Smarc FILE *fd;
324*35157Smarc {
325*35157Smarc 	FILEBLK	fb;
326*35157Smarc 	SHFILE f;
327*35157Smarc 	register int c;
328*35157Smarc 	int issep;
329*35157Smarc 	register NAMPTR	n;
330*35157Smarc 	int checksep = 1;		/* set when looking for separators */
331*35157Smarc 	STKPTR	rel;
332*35157Smarc 	char *seps;
333*35157Smarc 	char is_eol;
334*35157Smarc 	FILE *savef;
335*35157Smarc 	states |= RWAIT;
336*35157Smarc 	/* save in history file if S_FLAG is set */
337*35157Smarc 	if((raw&S_FLAG) && fc_fix)
338*35157Smarc 		states |= FIXFLG;
339*35157Smarc 	raw &= R_FLAG;
340*35157Smarc 	f = &fb;
341*35157Smarc 	if(*names)
342*35157Smarc 	{
343*35157Smarc 		if(seps=strchr(*names,'?'))
344*35157Smarc 			*seps = 0;
345*35157Smarc 		n = lookup(*names++);
346*35157Smarc 		if(seps)
347*35157Smarc 			*seps = '?';
348*35157Smarc 	}
349*35157Smarc 	else
350*35157Smarc 		n = REPLYNOD;
351*35157Smarc 	rel=(STKPTR)relstak();
352*35157Smarc 	seps = qvalup(IFSNOD);
353*35157Smarc 	if(seps==NULL)
354*35157Smarc 		seps = sptbnl;
355*35157Smarc 	savef = input;
356*35157Smarc 	if(fd==NULL)
357*35157Smarc 		failed(bread,noquery);
358*35157Smarc 	if(fd != input)
359*35157Smarc 	{
360*35157Smarc 		/* buffer the input stream if possible */
361*35157Smarc 		if(fnobuff(fd) && (fd!=stdin || !ispipe(stdin)))
362*35157Smarc 			setbuf(fd,malloc((unsigned)BUFSIZ));
363*35157Smarc 		push(f);
364*35157Smarc 		initf(fd);
365*35157Smarc 	}
366*35157Smarc 	while(1)
367*35157Smarc 	{
368*35157Smarc 		c = (raw?readc():nextc());
369*35157Smarc 		issep = (strchr(seps,c)!=0);
370*35157Smarc 		is_eol = eolchar(c);
371*35157Smarc 		if(checksep && issep && !is_eol)
372*35157Smarc 		{
373*35157Smarc 			/* visable adjacent separators signify null fields*/
374*35157Smarc 			if(strchr(sptbnl,c)!=0)
375*35157Smarc 				continue;
376*35157Smarc 		}
377*35157Smarc 		checksep = 0;
378*35157Smarc 		if((issep && *names) || is_eol)	/* from non-separator to separator */
379*35157Smarc 		{
380*35157Smarc 			if(*names==NULL && staktop>stakbot)
381*35157Smarc 			{
382*35157Smarc 				/* remove trailing separators */
383*35157Smarc 				while(strchr(seps,*--staktop));
384*35157Smarc 				staktop++;
385*35157Smarc 			}
386*35157Smarc 			zerostak();
387*35157Smarc 			assign(n,absstak(rel)); setstak(rel);
388*35157Smarc 			if(is_option(ALLEXP))
389*35157Smarc 				attrib(n,N_EXPORT);
390*35157Smarc 			n = (*names?lookup(*names++):0);
391*35157Smarc 			if(is_eol)
392*35157Smarc 				break;
393*35157Smarc 			checksep = 1;
394*35157Smarc 		}
395*35157Smarc 		else 		/* not a separator */
396*35157Smarc 			pushstak(c);
397*35157Smarc 	}
398*35157Smarc 	while(n)
399*35157Smarc 	{
400*35157Smarc 		assign(n, nullstr);
401*35157Smarc 		if(is_option(ALLEXP))
402*35157Smarc 			attrib(n,N_EXPORT);
403*35157Smarc 		n = (*names?lookup(*names++):0);
404*35157Smarc 	}
405*35157Smarc 	if(savef != fd)
406*35157Smarc 		pop(1);
407*35157Smarc 	if(states&FIXFLG)
408*35157Smarc 		hist_flush();
409*35157Smarc 	states &= ~(RWAIT|PROMPT);
410*35157Smarc 	states |= is_option(INTFLG);
411*35157Smarc 	return;
412*35157Smarc }
413*35157Smarc 
414*35157Smarc /*
415*35157Smarc  * put string v onto the heap and return the heap pointer
416*35157Smarc  */
417*35157Smarc 
heap(v)418*35157Smarc char *heap(v)
419*35157Smarc register char *v;
420*35157Smarc {
421*35157Smarc 	register char *p;
422*35157Smarc 	if(v)
423*35157Smarc 	{
424*35157Smarc 		movstr(v,p=malloc((unsigned)strlen(v)+1));
425*35157Smarc 		return(p);
426*35157Smarc 	}
427*35157Smarc 	else
428*35157Smarc 		return(0);
429*35157Smarc }
430*35157Smarc 
431*35157Smarc 
432*35157Smarc /*
433*35157Smarc  * print out the name and value of a name-value pair <n>
434*35157Smarc  */
435*35157Smarc 
printnam(n,flag)436*35157Smarc int printnam(n,flag)
437*35157Smarc register NAMPTR		n;
438*35157Smarc register int	flag;
439*35157Smarc {
440*35157Smarc 	register FILE *fd;
441*35157Smarc 	register char *s;
442*35157Smarc 	union Namval *up= &n->value.namval;
443*35157Smarc 	if(trapnote&SIGSET)
444*35157Smarc 		exitsh(SIGFAIL);
445*35157Smarc 	fd = output;
446*35157Smarc 	if(attest(n,NO_ALIAS)==NO_ALIAS)
447*35157Smarc 	{
448*35157Smarc 		return(0);
449*35157Smarc 	}
450*35157Smarc 	if(is_afunction(n))
451*35157Smarc 	{
452*35157Smarc 		fputs(bltfn,fd);
453*35157Smarc 		fputs(n->namid,fd);
454*35157Smarc 		if(flag==0 && n->value.namval.rp->hoffset >=0 )
455*35157Smarc 		{
456*35157Smarc 			fputs(fn_hdr,fd);
457*35157Smarc 			hist_list(n->value.namval.rp->hoffset,EOF,"\n");
458*35157Smarc 		}
459*35157Smarc 		else
460*35157Smarc 			putc('\n',fd);
461*35157Smarc 		return(n->namsz+1);
462*35157Smarc 	}
463*35157Smarc 	if(s=valup(n))
464*35157Smarc 	{
465*35157Smarc 		char numbuf[30];
466*35157Smarc 		pr_name(n,0);
467*35157Smarc 		flag = (flag?NL:'=');
468*35157Smarc 	        if (attest (n, ARRAY))
469*35157Smarc 		{
470*35157Smarc 			if(attest(n,INT_GER))
471*35157Smarc 			{
472*35157Smarc 				/* copy to a save place */
473*35157Smarc 				strcpy(numbuf,s);
474*35157Smarc 				s = numbuf;
475*35157Smarc 			}
476*35157Smarc 			p_sub((int)up->aray->adot,flag);
477*35157Smarc 		}
478*35157Smarc 		else
479*35157Smarc 			putc(flag,fd);
480*35157Smarc 		if(flag != NL)
481*35157Smarc 			p_str(s,NL);
482*35157Smarc 		return(1);
483*35157Smarc 	}
484*35157Smarc 	return(0);
485*35157Smarc }
486*35157Smarc 
487*35157Smarc /*
488*35157Smarc  * print the name of a node followed by the character c
489*35157Smarc  */
490*35157Smarc 
pr_name(n,c)491*35157Smarc static void pr_name(n,c)
492*35157Smarc register NAMPTR		n;
493*35157Smarc int c;
494*35157Smarc {
495*35157Smarc 	register char *cp = strchr(n->namid,'=');
496*35157Smarc 	if(cp)
497*35157Smarc 		*cp = 0;
498*35157Smarc 	p_str(n->namid,c);
499*35157Smarc 	if(cp)
500*35157Smarc 		*cp = '=';
501*35157Smarc }
502*35157Smarc 
pushnid(np)503*35157Smarc static void pushnid(np)
504*35157Smarc NAMPTR np;
505*35157Smarc {
506*35157Smarc 	*argnam++ = np->namid;
507*35157Smarc 	namec++;
508*35157Smarc 	if(attest(np,ARRAY))
509*35157Smarc 		arayp(np)->adot = arayp(np)->maxi;
510*35157Smarc }
511*35157Smarc 
512*35157Smarc /*
513*35157Smarc  * print the nodes in tree <root> which have attributes <flag> set
514*35157Smarc  */
515*35157Smarc 
prinscan(file,flag,root,option)516*35157Smarc void prinscan(file,flag,root,option)
517*35157Smarc FILE *file;
518*35157Smarc struct Amemory *root;
519*35157Smarc {
520*35157Smarc 	register char **argv;
521*35157Smarc 	register NAMPTR np;
522*35157Smarc 	p_setout(file);
523*35157Smarc 	argv = argnam  = (char**)locstak();
524*35157Smarc 	namec = 0;
525*35157Smarc 	if(flag)
526*35157Smarc 		gscan_some(pushnid,root,flag,flag);
527*35157Smarc 	else
528*35157Smarc 		gscan_all(pushnid,root);
529*35157Smarc 	gsort(argv,namec);
530*35157Smarc 	while(namec--)
531*35157Smarc 	{
532*35157Smarc 		{
533*35157Smarc 			register char *cp;
534*35157Smarc 			if(cp = strchr(*argv,'='))
535*35157Smarc 				*cp = 0;
536*35157Smarc 			np = checkfor(*argv++,root);
537*35157Smarc 			if(cp)
538*35157Smarc 				*cp = '=';
539*35157Smarc 		}
540*35157Smarc 		if(np)
541*35157Smarc 		{
542*35157Smarc 			if(attest(np,ARRAY))
543*35157Smarc 			{
544*35157Smarc 				register struct Namaray *ap = arayp (np);
545*35157Smarc 				register int i, imax;
546*35157Smarc 				i = ap->adot = 0;
547*35157Smarc 				imax = ap->maxi;
548*35157Smarc 				for (; i <= imax; i++)
549*35157Smarc 				{
550*35157Smarc 					ap->adot = i;
551*35157Smarc 					if (ap->val[i])
552*35157Smarc 						printnam(np,option);
553*35157Smarc 				}
554*35157Smarc 			}
555*35157Smarc 			else
556*35157Smarc 				printnam(np,option);
557*35157Smarc 		}
558*35157Smarc 	}
559*35157Smarc }
560*35157Smarc 
staknam(n,value)561*35157Smarc static char *staknam(n,value)
562*35157Smarc char *	value;
563*35157Smarc register NAMPTR	n;
564*35157Smarc {
565*35157Smarc 	register char *p,*q;
566*35157Smarc 	q = getstak(strlen(n->namid)+strlen(value)+2);
567*35157Smarc 	p=movstr(n->namid,q);
568*35157Smarc 	*p++ = '=';
569*35157Smarc 	strcpy(p,value);
570*35157Smarc 	return(q);
571*35157Smarc }
572*35157Smarc 
573*35157Smarc 
printflg(n)574*35157Smarc void	printflg(n)
575*35157Smarc register NAMPTR		n;
576*35157Smarc {
577*35157Smarc 	register SYSPTR	syscan;
578*35157Smarc 	register int val;
579*35157Smarc 	if (namflag(n) != N_DEFAULT)
580*35157Smarc 	{
581*35157Smarc 		syscan=attributes;
582*35157Smarc 		while(*syscan->sysnam)
583*35157Smarc 		{
584*35157Smarc 			val = syscan->sysval;
585*35157Smarc 			if(attest(n,val)==val)
586*35157Smarc 			{
587*35157Smarc 				p_str(syscan->sysnam,SP);
588*35157Smarc 		                if (attest (n, L_JUST|R_JUST|Z_FILL))
589*35157Smarc 					p_num(n->namsz,SP);
590*35157Smarc 				if(val == (BLT_NOD|INT_GER))
591*35157Smarc 					break;
592*35157Smarc 			}
593*35157Smarc 		        if(val == INT_GER && attest(n,INT_GER))
594*35157Smarc 			{
595*35157Smarc 				if(n->namsz != 10)
596*35157Smarc 				{
597*35157Smarc 					p_str(intbase,SP);
598*35157Smarc 					p_num(n->namsz,SP);
599*35157Smarc 				}
600*35157Smarc 				break;
601*35157Smarc 			}
602*35157Smarc 			syscan++;
603*35157Smarc 		}
604*35157Smarc 		pr_name(n,NL);
605*35157Smarc 	}
606*35157Smarc }
607*35157Smarc 
genenv()608*35157Smarc int	genenv()
609*35157Smarc {
610*35157Smarc 	register char **e=environ;
611*35157Smarc 	register NAMPTR		n;
612*35157Smarc 	rsflag = 1;
613*35157Smarc 	if(e)
614*35157Smarc 	{
615*35157Smarc 		while(*e)
616*35157Smarc 		{
617*35157Smarc 			n = setname(*e, (N_IMPORT|N_EXPORT));
618*35157Smarc 			n->namid = *e++;
619*35157Smarc 		}
620*35157Smarc 	}
621*35157Smarc 	return(rsflag);
622*35157Smarc }
623*35157Smarc 
624*35157Smarc 
countnam()625*35157Smarc static void	countnam()
626*35157Smarc {
627*35157Smarc 	namec++;
628*35157Smarc }
629*35157Smarc 
630*35157Smarc 
pushnam(n)631*35157Smarc static void	pushnam(n)
632*35157Smarc register NAMPTR		n;
633*35157Smarc {
634*35157Smarc 	register char *value;
635*35157Smarc 	if(attest(n,N_IMPORT))
636*35157Smarc 		*argnam++ = n->namid;
637*35157Smarc 	else if(value=valup(n))
638*35157Smarc 		*argnam++ = staknam(n,value);
639*35157Smarc }
640*35157Smarc 
641*35157Smarc /*
642*35157Smarc  * Generate the environment list for the child.
643*35157Smarc  */
644*35157Smarc 
645*35157Smarc 
setenv()646*35157Smarc char **setenv()
647*35157Smarc {
648*35157Smarc 	register char **er;
649*35157Smarc 	namec = 0;
650*35157Smarc 	/* L_ARGNOD gets generated automatically as full path name of command */
651*35157Smarc 	pattrib(L_ARGNOD,~N_EXPORT);
652*35157Smarc 	gscan_some (countnam,namep, N_EXPORT|N_IMPORT, N_EXPORT);
653*35157Smarc 	er = (char**)getstak((namec+2)*BYTESPERWORD);
654*35157Smarc 	argnam = ++er;
655*35157Smarc 	gscan_some (pushnam, namep, N_EXPORT|N_IMPORT, N_EXPORT);
656*35157Smarc 	*argnam++ = 0;
657*35157Smarc 	return(er);
658*35157Smarc }
659*35157Smarc 
660*35157Smarc /*
661*35157Smarc  * Initialize the shell name and alias table
662*35157Smarc  */
663*35157Smarc 
meminit()664*35157Smarc void meminit()
665*35157Smarc {
666*35157Smarc 	register NAMPTR np;
667*35157Smarc 	bltin_nodes = (NAMPTR)malloc((unsigned)(NNODES*sizeof(struct Namnod)));
668*35157Smarc 	namebase = namep = inittree(node_names,bltin_nodes,0);
669*35157Smarc 	/* set up random number generator */
670*35157Smarc #ifdef apollo
671*35157Smarc 	(PPIDNOD)->value.namval.cp = (char*)(&ppid);
672*35157Smarc 	(L_ARGNOD)->value.namval.cp = (char*)(&lastarg);
673*35157Smarc 	(TMOUTNOD)->value.namval.cp = (char*)(&timeout);
674*35157Smarc 	(SECONDS)->value.namval.cp = (char*)(&seconds);
675*35157Smarc 	(MCHKNOD)->value.namval.cp = (char*)(&mailchk);
676*35157Smarc 	(RANDNOD)->value.namval.cp = (char*)(&randnum);
677*35157Smarc #endif	/* apollo */
678*35157Smarc 	namflag(RANDNOD) = N_FREE|INT_GER|BLT_NOD;
679*35157Smarc 	/* set up the seconds clock */
680*35157Smarc 	namflag(SECONDS) = N_FREE|INT_GER|BLT_NOD;
681*35157Smarc 	set_second(0L);
682*35157Smarc 	namflag(MCHKNOD) = N_FREE|INT_GER;
683*35157Smarc 	namflag(TMOUTNOD) = INT_GER;
684*35157Smarc 	namflag(PPIDNOD) = (N_FREE|INT_GER|N_RDONLY);
685*35157Smarc 	namflag(L_ARGNOD) = N_FREE|IN_DIR;
686*35157Smarc 	np = (NAMPTR)malloc(NALIAS*sizeof(struct Namnod));
687*35157Smarc 	alias = inittree(alias_names,np,N_EXPORT);
688*35157Smarc 	prnames = gettree(MEMSIZE/4);
689*35157Smarc }
690*35157Smarc 
691*35157Smarc /*
692*35157Smarc  * re-initialize name-value pairs after fork
693*35157Smarc  */
694*35157Smarc 
695*35157Smarc 
inittree(name_vals,nodes,atflag)696*35157Smarc static struct Amemory *inittree(name_vals,nodes,atflag)
697*35157Smarc struct name_value *name_vals;
698*35157Smarc NAMPTR nodes;
699*35157Smarc {
700*35157Smarc 	register struct Amemory *treep;
701*35157Smarc 	register NAMPTR np;
702*35157Smarc 	register struct name_value *nv;
703*35157Smarc 	int flag;
704*35157Smarc 	treep = gettree (MEMSIZE);
705*35157Smarc 	for(np=nodes,nv=name_vals;*nv->nv_name;nv++,np++)
706*35157Smarc 	{
707*35157Smarc 		np->namid = nv->nv_name;
708*35157Smarc 		np->value.namval.cp = nv->nv_value;
709*35157Smarc 		flag = 0;
710*35157Smarc #ifdef apollo
711*35157Smarc 		if(*nv->nv_value==0)
712*35157Smarc 			np->value.namval.cp = 0;
713*35157Smarc 		else
714*35157Smarc #else
715*35157Smarc 		if(nv->nv_value)
716*35157Smarc #endif	/* apollo */
717*35157Smarc 		{
718*35157Smarc 			flag = atflag|N_FREE;
719*35157Smarc 			if(atflag && *nv->nv_value=='/')
720*35157Smarc 				flag |= T_FLAG;
721*35157Smarc 		}
722*35157Smarc 		sattrib(np,flag);
723*35157Smarc 		np->namsz = 10;
724*35157Smarc 		linknod (np, treep);
725*35157Smarc 	}
726*35157Smarc 	return(treep);
727*35157Smarc }
728*35157Smarc 
729*35157Smarc /*
730*35157Smarc  * create a new environment scope
731*35157Smarc  */
732*35157Smarc 
mem_scope(envlist)733*35157Smarc void mem_scope(envlist)
734*35157Smarc ARGPTR envlist;
735*35157Smarc {
736*35157Smarc 	register struct Amemory *sav_namep = namep;
737*35157Smarc 	register struct Amemory *newscope;
738*35157Smarc 	newscope = gettree(MEMSIZE/8);
739*35157Smarc 	newscope->nexttree = sav_namep;
740*35157Smarc 	namep = newscope;
741*35157Smarc 	setlist(envlist,N_EXPORT|S_FLAG);
742*35157Smarc 	newscope->nexttree = NULL;
743*35157Smarc 	namep = sav_namep;
744*35157Smarc 	scan_all(no_export,newscope);
745*35157Smarc 	newscope->nexttree = sav_namep;
746*35157Smarc 	namep = newscope;
747*35157Smarc }
748*35157Smarc 
749*35157Smarc /*
750*35157Smarc  * Temporarily remove name from export list of previous scopes
751*35157Smarc  */
752*35157Smarc 
no_export(nnod)753*35157Smarc static void no_export(nnod)
754*35157Smarc register struct Namnod *nnod;
755*35157Smarc {
756*35157Smarc 	register struct Namnod *np = checkfor(nnod->namid,namep);
757*35157Smarc 	if(np && attest(np,N_EXPORT))
758*35157Smarc 	{
759*35157Smarc 		pattrib(np,~N_EXPORT);
760*35157Smarc 		attrib(np,E_FLAG);
761*35157Smarc 	}
762*35157Smarc }
763*35157Smarc 
764*35157Smarc /*
765*35157Smarc  * free up top environment scope
766*35157Smarc  */
767*35157Smarc 
mem_unscope()768*35157Smarc void mem_unscope()
769*35157Smarc {
770*35157Smarc 	register struct Amemory *ap = namep;
771*35157Smarc 	if((namep = ap->nexttree)==NULL)
772*35157Smarc 		namep = namebase;
773*35157Smarc 	scan_all(rm_node,ap);
774*35157Smarc 	free((char*)ap);
775*35157Smarc }
776*35157Smarc 
777*35157Smarc /*
778*35157Smarc  * free up all environment scopes except the first
779*35157Smarc  */
780*35157Smarc 
name_unscope()781*35157Smarc void name_unscope()
782*35157Smarc {
783*35157Smarc 	while(namep->nexttree)
784*35157Smarc 		mem_unscope();
785*35157Smarc }
786*35157Smarc 
787*35157Smarc /*
788*35157Smarc  * Remove a node and free up all the space
789*35157Smarc  * Restate export attribute for hidden nodes if necessary
790*35157Smarc  */
rm_node(nnod)791*35157Smarc static void rm_node(nnod)
792*35157Smarc register struct Namnod *nnod;
793*35157Smarc {
794*35157Smarc 	register struct Namnod *np = checkfor(nnod->namid,namep);
795*35157Smarc 	if(np && attest(np,E_FLAG))
796*35157Smarc 	{
797*35157Smarc 		pattrib(np,~E_FLAG);
798*35157Smarc 		attrib(np,N_EXPORT);
799*35157Smarc 	}
800*35157Smarc 	pattrib(nnod,~N_EXPORT);
801*35157Smarc 	rmlocal(nnod);
802*35157Smarc 	free((char*)nnod);
803*35157Smarc }
804*35157Smarc 
805*35157Smarc /*
806*35157Smarc  * Remove freeable local space associated with the namval field
807*35157Smarc  * of nnod. This includes any strings representing the value(s) of the
808*35157Smarc  * node, as well as its dope vector, if it is an array.
809*35157Smarc  */
810*35157Smarc 
rmlocal(nnod)811*35157Smarc void	rmlocal (nnod)
812*35157Smarc register struct Namnod *nnod;
813*35157Smarc {
814*35157Smarc 	register int i;
815*35157Smarc 	register struct Nodval *nv;
816*35157Smarc 	register struct Namaray *ap;
817*35157Smarc 	register union Namval *up = &nnod->value.namval;
818*35157Smarc 
819*35157Smarc 	/* return if the node is global or unfreeable */
820*35157Smarc 
821*35157Smarc 	if (attest (nnod, N_EXPORT|N_FREE))
822*35157Smarc 		return;
823*35157Smarc 	/*
824*35157Smarc 	 * If the node is a freeable array, then free both the stringspace
825*35157Smarc 	 * associated with it and its dope vector.
826*35157Smarc 	 */
827*35157Smarc 
828*35157Smarc 	else if (attest (nnod, ARRAY))
829*35157Smarc 	{
830*35157Smarc 	        ap = up->aray;
831*35157Smarc 		i = ap->maxi;
832*35157Smarc 		while(i >= 0)
833*35157Smarc 		{
834*35157Smarc 			nv = ap->val[i--];
835*35157Smarc 			if (nv)
836*35157Smarc 			{
837*35157Smarc 	                	if (freeble (nv))
838*35157Smarc 					rmnval (unmark (nv));
839*35157Smarc 				else
840*35157Smarc 				{
841*35157Smarc 					up = &nv->namval;
842*35157Smarc 					if ((up->cp) && ((nv->namflg & (N_FREE|N_ALLOC)) == 0))
843*35157Smarc 						free ((nv->namflg & IN_DIR)?up->up->cp:up->cp);
844*35157Smarc 				}
845*35157Smarc 			}
846*35157Smarc 		}
847*35157Smarc 		free ((char*)(arayp(nnod)));
848*35157Smarc 		nnod->value.namval.cp = NULL;
849*35157Smarc 	}
850*35157Smarc 	/*
851*35157Smarc 	 * otherwise node is a freeable scalar, so free the string
852*35157Smarc 	 * representing its value.
853*35157Smarc 	 */
854*35157Smarc 	else
855*35157Smarc 	{
856*35157Smarc 		unassign (nnod);
857*35157Smarc 	}
858*35157Smarc 	sattrib (nnod, N_DEFAULT);
859*35157Smarc }
860*35157Smarc 
861*35157Smarc /*
862*35157Smarc  * Get the value of a built-in node
863*35157Smarc  * A lookup may not be necessary
864*35157Smarc  */
865*35157Smarc 
qvalup(n)866*35157Smarc char *qvalup(n)
867*35157Smarc register NAMPTR	n;
868*35157Smarc {
869*35157Smarc 	if(namep->nexttree)
870*35157Smarc 		n = lookup((node_names+(n-bltin_nodes))->nv_name);
871*35157Smarc 	return(valup(n));
872*35157Smarc }
873*35157Smarc 
874*35157Smarc /*
875*35157Smarc  * lookup name in trees root and return Namnod pointer with this name.
876*35157Smarc  * If none exists, it will not be created.
877*35157Smarc  */
878*35157Smarc 
checkfor(name,root)879*35157Smarc NAMPTR checkfor(name,root)
880*35157Smarc char *name;
881*35157Smarc struct Amemory *root;
882*35157Smarc {
883*35157Smarc 	register struct Namnod *np = NULL;
884*35157Smarc 	register struct Amemory *app = root;
885*35157Smarc 	struct Namnod *findnod();
886*35157Smarc 	while(app && np==NULL)
887*35157Smarc 	{
888*35157Smarc 		np = findnod(name,app,0);
889*35157Smarc 		app = app->nexttree;
890*35157Smarc 	}
891*35157Smarc 	return((np==NULL||isnull(np))?NULL:np);
892*35157Smarc }
893*35157Smarc 
894*35157Smarc /*
895*35157Smarc  *  for the whence command
896*35157Smarc  */
897*35157Smarc 
do_whence(com,flag)898*35157Smarc void	do_whence(com,flag)
899*35157Smarc char **com;
900*35157Smarc register int flag;
901*35157Smarc {
902*35157Smarc 	register char *a1;
903*35157Smarc 	register struct Namnod *np;
904*35157Smarc 	register char *cp;
905*35157Smarc 	struct Namnod *fp;
906*35157Smarc 	while(a1 = *++com)
907*35157Smarc 	{
908*35157Smarc 		if(flag)
909*35157Smarc 			fputs(a1,output);
910*35157Smarc 		np = NULL;
911*35157Smarc 		/* reserved words first */
912*35157Smarc 		if(syslook(a1,reserved))
913*35157Smarc 		{
914*35157Smarc 			if(flag)
915*35157Smarc 				a1 = is_reserved;
916*35157Smarc 		}
917*35157Smarc 		/* non-tracked aliases */
918*35157Smarc 		else if((np=findnod(a1,alias,CHK_FOR)) && !isnull(np)
919*35157Smarc 			 && attest(np,T_FLAG)==0 && (a1=valup(np)))
920*35157Smarc 		{
921*35157Smarc 			if(flag)
922*35157Smarc 			{
923*35157Smarc 				if(attest(np,N_EXPORT))
924*35157Smarc 					cp = is_xalias;
925*35157Smarc 				else
926*35157Smarc 					cp = is_alias;
927*35157Smarc 				fputs(cp,output);
928*35157Smarc 			}
929*35157Smarc 		}
930*35157Smarc 		/* built-in commands next */
931*35157Smarc 		else if(syslook(a1,commands))
932*35157Smarc 		{
933*35157Smarc 			if(flag)
934*35157Smarc 				a1 = is_builtin;
935*35157Smarc 		}
936*35157Smarc 		/* functions next */
937*35157Smarc 		else if((fp=findnod(a1,prnames,CHK_FOR))&& !isnull(fp))
938*35157Smarc 		{
939*35157Smarc 			if(flag)
940*35157Smarc 		 		a1=attest(fp,N_EXPORT)?is_xfunction:is_function;
941*35157Smarc 		}
942*35157Smarc 		else
943*35157Smarc 		{
944*35157Smarc 			/* find full pathname */
945*35157Smarc 			a1 = fullname(a1);
946*35157Smarc 			if(a1)
947*35157Smarc 			{
948*35157Smarc 				if(flag)
949*35157Smarc 				{
950*35157Smarc 					/* tracked aliases next */
951*35157Smarc 					if(np && attest(np,T_FLAG) && *a1 == '/')
952*35157Smarc 						fputs(is_talias,output);
953*35157Smarc 					else
954*35157Smarc 						fputs(is_,output);
955*35157Smarc 				}
956*35157Smarc 			}
957*35157Smarc 			else
958*35157Smarc 			{
959*35157Smarc 				a1 = (flag?notfound:nullstr);
960*35157Smarc 				exitval |= 1;
961*35157Smarc 			}
962*35157Smarc 		}
963*35157Smarc 		p_str(a1,NL);
964*35157Smarc 	}
965*35157Smarc }
966*35157Smarc 
967*35157Smarc /*
968*35157Smarc  * these functions are used to get and set the SECONDS variable
969*35157Smarc  */
970*35157Smarc 
971*35157Smarc static long sec_offset;
972*35157Smarc 
set_second(n)973*35157Smarc static int set_second(n)
974*35157Smarc long n;
975*35157Smarc {
976*35157Smarc 	sec_offset =  time((long*)0) - n ;
977*35157Smarc }
978*35157Smarc 
get_second()979*35157Smarc static long get_second()
980*35157Smarc {
981*35157Smarc 	return(time((long*)0)-sec_offset);
982*35157Smarc }
983*35157Smarc 
984*35157Smarc /*
985*35157Smarc  * These functions are used to get and set the RANDOM variable
986*35157Smarc  */
987*35157Smarc 
set_rand(n)988*35157Smarc static int set_rand(n)
989*35157Smarc long n;
990*35157Smarc {
991*35157Smarc 	srand((int)n);
992*35157Smarc }
993*35157Smarc 
get_rand()994*35157Smarc static long get_rand()
995*35157Smarc {
996*35157Smarc 	return((long)rand());
997*35157Smarc }
998*35157Smarc 
999*35157Smarc #ifdef ECHO_N
echo_mode()1000*35157Smarc char *echo_mode()
1001*35157Smarc {
1002*35157Smarc 	register char *cp;
1003*35157Smarc 	optflag savopts;
1004*35157Smarc 	if(echo_arg==0)
1005*35157Smarc 	{
1006*35157Smarc #ifdef apollo
1007*35157Smarc 		register NAMPTR np = checkfor("SYSTYPE",namep);
1008*35157Smarc 		if(np && (cp=valup(np)))
1009*35157Smarc 		{
1010*35157Smarc 			echo_arg = (*cp=='b'?echo_opt:minus);
1011*35157Smarc 			return(echo_arg);
1012*35157Smarc 		}
1013*35157Smarc #endif /* apollo */
1014*35157Smarc 		savopts = flags;
1015*35157Smarc 		off_option(HASHALL);
1016*35157Smarc 		cp = fullname(echo_bin+5);
1017*35157Smarc 		flags = savopts;
1018*35157Smarc 		if(eq(cp,echo_bin))
1019*35157Smarc 			echo_arg = echo_opt;
1020*35157Smarc 		else
1021*35157Smarc 			echo_arg = minus;
1022*35157Smarc 	}
1023*35157Smarc 	return(echo_arg);
1024*35157Smarc }
1025*35157Smarc #endif	/* ECHO_N */
1026