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]
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 */
38 extern unsigned char *simple();
41 static void setname(unsigned char *, int);
42 static void set_builtins_path();
44 static void namwalk(struct namnod
*);
45 static void dolocale();
47 struct namnod ps2nod
=
51 (unsigned char *)ps2name
53 struct namnod cdpnod
=
57 (unsigned char *)cdpname
59 struct namnod pathnod
=
63 (unsigned char *)pathname
65 struct namnod ifsnod
=
69 (unsigned char *)ifsname
71 struct namnod ps1nod
=
75 (unsigned char *)ps1name
77 struct namnod homenod
=
81 (unsigned char *)homename
83 struct namnod mailnod
=
87 (unsigned char *)mailname
89 struct namnod mchknod
=
93 (unsigned char *)mchkname
95 struct namnod acctnod
=
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
)
121 if (w
== 0 || *w
== 0)
129 mid
= (low
+ high
) / 2;
131 if ((cond
= cf(w
, syswds
[mid
].sysnam
)) < 0)
136 return(syswds
[mid
].sysval
);
142 setlist(struct argnod
*arg
, int xp
)
144 if (flags
& exportflg
)
149 unsigned char *s
= mactrim(arg
->argval
);
164 setname(unsigned char *argi
, int xp
) /* does parameter assignments */
166 unsigned char *argscan
= argi
;
169 if (letter(*argscan
))
171 while (alphanum(*argscan
))
176 *argscan
= 0; /* make name a cohesive string */
183 n
->namenv
= n
->namval
= argscan
;
197 replace(unsigned char **a
, unsigned char *v
)
204 dfault(struct namnod
*n
, unsigned char *v
)
211 assign(struct namnod
*n
, unsigned char *v
)
213 if (n
->namflg
& N_RDONLY
)
214 failed(n
->namid
, wtfailed
);
218 else if (flags
& rshflg
)
220 if (n
== &pathnod
|| eq(n
->namid
,"SHELL"))
221 failed(n
->namid
, restricted
);
225 else if (n
->namflg
& N_FUNCTN
)
227 func_unhash(n
->namid
);
231 n
->namflg
= N_DEFAULT
;
239 replace(&n
->namval
, v
);
252 if ((n
== &mailpnod
) || (n
== &mailnod
&& mailpnod
.namflg
== N_DEFAULT
))
264 while (path
&& *path
)
266 if (patheq(path
, "/usr/ucb"))
271 else if (patheq(path
, "/usr/bin"))
273 else if (patheq(path
, "/bin"))
275 else if (patheq(path
, "/usr/5bin"))
277 path
= nextpath(path
);
282 patheq(unsigned char *component
, char *dir
)
290 c
= '\0'; /* end of component of path */
299 readvar(unsigned char **names
)
302 struct fileblk
*f
= &fb
;
303 unsigned char c
[MULTI_BYTE_MAX
+1];
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
;
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)
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)
335 * strip leading IFS characters
344 while(*pc
++ = *rest
++);
345 if(!anys(c
, ifsnod
.namval
))
352 if ((*names
&& anys(c
, ifsnod
.namval
)) || eolchar(d
))
354 if (staktop
>= brkend
)
357 assign(n
, absstak(rel
));
360 n
= lookup(*names
++);
367 else /* strip imbedded IFS characters */
374 while(*pc
++ = *rest
++);
375 if(!anys(c
, ifsnod
.namval
))
385 if (staktop
>= brkend
)
395 if (staktop
>= brkend
)
399 if(!anys(c
, ifsnod
.namval
))
410 while(*pc
++ = *rest
++);
416 assign(n
, (unsigned char *)nullstr
);
418 n
= lookup(*names
++);
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
);
442 assnum(unsigned char **p
, long i
)
445 replace(p
, &numbuf
[j
]);
456 movstr(v
, p
= (unsigned char *)alloc(length(v
)));
465 lookup(unsigned char *nam
)
467 struct namnod
*nscan
= namep
;
468 struct namnod
**prev
;
476 if ((LR
= cf(nam
, nscan
->namid
)) == 0)
480 prev
= &(nscan
->namlft
);
482 prev
= &(nscan
->namrgt
);
488 nscan
= (struct namnod
*)alloc(sizeof *nscan
);
489 nscan
->namlft
= nscan
->namrgt
= (struct namnod
*)NIL
;
490 nscan
->namid
= make(nam
);
492 nscan
->namflg
= N_DEFAULT
;
495 return(*prev
= nscan
);
502 unsigned char *cp
= nam
;
517 static void (*namfn
)();
520 namscan(void (*fn
)())
527 namwalk(struct namnod
*np
)
538 printnam(struct namnod
*n
)
544 if (n
->namflg
& N_FUNCTN
)
546 struct fndnod
*f
= fndptr(n
->namenv
);
554 else if (s
= n
->namval
)
566 printro(struct namnod
*n
)
568 if (n
->namflg
& N_RDONLY
)
570 prs_buff(_gettext(readonly
));
578 printexp(struct namnod
*n
)
580 if (n
->namflg
& N_EXPORT
)
582 prs_buff(_gettext(export
));
592 unsigned char **e
= environ
;
595 setname(*e
++, N_ENVNAM
);
599 static unsigned char **argnam
;
602 countnam(struct namnod
*n
)
609 pushnam(struct namnod
*n
)
613 unsigned char *namval
;
615 if (((flg
& N_ENVCHG
) && (flg
& N_EXPORT
)) || (flg
& N_FUNCTN
))
618 /* Discard Local variable in child process */
619 if (!(flg
& ~N_ENVCHG
)) {
623 /* Release for re-use */
625 n
->namval
= (unsigned char *)NIL
;
633 p
= movstrstak(n
->namid
, staktop
);
634 p
= movstrstak("=", p
);
635 p
= movstrstak(namval
, p
);
636 *argnam
++ = getstak(p
+ 1 - (unsigned char *)(stakbot
));
648 argnam
= er
= (unsigned char **)getstak(namec
* BYTESPERWORD
+ BYTESPERWORD
);
658 struct namnod
*nscan
= namep
;
665 if ((LR
= cf(nam
, nscan
->namid
)) == 0)
668 nscan
= nscan
->namlft
;
670 nscan
= nscan
->namrgt
;
676 unset_name(unsigned char *name
)
679 unsigned char call_dolocale
= 0;
681 if (n
= findnam(name
))
683 if (n
->namflg
& N_RDONLY
)
684 failed(name
, wtfailed
);
692 failed(name
, badunset
);
697 if ((flags
& rshflg
) && eq(name
, "SHELL"))
698 failed(name
, restricted
);
702 if (n
->namflg
& N_FUNCTN
)
714 n
->namval
= n
->namenv
= 0;
715 n
->namflg
= N_DEFAULT
;
723 setmail(mailnod
.namval
);
724 else if (n
== &mailnod
&& mailpnod
.namflg
== N_DEFAULT
)
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
[] = {
744 static char *fake_env
[] = {
753 * If name is one of several special variables which affect the locale,
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"))))
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
]))) {
798 fake_env
[fe
++] = p
= alloc(length(localevar
[lv
])
799 + length(n
->namval
) + 2);
808 q
= (char*)(n
->namval
);
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
++) {
831 fake_env
[i
] = (char *)0;