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