xref: /onnv-gate/usr/src/cmd/sh/name.c (revision 9369:4df685ccc8c1)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52256Sna195498  * Common Development and Distribution License (the "License").
62256Sna195498  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate 
220Sstevel@tonic-gate /*
23*9369SNobutomo.Nakano@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
27527Schin /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28527Schin /*	  All Rights Reserved  	*/
29527Schin 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * UNIX shell
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include	"defs.h"
350Sstevel@tonic-gate #include	<stropts.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate extern BOOL	chkid();
380Sstevel@tonic-gate extern unsigned char	*simple();
390Sstevel@tonic-gate extern int	mailchk;
400Sstevel@tonic-gate 
41527Schin static void	setname(unsigned char *, int);
420Sstevel@tonic-gate static void	set_builtins_path();
430Sstevel@tonic-gate static int	patheq();
44527Schin static void	namwalk(struct namnod *);
45527Schin static void	dolocale();
460Sstevel@tonic-gate 
470Sstevel@tonic-gate struct namnod ps2nod =
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	(struct namnod *)NIL,
500Sstevel@tonic-gate 	&acctnod,
510Sstevel@tonic-gate 	(unsigned char *)ps2name
520Sstevel@tonic-gate };
530Sstevel@tonic-gate struct namnod cdpnod =
540Sstevel@tonic-gate {
550Sstevel@tonic-gate 	(struct namnod *)NIL,
560Sstevel@tonic-gate 	(struct namnod *)NIL,
570Sstevel@tonic-gate 	(unsigned char *)cdpname
580Sstevel@tonic-gate };
590Sstevel@tonic-gate struct namnod pathnod =
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	&mailpnod,
620Sstevel@tonic-gate 	(struct namnod *)NIL,
630Sstevel@tonic-gate 	(unsigned char *)pathname
640Sstevel@tonic-gate };
650Sstevel@tonic-gate struct namnod ifsnod =
660Sstevel@tonic-gate {
670Sstevel@tonic-gate 	&homenod,
680Sstevel@tonic-gate 	&mailnod,
690Sstevel@tonic-gate 	(unsigned char *)ifsname
700Sstevel@tonic-gate };
710Sstevel@tonic-gate struct namnod ps1nod =
720Sstevel@tonic-gate {
730Sstevel@tonic-gate 	&pathnod,
740Sstevel@tonic-gate 	&ps2nod,
750Sstevel@tonic-gate 	(unsigned char *)ps1name
760Sstevel@tonic-gate };
770Sstevel@tonic-gate struct namnod homenod =
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	&cdpnod,
800Sstevel@tonic-gate 	(struct namnod *)NIL,
810Sstevel@tonic-gate 	(unsigned char *)homename
820Sstevel@tonic-gate };
830Sstevel@tonic-gate struct namnod mailnod =
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 	(struct namnod *)NIL,
860Sstevel@tonic-gate 	(struct namnod *)NIL,
870Sstevel@tonic-gate 	(unsigned char *)mailname
880Sstevel@tonic-gate };
890Sstevel@tonic-gate struct namnod mchknod =
900Sstevel@tonic-gate {
910Sstevel@tonic-gate 	&ifsnod,
920Sstevel@tonic-gate 	&ps1nod,
930Sstevel@tonic-gate 	(unsigned char *)mchkname
940Sstevel@tonic-gate };
950Sstevel@tonic-gate struct namnod acctnod =
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	(struct namnod *)NIL,
980Sstevel@tonic-gate 	(struct namnod *)NIL,
990Sstevel@tonic-gate 	(unsigned char *)acctname
1000Sstevel@tonic-gate };
1010Sstevel@tonic-gate struct namnod mailpnod =
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate 	(struct namnod *)NIL,
1040Sstevel@tonic-gate 	(struct namnod *)NIL,
1050Sstevel@tonic-gate 	(unsigned char *)mailpname
1060Sstevel@tonic-gate };
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate struct namnod *namep = &mchknod;
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate /* ========	variable and string handling	======== */
1120Sstevel@tonic-gate 
113527Schin int
syslook(unsigned char * w,struct sysnod syswds[],int n)114527Schin syslook(unsigned char *w, struct sysnod syswds[], int n)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	int	low;
1170Sstevel@tonic-gate 	int	high;
1180Sstevel@tonic-gate 	int	mid;
119527Schin 	int	cond;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	if (w == 0 || *w == 0)
1220Sstevel@tonic-gate 		return(0);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	low = 0;
1250Sstevel@tonic-gate 	high = n - 1;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	while (low <= high)
1280Sstevel@tonic-gate 	{
1290Sstevel@tonic-gate 		mid = (low + high) / 2;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 		if ((cond = cf(w, syswds[mid].sysnam)) < 0)
1320Sstevel@tonic-gate 			high = mid - 1;
1330Sstevel@tonic-gate 		else if (cond > 0)
1340Sstevel@tonic-gate 			low = mid + 1;
1350Sstevel@tonic-gate 		else
1360Sstevel@tonic-gate 			return(syswds[mid].sysval);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 	return(0);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
141527Schin void
setlist(struct argnod * arg,int xp)142527Schin setlist(struct argnod *arg, int xp)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate 	if (flags & exportflg)
1450Sstevel@tonic-gate 		xp |= N_EXPORT;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	while (arg)
1480Sstevel@tonic-gate 	{
149527Schin 		unsigned char *s = mactrim(arg->argval);
1500Sstevel@tonic-gate 		setname(s, xp);
1510Sstevel@tonic-gate 		arg = arg->argnxt;
1520Sstevel@tonic-gate 		if (flags & execpr)
1530Sstevel@tonic-gate 		{
1540Sstevel@tonic-gate 			prs(s);
1550Sstevel@tonic-gate 			if (arg)
1560Sstevel@tonic-gate 				blank();
1570Sstevel@tonic-gate 			else
1580Sstevel@tonic-gate 				newline();
1590Sstevel@tonic-gate 		}
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
163527Schin static void
setname(unsigned char * argi,int xp)164527Schin setname(unsigned char *argi, int xp)	/* does parameter assignments */
1650Sstevel@tonic-gate {
166527Schin 	unsigned char *argscan = argi;
167527Schin 	struct namnod *n;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (letter(*argscan))
1700Sstevel@tonic-gate 	{
1710Sstevel@tonic-gate 		while (alphanum(*argscan))
1720Sstevel@tonic-gate 			argscan++;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 		if (*argscan == '=')
1750Sstevel@tonic-gate 		{
1760Sstevel@tonic-gate 			*argscan = 0;	/* make name a cohesive string */
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 			n = lookup(argi);
1790Sstevel@tonic-gate 			*argscan++ = '=';
1800Sstevel@tonic-gate 			attrib(n, xp);
1810Sstevel@tonic-gate 			if (xp & N_ENVNAM)
1820Sstevel@tonic-gate 			{
1830Sstevel@tonic-gate 				n->namenv = n->namval = argscan;
1840Sstevel@tonic-gate 				if (n == &pathnod)
1850Sstevel@tonic-gate 					set_builtins_path();
1860Sstevel@tonic-gate 			}
1870Sstevel@tonic-gate 			else
1880Sstevel@tonic-gate 				assign(n, argscan);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 			dolocale(n->namid);
1910Sstevel@tonic-gate 			return;
1920Sstevel@tonic-gate 		}
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
196527Schin void
replace(unsigned char ** a,unsigned char * v)197527Schin replace(unsigned char **a, unsigned char *v)
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate 	free(*a);
2000Sstevel@tonic-gate 	*a = make(v);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
203527Schin void
dfault(struct namnod * n,unsigned char * v)204527Schin dfault(struct namnod *n, unsigned char	*v)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate 	if (n->namval == 0)
2070Sstevel@tonic-gate 		assign(n, v);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
210527Schin void
assign(struct namnod * n,unsigned char * v)211527Schin assign(struct namnod *n, unsigned char *v)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate 	if (n->namflg & N_RDONLY)
2140Sstevel@tonic-gate 		failed(n->namid, wtfailed);
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate #ifndef RES
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	else if (flags & rshflg)
2190Sstevel@tonic-gate 	{
2200Sstevel@tonic-gate 		if (n == &pathnod || eq(n->namid,"SHELL"))
2210Sstevel@tonic-gate 			failed(n->namid, restricted);
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate #endif
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	else if (n->namflg & N_FUNCTN)
2260Sstevel@tonic-gate 	{
2270Sstevel@tonic-gate 		func_unhash(n->namid);
2280Sstevel@tonic-gate 		freefunc(n);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 		n->namenv = 0;
2310Sstevel@tonic-gate 		n->namflg = N_DEFAULT;
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if (n == &mchknod)
2350Sstevel@tonic-gate 	{
2360Sstevel@tonic-gate 		mailchk = stoi(v);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	replace(&n->namval, v);
2400Sstevel@tonic-gate 	attrib(n, N_ENVCHG);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	if (n == &pathnod)
2430Sstevel@tonic-gate 	{
2440Sstevel@tonic-gate 		zaphash();
2450Sstevel@tonic-gate 		set_dotpath();
2460Sstevel@tonic-gate 		set_builtins_path();
2470Sstevel@tonic-gate 		return;
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (flags & prompt)
2510Sstevel@tonic-gate 	{
2520Sstevel@tonic-gate 		if ((n == &mailpnod) || (n == &mailnod && mailpnod.namflg == N_DEFAULT))
2530Sstevel@tonic-gate 			setmail(n->namval);
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate static void
set_builtins_path()2580Sstevel@tonic-gate set_builtins_path()
2590Sstevel@tonic-gate {
260527Schin 	unsigned char *path;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate         ucb_builtins = 0;
2630Sstevel@tonic-gate         path = getpath("");
2640Sstevel@tonic-gate         while (path && *path)
2650Sstevel@tonic-gate         {
2660Sstevel@tonic-gate                 if (patheq(path, "/usr/ucb"))
2670Sstevel@tonic-gate                 {
2680Sstevel@tonic-gate                         ucb_builtins++;
2690Sstevel@tonic-gate                         break;
2700Sstevel@tonic-gate                 }
2710Sstevel@tonic-gate                 else if (patheq(path, "/usr/bin"))
2720Sstevel@tonic-gate                         break;
2730Sstevel@tonic-gate                 else if (patheq(path, "/bin"))
2740Sstevel@tonic-gate                         break;
2750Sstevel@tonic-gate                 else if (patheq(path, "/usr/5bin"))
2760Sstevel@tonic-gate                         break;
2770Sstevel@tonic-gate                 path = nextpath(path);
2780Sstevel@tonic-gate         }
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate static int
patheq(unsigned char * component,char * dir)282527Schin patheq(unsigned char *component, char *dir)
2830Sstevel@tonic-gate {
284527Schin 	unsigned char   c;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate         for (;;)
2870Sstevel@tonic-gate         {
2880Sstevel@tonic-gate                 c = *component++;
2890Sstevel@tonic-gate                 if (c == COLON)
2900Sstevel@tonic-gate                         c = '\0';       /* end of component of path */
291527Schin 		if (c != *dir++)
292527Schin 			return (0);
2930Sstevel@tonic-gate                 if (c == '\0')
2940Sstevel@tonic-gate                         return(1);
2950Sstevel@tonic-gate         }
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
298527Schin int
readvar(unsigned char ** names)299527Schin readvar(unsigned char **names)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate 	struct fileblk	fb;
302527Schin 	struct fileblk *f = &fb;
3030Sstevel@tonic-gate 	unsigned char	c[MULTI_BYTE_MAX+1];
304527Schin 	int	rc = 0;
3050Sstevel@tonic-gate 	struct namnod *n = lookup(*names++);	/* done now to avoid storage mess */
3060Sstevel@tonic-gate 	unsigned char	*rel = (unsigned char *)relstak();
3070Sstevel@tonic-gate 	unsigned char *oldstak;
308527Schin 	unsigned char *pc, *rest;
3090Sstevel@tonic-gate 	int		d;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	push(f);
3120Sstevel@tonic-gate 	initf(dup(0));
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/*
3150Sstevel@tonic-gate 	 * If stdin is a pipe then this lseek(2) will fail with ESPIPE, so
3160Sstevel@tonic-gate 	 * the read buffer size is set to 1 because we will not be able
3170Sstevel@tonic-gate 	 * lseek(2) back towards the beginning of the file, so we have
3180Sstevel@tonic-gate 	 * to read a byte at a time instead
3190Sstevel@tonic-gate 	 *
3200Sstevel@tonic-gate 	 */
3210Sstevel@tonic-gate 	if (lseek(0, (off_t)0, SEEK_CUR) == -1)
3220Sstevel@tonic-gate 		f->fsiz = 1;
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	/*
3250Sstevel@tonic-gate 	 * If stdin is a socket then this isastream(3C) will return 1, so
3260Sstevel@tonic-gate 	 * the read buffer size is set to 1 because we will not be able
3270Sstevel@tonic-gate 	 * lseek(2) back towards the beginning of the file, so we have
3280Sstevel@tonic-gate 	 * to read a byte at a time instead
3290Sstevel@tonic-gate 	 *
3300Sstevel@tonic-gate 	 */
3310Sstevel@tonic-gate 	if (isastream(0) == 1)
3320Sstevel@tonic-gate 		f->fsiz = 1;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/*
3350Sstevel@tonic-gate 	 * strip leading IFS characters
3360Sstevel@tonic-gate 	 */
3370Sstevel@tonic-gate 	for (;;)
3380Sstevel@tonic-gate 	{
3390Sstevel@tonic-gate 		d = nextwc();
3400Sstevel@tonic-gate 		if(eolchar(d))
3410Sstevel@tonic-gate 			break;
3420Sstevel@tonic-gate 		rest = readw(d);
3430Sstevel@tonic-gate 		pc = c;
3440Sstevel@tonic-gate 		while(*pc++ = *rest++);
3450Sstevel@tonic-gate 		if(!anys(c, ifsnod.namval))
3460Sstevel@tonic-gate 			break;
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	oldstak = curstak();
3500Sstevel@tonic-gate 	for (;;)
3510Sstevel@tonic-gate 	{
3520Sstevel@tonic-gate 		if ((*names && anys(c, ifsnod.namval)) || eolchar(d))
3530Sstevel@tonic-gate 		{
3540Sstevel@tonic-gate 			if (staktop >= brkend)
3550Sstevel@tonic-gate 				growstak(staktop);
3560Sstevel@tonic-gate 			zerostak();
3570Sstevel@tonic-gate 			assign(n, absstak(rel));
3580Sstevel@tonic-gate 			setstak(rel);
3590Sstevel@tonic-gate 			if (*names)
3600Sstevel@tonic-gate 				n = lookup(*names++);
3610Sstevel@tonic-gate 			else
3620Sstevel@tonic-gate 				n = 0;
3630Sstevel@tonic-gate 			if (eolchar(d))
3640Sstevel@tonic-gate 			{
3650Sstevel@tonic-gate 				break;
3660Sstevel@tonic-gate 			}
3670Sstevel@tonic-gate 			else		/* strip imbedded IFS characters */
3680Sstevel@tonic-gate 				while(1) {
3690Sstevel@tonic-gate 					d = nextwc();
3700Sstevel@tonic-gate 					if(eolchar(d))
3710Sstevel@tonic-gate 						break;
3720Sstevel@tonic-gate 					rest = readw(d);
3730Sstevel@tonic-gate 					pc = c;
3740Sstevel@tonic-gate 					while(*pc++ = *rest++);
3750Sstevel@tonic-gate 					if(!anys(c, ifsnod.namval))
3760Sstevel@tonic-gate 						break;
3770Sstevel@tonic-gate 				}
3780Sstevel@tonic-gate 		}
3790Sstevel@tonic-gate 		else
3800Sstevel@tonic-gate 		{
3810Sstevel@tonic-gate 			if(d == '\\') {
3820Sstevel@tonic-gate 				d = readwc();
3830Sstevel@tonic-gate 				rest = readw(d);
3840Sstevel@tonic-gate 				while(d = *rest++) {
3850Sstevel@tonic-gate 					if (staktop >= brkend)
3860Sstevel@tonic-gate 						growstak(staktop);
3870Sstevel@tonic-gate 					pushstak(d);
3880Sstevel@tonic-gate 				}
3890Sstevel@tonic-gate 				oldstak = staktop;
3900Sstevel@tonic-gate 			}
3910Sstevel@tonic-gate 			else
3920Sstevel@tonic-gate 			{
3930Sstevel@tonic-gate 				pc = c;
3940Sstevel@tonic-gate 				while(d = *pc++) {
3950Sstevel@tonic-gate 					if (staktop >= brkend)
3960Sstevel@tonic-gate 						growstak(staktop);
3970Sstevel@tonic-gate 					pushstak(d);
3980Sstevel@tonic-gate 				}
3990Sstevel@tonic-gate 				if(!anys(c, ifsnod.namval))
4000Sstevel@tonic-gate 					oldstak = staktop;
4010Sstevel@tonic-gate 			}
4020Sstevel@tonic-gate 			d = nextwc();
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 			if (eolchar(d))
4050Sstevel@tonic-gate 				staktop = oldstak;
4060Sstevel@tonic-gate 			else
4070Sstevel@tonic-gate 			{
4080Sstevel@tonic-gate 				rest = readw(d);
4090Sstevel@tonic-gate 				pc = c;
4100Sstevel@tonic-gate 				while(*pc++ = *rest++);
4110Sstevel@tonic-gate 			}
4120Sstevel@tonic-gate 		}
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 	while (n)
4150Sstevel@tonic-gate 	{
416527Schin 		assign(n, (unsigned char *)nullstr);
4170Sstevel@tonic-gate 		if (*names)
4180Sstevel@tonic-gate 			n = lookup(*names++);
4190Sstevel@tonic-gate 		else
4200Sstevel@tonic-gate 			n = 0;
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	if (eof)
4240Sstevel@tonic-gate 		rc = 1;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	if (isastream(0) != 1)
4270Sstevel@tonic-gate 		/*
4280Sstevel@tonic-gate 		 * If we are reading on a stream do not attempt to
4290Sstevel@tonic-gate 		 * lseek(2) back towards the start because this is
4300Sstevel@tonic-gate 		 * logically meaningless, but there is nothing in
4310Sstevel@tonic-gate 		 * the standards to pervent the stream implementation
4320Sstevel@tonic-gate 		 * from attempting it and breaking our code here
4330Sstevel@tonic-gate 		 *
4340Sstevel@tonic-gate 		 */
4350Sstevel@tonic-gate 		lseek(0, (off_t)(f->nxtoff - f->endoff), SEEK_CUR);
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	pop();
4380Sstevel@tonic-gate 	return(rc);
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate 
441527Schin void
assnum(unsigned char ** p,long i)442527Schin assnum(unsigned char **p, long i)
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate 	int j = ltos(i);
4450Sstevel@tonic-gate 	replace(p, &numbuf[j]);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate unsigned char *
make(v)4490Sstevel@tonic-gate make(v)
4500Sstevel@tonic-gate unsigned char	*v;
4510Sstevel@tonic-gate {
452527Schin 	unsigned char	*p;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	if (v)
4550Sstevel@tonic-gate 	{
4560Sstevel@tonic-gate 		movstr(v, p = (unsigned char *)alloc(length(v)));
4570Sstevel@tonic-gate 		return(p);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 	else
4600Sstevel@tonic-gate 		return(0);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate struct namnod *
lookup(unsigned char * nam)465527Schin lookup(unsigned char *nam)
4660Sstevel@tonic-gate {
467527Schin 	struct namnod *nscan = namep;
468527Schin 	struct namnod **prev;
4690Sstevel@tonic-gate 	int		LR;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	if (!chkid(nam))
4720Sstevel@tonic-gate 		failed(nam, notid);
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	while (nscan)
4750Sstevel@tonic-gate 	{
4760Sstevel@tonic-gate 		if ((LR = cf(nam, nscan->namid)) == 0)
4770Sstevel@tonic-gate 			return(nscan);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 		else if (LR < 0)
4800Sstevel@tonic-gate 			prev = &(nscan->namlft);
4810Sstevel@tonic-gate 		else
4820Sstevel@tonic-gate 			prev = &(nscan->namrgt);
4830Sstevel@tonic-gate 		nscan = *prev;
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 	/*
4860Sstevel@tonic-gate 	 * add name node
4870Sstevel@tonic-gate 	 */
4880Sstevel@tonic-gate 	nscan = (struct namnod *)alloc(sizeof *nscan);
4890Sstevel@tonic-gate 	nscan->namlft = nscan->namrgt = (struct namnod *)NIL;
4900Sstevel@tonic-gate 	nscan->namid = make(nam);
4910Sstevel@tonic-gate 	nscan->namval = 0;
4920Sstevel@tonic-gate 	nscan->namflg = N_DEFAULT;
4930Sstevel@tonic-gate 	nscan->namenv = 0;
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	return(*prev = nscan);
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate BOOL
chkid(nam)4990Sstevel@tonic-gate chkid(nam)
5000Sstevel@tonic-gate unsigned char	*nam;
5010Sstevel@tonic-gate {
502527Schin 	unsigned char *cp = nam;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	if (!letter(*cp))
5050Sstevel@tonic-gate 		return(FALSE);
5060Sstevel@tonic-gate 	else
5070Sstevel@tonic-gate 	{
5080Sstevel@tonic-gate 		while (*++cp)
5090Sstevel@tonic-gate 		{
5100Sstevel@tonic-gate 			if (!alphanum(*cp))
5110Sstevel@tonic-gate 				return(FALSE);
5120Sstevel@tonic-gate 		}
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 	return(TRUE);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate 
517527Schin static void (*namfn)();
518527Schin 
519527Schin void
namscan(void (* fn)())520527Schin namscan(void (*fn)())
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate 	namfn = fn;
5230Sstevel@tonic-gate 	namwalk(namep);
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate static void
namwalk(struct namnod * np)527527Schin namwalk(struct namnod *np)
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate 	if (np)
5300Sstevel@tonic-gate 	{
5310Sstevel@tonic-gate 		namwalk(np->namlft);
5320Sstevel@tonic-gate 		(*namfn)(np);
5330Sstevel@tonic-gate 		namwalk(np->namrgt);
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
537527Schin void
printnam(struct namnod * n)538527Schin printnam(struct namnod *n)
5390Sstevel@tonic-gate {
540527Schin 	unsigned char	*s;
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	sigchk();
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	if (n->namflg & N_FUNCTN)
5450Sstevel@tonic-gate 	{
546*9369SNobutomo.Nakano@Sun.COM 		struct fndnod *f = fndptr(n->namenv);
547*9369SNobutomo.Nakano@Sun.COM 
5480Sstevel@tonic-gate 		prs_buff(n->namid);
5490Sstevel@tonic-gate 		prs_buff("(){\n");
550*9369SNobutomo.Nakano@Sun.COM 		if (f != NULL)
551*9369SNobutomo.Nakano@Sun.COM 			prf(f->fndval);
5520Sstevel@tonic-gate 		prs_buff("\n}\n");
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 	else if (s = n->namval)
5550Sstevel@tonic-gate 	{
5560Sstevel@tonic-gate 		prs_buff(n->namid);
5570Sstevel@tonic-gate 		prc_buff('=');
5580Sstevel@tonic-gate 		prs_buff(s);
5590Sstevel@tonic-gate 		prc_buff(NL);
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate static int namec;
5640Sstevel@tonic-gate 
565527Schin void
printro(struct namnod * n)566527Schin printro(struct namnod *n)
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate 	if (n->namflg & N_RDONLY)
5690Sstevel@tonic-gate 	{
5702256Sna195498 		prs_buff(_gettext(readonly));
5710Sstevel@tonic-gate 		prc_buff(SPACE);
5720Sstevel@tonic-gate 		prs_buff(n->namid);
5730Sstevel@tonic-gate 		prc_buff(NL);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate 
577527Schin void
printexp(struct namnod * n)578527Schin printexp(struct namnod *n)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate 	if (n->namflg & N_EXPORT)
5810Sstevel@tonic-gate 	{
5822256Sna195498 		prs_buff(_gettext(export));
5830Sstevel@tonic-gate 		prc_buff(SPACE);
5840Sstevel@tonic-gate 		prs_buff(n->namid);
5850Sstevel@tonic-gate 		prc_buff(NL);
5860Sstevel@tonic-gate 	}
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate 
589527Schin void
setup_env(void)590527Schin setup_env(void)
5910Sstevel@tonic-gate {
592527Schin 	unsigned char **e = environ;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	while (*e)
5950Sstevel@tonic-gate 		setname(*e++, N_ENVNAM);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate static unsigned char **argnam;
6000Sstevel@tonic-gate 
601527Schin static void
countnam(struct namnod * n)602527Schin countnam(struct namnod *n)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	if (n->namval)
6050Sstevel@tonic-gate 		namec++;
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate 
608527Schin static void
pushnam(struct namnod * n)609527Schin pushnam(struct namnod *n)
6100Sstevel@tonic-gate {
611527Schin 	int 	flg = n->namflg;
612527Schin 	unsigned char	*p;
613527Schin 	unsigned char	*namval;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	if (((flg & N_ENVCHG) && (flg & N_EXPORT)) || (flg & N_FUNCTN))
6160Sstevel@tonic-gate 		namval = n->namval;
6170Sstevel@tonic-gate 	else {
6180Sstevel@tonic-gate 		/* Discard Local variable in child process */
6190Sstevel@tonic-gate 		if (!(flg & ~N_ENVCHG)) {
6200Sstevel@tonic-gate 			n->namflg = 0;
6210Sstevel@tonic-gate 			n->namenv = 0;
6220Sstevel@tonic-gate 			if (n->namval) {
6230Sstevel@tonic-gate 				/* Release for re-use */
6240Sstevel@tonic-gate 				free(n->namval);
6250Sstevel@tonic-gate 				n->namval = (unsigned char *)NIL;
6260Sstevel@tonic-gate 			}
6270Sstevel@tonic-gate 		}
6280Sstevel@tonic-gate 		namval = n->namenv;
6290Sstevel@tonic-gate 	}
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	if (namval)
6320Sstevel@tonic-gate 	{
6330Sstevel@tonic-gate 		p = movstrstak(n->namid, staktop);
6340Sstevel@tonic-gate 		p = movstrstak("=", p);
6350Sstevel@tonic-gate 		p = movstrstak(namval, p);
6360Sstevel@tonic-gate 		*argnam++ = getstak(p + 1 - (unsigned char *)(stakbot));
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate unsigned char **
local_setenv()6410Sstevel@tonic-gate local_setenv()
6420Sstevel@tonic-gate {
643527Schin 	unsigned char	**er;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	namec = 0;
6460Sstevel@tonic-gate 	namscan(countnam);
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	argnam = er = (unsigned char **)getstak(namec * BYTESPERWORD + BYTESPERWORD);
6490Sstevel@tonic-gate 	namscan(pushnam);
6500Sstevel@tonic-gate 	*argnam++ = 0;
6510Sstevel@tonic-gate 	return(er);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate struct namnod *
findnam(nam)6550Sstevel@tonic-gate findnam(nam)
656527Schin 	unsigned char	*nam;
6570Sstevel@tonic-gate {
658527Schin 	struct namnod	*nscan = namep;
6590Sstevel@tonic-gate 	int		LR;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	if (!chkid(nam))
6620Sstevel@tonic-gate 		return(0);
6630Sstevel@tonic-gate 	while (nscan)
6640Sstevel@tonic-gate 	{
6650Sstevel@tonic-gate 		if ((LR = cf(nam, nscan->namid)) == 0)
6660Sstevel@tonic-gate 			return(nscan);
6670Sstevel@tonic-gate 		else if (LR < 0)
6680Sstevel@tonic-gate 			nscan = nscan->namlft;
6690Sstevel@tonic-gate 		else
6700Sstevel@tonic-gate 			nscan = nscan->namrgt;
6710Sstevel@tonic-gate 	}
6720Sstevel@tonic-gate 	return(0);
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate 
675527Schin void
unset_name(unsigned char * name)676527Schin unset_name(unsigned char 	*name)
6770Sstevel@tonic-gate {
678527Schin 	struct namnod	*n;
679527Schin 	unsigned char 	call_dolocale = 0;
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	if (n = findnam(name))
6820Sstevel@tonic-gate 	{
6830Sstevel@tonic-gate 		if (n->namflg & N_RDONLY)
6840Sstevel@tonic-gate 			failed(name, wtfailed);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 		if (n == &pathnod ||
6870Sstevel@tonic-gate 		    n == &ifsnod ||
6880Sstevel@tonic-gate 		    n == &ps1nod ||
6890Sstevel@tonic-gate 		    n == &ps2nod ||
6900Sstevel@tonic-gate 		    n == &mchknod)
6910Sstevel@tonic-gate 		{
6920Sstevel@tonic-gate 			failed(name, badunset);
6930Sstevel@tonic-gate 		}
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate #ifndef RES
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 		if ((flags & rshflg) && eq(name, "SHELL"))
6980Sstevel@tonic-gate 			failed(name, restricted);
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate #endif
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 		if (n->namflg & N_FUNCTN)
7030Sstevel@tonic-gate 		{
7040Sstevel@tonic-gate 			func_unhash(name);
7050Sstevel@tonic-gate 			freefunc(n);
7060Sstevel@tonic-gate 		}
7070Sstevel@tonic-gate 		else
7080Sstevel@tonic-gate 		{
7090Sstevel@tonic-gate 			call_dolocale++;
7100Sstevel@tonic-gate 			free(n->namval);
7110Sstevel@tonic-gate 			free(n->namenv);
7120Sstevel@tonic-gate 		}
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 		n->namval = n->namenv = 0;
7150Sstevel@tonic-gate 		n->namflg = N_DEFAULT;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 		if (call_dolocale)
7180Sstevel@tonic-gate 			dolocale(name);
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 		if (flags & prompt)
7210Sstevel@tonic-gate 		{
7220Sstevel@tonic-gate 			if (n == &mailpnod)
7230Sstevel@tonic-gate 				setmail(mailnod.namval);
7240Sstevel@tonic-gate 			else if (n == &mailnod && mailpnod.namflg == N_DEFAULT)
7250Sstevel@tonic-gate 				setmail(0);
7260Sstevel@tonic-gate 		}
7270Sstevel@tonic-gate 	}
7280Sstevel@tonic-gate }
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate /*
7310Sstevel@tonic-gate  * The environment variables which affect locale.
7320Sstevel@tonic-gate  * Note: if all names in this list do not begin with 'L',
7330Sstevel@tonic-gate  * you MUST modify dolocale().  Also, be sure that the
7340Sstevel@tonic-gate  * fake_env has the same number of elements as localevar.
7350Sstevel@tonic-gate  */
7360Sstevel@tonic-gate static char *localevar[] = {
7370Sstevel@tonic-gate 	"LC_ALL",
7380Sstevel@tonic-gate 	"LC_CTYPE",
7390Sstevel@tonic-gate 	"LC_MESSAGES",
7400Sstevel@tonic-gate 	"LANG",
7410Sstevel@tonic-gate 	0
7420Sstevel@tonic-gate };
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate static char *fake_env[] = {
7450Sstevel@tonic-gate 	0,
7460Sstevel@tonic-gate 	0,
7470Sstevel@tonic-gate 	0,
7480Sstevel@tonic-gate 	0,
7490Sstevel@tonic-gate 	0
7500Sstevel@tonic-gate };
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate  * If name is one of several special variables which affect the locale,
7540Sstevel@tonic-gate  * do a setlocale().
7550Sstevel@tonic-gate  */
7560Sstevel@tonic-gate static void
dolocale(nm)7570Sstevel@tonic-gate dolocale(nm)
7580Sstevel@tonic-gate 	char *nm;
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate 	char **real_env;
7610Sstevel@tonic-gate 	struct namnod *n;
7620Sstevel@tonic-gate 	int lv, fe;
7630Sstevel@tonic-gate 	int i;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	/*
7660Sstevel@tonic-gate 	 * Take advantage of fact that names of these vars all start
7670Sstevel@tonic-gate 	 * with 'L' to avoid unnecessary work.
7680Sstevel@tonic-gate 	 * Do locale processing only if /usr is mounted.
7690Sstevel@tonic-gate 	 */
7700Sstevel@tonic-gate 	if ((*nm != 'L') || !localedir_exists ||
7710Sstevel@tonic-gate 	    (!(eq(nm, "LC_ALL") || eq(nm, "LC_CTYPE") ||
7720Sstevel@tonic-gate 	    eq(nm, "LANG") || eq(nm, "LC_MESSAGES"))))
7730Sstevel@tonic-gate 		return;
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	/*
7760Sstevel@tonic-gate 	 * setlocale() has all the smarts built into it, but
7770Sstevel@tonic-gate 	 * it works by examining the environment.  Unfortunately,
7780Sstevel@tonic-gate 	 * when you set an environment variable, the shell does
7790Sstevel@tonic-gate 	 * not modify its own environment; it just remembers that the
7800Sstevel@tonic-gate 	 * variable needs to be exported to any children.  We hack around
7810Sstevel@tonic-gate 	 * this by consing up a fake environment for the use of setlocale()
7820Sstevel@tonic-gate 	 * and substituting it for the real env before calling setlocale().
7830Sstevel@tonic-gate 	 */
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	/*
7860Sstevel@tonic-gate 	 * Build the fake environment.
7870Sstevel@tonic-gate 	 * Look up the value of each of the special environment
7880Sstevel@tonic-gate 	 * variables, and put their value into the fake environment,
7890Sstevel@tonic-gate 	 * if they are exported.
7900Sstevel@tonic-gate 	 */
7910Sstevel@tonic-gate 	for (lv = 0, fe = 0; localevar[lv]; lv++) {
7920Sstevel@tonic-gate 		if ((n = findnam(localevar[lv]))) {
793527Schin 			char *p, *q;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 			if (!n->namval)
7960Sstevel@tonic-gate 				continue;
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 			fake_env[fe++] = p = alloc(length(localevar[lv])
7990Sstevel@tonic-gate 					       + length(n->namval) + 2);
8000Sstevel@tonic-gate 			/* copy name */
8010Sstevel@tonic-gate 			q = localevar[lv];
8020Sstevel@tonic-gate 			while (*q)
8030Sstevel@tonic-gate 				*p++ = *q++;
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 			*p++ = '=';
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 			/* copy value */
8080Sstevel@tonic-gate 			q = (char*)(n->namval);
8090Sstevel@tonic-gate 			while (*q)
8100Sstevel@tonic-gate 				*p++ = *q++;
8110Sstevel@tonic-gate 			*p++ = '\0';
8120Sstevel@tonic-gate 		}
8130Sstevel@tonic-gate 	}
8140Sstevel@tonic-gate 	fake_env[fe] = (char *)0;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	/*
8170Sstevel@tonic-gate 	 * Switch fake env for real and call setlocale().
8180Sstevel@tonic-gate 	 */
8190Sstevel@tonic-gate 	real_env = (char **)environ;
8200Sstevel@tonic-gate 	environ = (unsigned char **)fake_env;
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	if (setlocale(LC_ALL, "") == NULL)
8232256Sna195498 		prs(_gettext(badlocale));
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 	/*
8260Sstevel@tonic-gate 	 * Switch back and tear down the fake env.
8270Sstevel@tonic-gate 	 */
8280Sstevel@tonic-gate 	environ = (unsigned char **)real_env;
8290Sstevel@tonic-gate 	for (i = 0; i < fe; i++) {
8300Sstevel@tonic-gate 		free(fake_env[i]);
8310Sstevel@tonic-gate 		fake_env[i] = (char *)0;
8320Sstevel@tonic-gate 	}
8330Sstevel@tonic-gate }
834