8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sh / name.c
blob698d433bec5ba20cf14faa142f9176f22a78d4c0
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * UNIX shell
34 #include "defs.h"
35 #include <stropts.h>
37 extern BOOL chkid();
38 extern unsigned char *simple();
39 extern int mailchk;
41 static void setname(unsigned char *, int);
42 static void set_builtins_path();
43 static int patheq();
44 static void namwalk(struct namnod *);
45 static void dolocale();
47 struct namnod ps2nod =
49 (struct namnod *)NIL,
50 &acctnod,
51 (unsigned char *)ps2name
53 struct namnod cdpnod =
55 (struct namnod *)NIL,
56 (struct namnod *)NIL,
57 (unsigned char *)cdpname
59 struct namnod pathnod =
61 &mailpnod,
62 (struct namnod *)NIL,
63 (unsigned char *)pathname
65 struct namnod ifsnod =
67 &homenod,
68 &mailnod,
69 (unsigned char *)ifsname
71 struct namnod ps1nod =
73 &pathnod,
74 &ps2nod,
75 (unsigned char *)ps1name
77 struct namnod homenod =
79 &cdpnod,
80 (struct namnod *)NIL,
81 (unsigned char *)homename
83 struct namnod mailnod =
85 (struct namnod *)NIL,
86 (struct namnod *)NIL,
87 (unsigned char *)mailname
89 struct namnod mchknod =
91 &ifsnod,
92 &ps1nod,
93 (unsigned char *)mchkname
95 struct namnod acctnod =
97 (struct namnod *)NIL,
98 (struct namnod *)NIL,
99 (unsigned char *)acctname
101 struct namnod mailpnod =
103 (struct namnod *)NIL,
104 (struct namnod *)NIL,
105 (unsigned char *)mailpname
109 struct namnod *namep = &mchknod;
111 /* ======== variable and string handling ======== */
114 syslook(unsigned char *w, struct sysnod syswds[], int n)
116 int low;
117 int high;
118 int mid;
119 int cond;
121 if (w == 0 || *w == 0)
122 return(0);
124 low = 0;
125 high = n - 1;
127 while (low <= high)
129 mid = (low + high) / 2;
131 if ((cond = cf(w, syswds[mid].sysnam)) < 0)
132 high = mid - 1;
133 else if (cond > 0)
134 low = mid + 1;
135 else
136 return(syswds[mid].sysval);
138 return(0);
141 void
142 setlist(struct argnod *arg, int xp)
144 if (flags & exportflg)
145 xp |= N_EXPORT;
147 while (arg)
149 unsigned char *s = mactrim(arg->argval);
150 setname(s, xp);
151 arg = arg->argnxt;
152 if (flags & execpr)
154 prs(s);
155 if (arg)
156 blank();
157 else
158 newline();
163 static void
164 setname(unsigned char *argi, int xp) /* does parameter assignments */
166 unsigned char *argscan = argi;
167 struct namnod *n;
169 if (letter(*argscan))
171 while (alphanum(*argscan))
172 argscan++;
174 if (*argscan == '=')
176 *argscan = 0; /* make name a cohesive string */
178 n = lookup(argi);
179 *argscan++ = '=';
180 attrib(n, xp);
181 if (xp & N_ENVNAM)
183 n->namenv = n->namval = argscan;
184 if (n == &pathnod)
185 set_builtins_path();
187 else
188 assign(n, argscan);
190 dolocale(n->namid);
191 return;
196 void
197 replace(unsigned char **a, unsigned char *v)
199 free(*a);
200 *a = make(v);
203 void
204 dfault(struct namnod *n, unsigned char *v)
206 if (n->namval == 0)
207 assign(n, v);
210 void
211 assign(struct namnod *n, unsigned char *v)
213 if (n->namflg & N_RDONLY)
214 failed(n->namid, wtfailed);
216 #ifndef RES
218 else if (flags & rshflg)
220 if (n == &pathnod || eq(n->namid,"SHELL"))
221 failed(n->namid, restricted);
223 #endif
225 else if (n->namflg & N_FUNCTN)
227 func_unhash(n->namid);
228 freefunc(n);
230 n->namenv = 0;
231 n->namflg = N_DEFAULT;
234 if (n == &mchknod)
236 mailchk = stoi(v);
239 replace(&n->namval, v);
240 attrib(n, N_ENVCHG);
242 if (n == &pathnod)
244 zaphash();
245 set_dotpath();
246 set_builtins_path();
247 return;
250 if (flags & prompt)
252 if ((n == &mailpnod) || (n == &mailnod && mailpnod.namflg == N_DEFAULT))
253 setmail(n->namval);
257 static void
258 set_builtins_path()
260 unsigned char *path;
262 ucb_builtins = 0;
263 path = getpath("");
264 while (path && *path)
266 if (patheq(path, "/usr/ucb"))
268 ucb_builtins++;
269 break;
271 else if (patheq(path, "/usr/bin"))
272 break;
273 else if (patheq(path, "/bin"))
274 break;
275 else if (patheq(path, "/usr/5bin"))
276 break;
277 path = nextpath(path);
281 static int
282 patheq(unsigned char *component, char *dir)
284 unsigned char c;
286 for (;;)
288 c = *component++;
289 if (c == COLON)
290 c = '\0'; /* end of component of path */
291 if (c != *dir++)
292 return (0);
293 if (c == '\0')
294 return(1);
299 readvar(unsigned char **names)
301 struct fileblk fb;
302 struct fileblk *f = &fb;
303 unsigned char c[MULTI_BYTE_MAX+1];
304 int rc = 0;
305 struct namnod *n = lookup(*names++); /* done now to avoid storage mess */
306 unsigned char *rel = (unsigned char *)relstak();
307 unsigned char *oldstak;
308 unsigned char *pc, *rest;
309 int d;
311 push(f);
312 initf(dup(0));
315 * If stdin is a pipe then this lseek(2) will fail with ESPIPE, so
316 * the read buffer size is set to 1 because we will not be able
317 * lseek(2) back towards the beginning of the file, so we have
318 * to read a byte at a time instead
321 if (lseek(0, (off_t)0, SEEK_CUR) == -1)
322 f->fsiz = 1;
325 * If stdin is a socket then this isastream(3C) will return 1, so
326 * the read buffer size is set to 1 because we will not be able
327 * lseek(2) back towards the beginning of the file, so we have
328 * to read a byte at a time instead
331 if (isastream(0) == 1)
332 f->fsiz = 1;
335 * strip leading IFS characters
337 for (;;)
339 d = nextwc();
340 if(eolchar(d))
341 break;
342 rest = readw(d);
343 pc = c;
344 while(*pc++ = *rest++);
345 if(!anys(c, ifsnod.namval))
346 break;
349 oldstak = curstak();
350 for (;;)
352 if ((*names && anys(c, ifsnod.namval)) || eolchar(d))
354 if (staktop >= brkend)
355 growstak(staktop);
356 zerostak();
357 assign(n, absstak(rel));
358 setstak(rel);
359 if (*names)
360 n = lookup(*names++);
361 else
362 n = 0;
363 if (eolchar(d))
365 break;
367 else /* strip imbedded IFS characters */
368 while(1) {
369 d = nextwc();
370 if(eolchar(d))
371 break;
372 rest = readw(d);
373 pc = c;
374 while(*pc++ = *rest++);
375 if(!anys(c, ifsnod.namval))
376 break;
379 else
381 if(d == '\\') {
382 d = readwc();
383 rest = readw(d);
384 while(d = *rest++) {
385 if (staktop >= brkend)
386 growstak(staktop);
387 pushstak(d);
389 oldstak = staktop;
391 else
393 pc = c;
394 while(d = *pc++) {
395 if (staktop >= brkend)
396 growstak(staktop);
397 pushstak(d);
399 if(!anys(c, ifsnod.namval))
400 oldstak = staktop;
402 d = nextwc();
404 if (eolchar(d))
405 staktop = oldstak;
406 else
408 rest = readw(d);
409 pc = c;
410 while(*pc++ = *rest++);
414 while (n)
416 assign(n, (unsigned char *)nullstr);
417 if (*names)
418 n = lookup(*names++);
419 else
420 n = 0;
423 if (eof)
424 rc = 1;
426 if (isastream(0) != 1)
428 * If we are reading on a stream do not attempt to
429 * lseek(2) back towards the start because this is
430 * logically meaningless, but there is nothing in
431 * the standards to pervent the stream implementation
432 * from attempting it and breaking our code here
435 lseek(0, (off_t)(f->nxtoff - f->endoff), SEEK_CUR);
437 pop();
438 return(rc);
441 void
442 assnum(unsigned char **p, long i)
444 int j = ltos(i);
445 replace(p, &numbuf[j]);
448 unsigned char *
449 make(v)
450 unsigned char *v;
452 unsigned char *p;
454 if (v)
456 movstr(v, p = (unsigned char *)alloc(length(v)));
457 return(p);
459 else
460 return(0);
464 struct namnod *
465 lookup(unsigned char *nam)
467 struct namnod *nscan = namep;
468 struct namnod **prev;
469 int LR;
471 if (!chkid(nam))
472 failed(nam, notid);
474 while (nscan)
476 if ((LR = cf(nam, nscan->namid)) == 0)
477 return(nscan);
479 else if (LR < 0)
480 prev = &(nscan->namlft);
481 else
482 prev = &(nscan->namrgt);
483 nscan = *prev;
486 * add name node
488 nscan = (struct namnod *)alloc(sizeof *nscan);
489 nscan->namlft = nscan->namrgt = (struct namnod *)NIL;
490 nscan->namid = make(nam);
491 nscan->namval = 0;
492 nscan->namflg = N_DEFAULT;
493 nscan->namenv = 0;
495 return(*prev = nscan);
498 BOOL
499 chkid(nam)
500 unsigned char *nam;
502 unsigned char *cp = nam;
504 if (!letter(*cp))
505 return(FALSE);
506 else
508 while (*++cp)
510 if (!alphanum(*cp))
511 return(FALSE);
514 return(TRUE);
517 static void (*namfn)();
519 void
520 namscan(void (*fn)())
522 namfn = fn;
523 namwalk(namep);
526 static void
527 namwalk(struct namnod *np)
529 if (np)
531 namwalk(np->namlft);
532 (*namfn)(np);
533 namwalk(np->namrgt);
537 void
538 printnam(struct namnod *n)
540 unsigned char *s;
542 sigchk();
544 if (n->namflg & N_FUNCTN)
546 struct fndnod *f = fndptr(n->namenv);
548 prs_buff(n->namid);
549 prs_buff("(){\n");
550 if (f != NULL)
551 prf(f->fndval);
552 prs_buff("\n}\n");
554 else if (s = n->namval)
556 prs_buff(n->namid);
557 prc_buff('=');
558 prs_buff(s);
559 prc_buff(NL);
563 static int namec;
565 void
566 printro(struct namnod *n)
568 if (n->namflg & N_RDONLY)
570 prs_buff(_gettext(readonly));
571 prc_buff(SPACE);
572 prs_buff(n->namid);
573 prc_buff(NL);
577 void
578 printexp(struct namnod *n)
580 if (n->namflg & N_EXPORT)
582 prs_buff(_gettext(export));
583 prc_buff(SPACE);
584 prs_buff(n->namid);
585 prc_buff(NL);
589 void
590 setup_env(void)
592 unsigned char **e = environ;
594 while (*e)
595 setname(*e++, N_ENVNAM);
599 static unsigned char **argnam;
601 static void
602 countnam(struct namnod *n)
604 if (n->namval)
605 namec++;
608 static void
609 pushnam(struct namnod *n)
611 int flg = n->namflg;
612 unsigned char *p;
613 unsigned char *namval;
615 if (((flg & N_ENVCHG) && (flg & N_EXPORT)) || (flg & N_FUNCTN))
616 namval = n->namval;
617 else {
618 /* Discard Local variable in child process */
619 if (!(flg & ~N_ENVCHG)) {
620 n->namflg = 0;
621 n->namenv = 0;
622 if (n->namval) {
623 /* Release for re-use */
624 free(n->namval);
625 n->namval = (unsigned char *)NIL;
628 namval = n->namenv;
631 if (namval)
633 p = movstrstak(n->namid, staktop);
634 p = movstrstak("=", p);
635 p = movstrstak(namval, p);
636 *argnam++ = getstak(p + 1 - (unsigned char *)(stakbot));
640 unsigned char **
641 local_setenv()
643 unsigned char **er;
645 namec = 0;
646 namscan(countnam);
648 argnam = er = (unsigned char **)getstak(namec * BYTESPERWORD + BYTESPERWORD);
649 namscan(pushnam);
650 *argnam++ = 0;
651 return(er);
654 struct namnod *
655 findnam(nam)
656 unsigned char *nam;
658 struct namnod *nscan = namep;
659 int LR;
661 if (!chkid(nam))
662 return(0);
663 while (nscan)
665 if ((LR = cf(nam, nscan->namid)) == 0)
666 return(nscan);
667 else if (LR < 0)
668 nscan = nscan->namlft;
669 else
670 nscan = nscan->namrgt;
672 return(0);
675 void
676 unset_name(unsigned char *name)
678 struct namnod *n;
679 unsigned char call_dolocale = 0;
681 if (n = findnam(name))
683 if (n->namflg & N_RDONLY)
684 failed(name, wtfailed);
686 if (n == &pathnod ||
687 n == &ifsnod ||
688 n == &ps1nod ||
689 n == &ps2nod ||
690 n == &mchknod)
692 failed(name, badunset);
695 #ifndef RES
697 if ((flags & rshflg) && eq(name, "SHELL"))
698 failed(name, restricted);
700 #endif
702 if (n->namflg & N_FUNCTN)
704 func_unhash(name);
705 freefunc(n);
707 else
709 call_dolocale++;
710 free(n->namval);
711 free(n->namenv);
714 n->namval = n->namenv = 0;
715 n->namflg = N_DEFAULT;
717 if (call_dolocale)
718 dolocale(name);
720 if (flags & prompt)
722 if (n == &mailpnod)
723 setmail(mailnod.namval);
724 else if (n == &mailnod && mailpnod.namflg == N_DEFAULT)
725 setmail(0);
731 * The environment variables which affect locale.
732 * Note: if all names in this list do not begin with 'L',
733 * you MUST modify dolocale(). Also, be sure that the
734 * fake_env has the same number of elements as localevar.
736 static char *localevar[] = {
737 "LC_ALL",
738 "LC_CTYPE",
739 "LC_MESSAGES",
740 "LANG",
744 static char *fake_env[] = {
753 * If name is one of several special variables which affect the locale,
754 * do a setlocale().
756 static void
757 dolocale(nm)
758 char *nm;
760 char **real_env;
761 struct namnod *n;
762 int lv, fe;
763 int i;
766 * Take advantage of fact that names of these vars all start
767 * with 'L' to avoid unnecessary work.
768 * Do locale processing only if /usr is mounted.
770 if ((*nm != 'L') || !localedir_exists ||
771 (!(eq(nm, "LC_ALL") || eq(nm, "LC_CTYPE") ||
772 eq(nm, "LANG") || eq(nm, "LC_MESSAGES"))))
773 return;
776 * setlocale() has all the smarts built into it, but
777 * it works by examining the environment. Unfortunately,
778 * when you set an environment variable, the shell does
779 * not modify its own environment; it just remembers that the
780 * variable needs to be exported to any children. We hack around
781 * this by consing up a fake environment for the use of setlocale()
782 * and substituting it for the real env before calling setlocale().
786 * Build the fake environment.
787 * Look up the value of each of the special environment
788 * variables, and put their value into the fake environment,
789 * if they are exported.
791 for (lv = 0, fe = 0; localevar[lv]; lv++) {
792 if ((n = findnam(localevar[lv]))) {
793 char *p, *q;
795 if (!n->namval)
796 continue;
798 fake_env[fe++] = p = alloc(length(localevar[lv])
799 + length(n->namval) + 2);
800 /* copy name */
801 q = localevar[lv];
802 while (*q)
803 *p++ = *q++;
805 *p++ = '=';
807 /* copy value */
808 q = (char*)(n->namval);
809 while (*q)
810 *p++ = *q++;
811 *p++ = '\0';
814 fake_env[fe] = (char *)0;
817 * Switch fake env for real and call setlocale().
819 real_env = (char **)environ;
820 environ = (unsigned char **)fake_env;
822 if (setlocale(LC_ALL, "") == NULL)
823 prs(_gettext(badlocale));
826 * Switch back and tear down the fake env.
828 environ = (unsigned char **)real_env;
829 for (i = 0; i < fe; i++) {
830 free(fake_env[i]);
831 fake_env[i] = (char *)0;