xref: /freebsd/bin/sh/var.c (revision 8e537d168674d6b65869f73c20813001af875738)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	$Id: var.c,v 1.5 1996/08/12 22:14:50 ache Exp $
37  */
38 
39 #ifndef lint
40 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
41 #endif /* not lint */
42 
43 #include <unistd.h>
44 #include <stdlib.h>
45 
46 /*
47  * Shell variables.
48  */
49 
50 #include <locale.h>
51 
52 #include "shell.h"
53 #include "output.h"
54 #include "expand.h"
55 #include "nodes.h"	/* for other headers */
56 #include "eval.h"	/* defines cmdenviron */
57 #include "exec.h"
58 #include "syntax.h"
59 #include "options.h"
60 #include "mail.h"
61 #include "parser.h"
62 #include "var.h"
63 #include "memalloc.h"
64 #include "error.h"
65 #include "mystring.h"
66 #ifndef NO_HISTORY
67 #include "myhistedit.h"
68 #endif
69 
70 
71 #define VTABSIZE 39
72 
73 
74 struct varinit {
75 	struct var *var;
76 	int flags;
77 	char *text;
78 };
79 
80 
81 #if ATTY
82 struct var vatty;
83 #endif
84 #ifndef NO_HISTORY
85 struct var vhistsize;
86 #endif
87 struct var vifs;
88 struct var vmail;
89 struct var vmpath;
90 struct var vpath;
91 struct var vps1;
92 struct var vps2;
93 struct var vvers;
94 #if ATTY
95 struct var vterm;
96 #endif
97 
98 const struct varinit varinit[] = {
99 #if ATTY
100 	{&vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY="},
101 #endif
102 #ifndef NO_HISTORY
103 	{&vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE="},
104 #endif
105 	{&vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n"},
106 	{&vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL="},
107 	{&vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH="},
108 	{&vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=/bin:/usr/bin"},
109 	/*
110 	 * vps1 depends on uid
111 	 */
112 	{&vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> "},
113 #if ATTY
114 	{&vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM="},
115 #endif
116 	{NULL,	0,				NULL}
117 };
118 
119 struct var *vartab[VTABSIZE];
120 
121 STATIC int unsetvar __P((char *));
122 STATIC struct var **hashvar __P((char *));
123 STATIC int varequal __P((char *, char *));
124 STATIC int localevar __P((char *));
125 
126 /*
127  * Initialize the varable symbol tables and import the environment
128  */
129 
130 #ifdef mkinit
131 INCLUDE "var.h"
132 INIT {
133 	char **envp;
134 	extern char **environ;
135 
136 	initvar();
137 	for (envp = environ ; *envp ; envp++) {
138 		if (strchr(*envp, '=')) {
139 			setvareq(*envp, VEXPORT|VTEXTFIXED);
140 		}
141 	}
142 }
143 #endif
144 
145 
146 /*
147  * This routine initializes the builtin variables.  It is called when the
148  * shell is initialized and again when a shell procedure is spawned.
149  */
150 
151 void
152 initvar() {
153 	const struct varinit *ip;
154 	struct var *vp;
155 	struct var **vpp;
156 
157 	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
158 		if ((vp->flags & VEXPORT) == 0) {
159 			vpp = hashvar(ip->text);
160 			vp->next = *vpp;
161 			*vpp = vp;
162 			vp->text = ip->text;
163 			vp->flags = ip->flags;
164 		}
165 	}
166 	/*
167 	 * PS1 depends on uid
168 	 */
169 	if ((vps1.flags & VEXPORT) == 0) {
170 		vpp = hashvar("PS1=");
171 		vps1.next = *vpp;
172 		*vpp = &vps1;
173 		vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
174 		vps1.flags = VSTRFIXED|VTEXTFIXED;
175 	}
176 }
177 
178 /*
179  * Set the value of a variable.  The flags argument is ored with the
180  * flags of the variable.  If val is NULL, the variable is unset.
181  */
182 
183 void
184 setvar(name, val, flags)
185 	char *name, *val;
186 	int flags;
187 {
188 	char *p, *q;
189 	int len;
190 	int namelen;
191 	char *nameeq;
192 	int isbad;
193 
194 	isbad = 0;
195 	p = name;
196 	if (! is_name(*p))
197 		isbad = 1;
198 	p++;
199 	for (;;) {
200 		if (! is_in_name(*p)) {
201 			if (*p == '\0' || *p == '=')
202 				break;
203 			isbad = 1;
204 		}
205 		p++;
206 	}
207 	namelen = p - name;
208 	if (isbad)
209 		error("%.*s: bad variable name", namelen, name);
210 	len = namelen + 2;		/* 2 is space for '=' and '\0' */
211 	if (val == NULL) {
212 		flags |= VUNSET;
213 	} else {
214 		len += strlen(val);
215 	}
216 	p = nameeq = ckmalloc(len);
217 	q = name;
218 	while (--namelen >= 0)
219 		*p++ = *q++;
220 	*p++ = '=';
221 	*p = '\0';
222 	if (val)
223 		scopy(val, p);
224 	setvareq(nameeq, flags);
225 }
226 
227 STATIC int
228 localevar(s)
229 	char *s;
230 	{
231 	static char *lnames[7] = {
232 		"ALL", "COLLATE", "CTYPE", "MONETARY",
233 		"NUMERIC", "TIME", NULL
234 	};
235 	char **ss;
236 
237 	if (*s != 'L')
238 		return 0;
239 	if (varequal(s + 1, "ANG"))
240 		return 1;
241 	if (strncmp(s + 1, "C_", 2) != 0)
242 		return 0;
243 	for (ss = lnames; *ss ; ss++)
244 		if (varequal(s + 3, *ss))
245 			return 1;
246 	return 0;
247 }
248 
249 /*
250  * Same as setvar except that the variable and value are passed in
251  * the first argument as name=value.  Since the first argument will
252  * be actually stored in the table, it should not be a string that
253  * will go away.
254  */
255 
256 void
257 setvareq(s, flags)
258 	char *s;
259 	int flags;
260 {
261 	struct var *vp, **vpp;
262 
263 	vpp = hashvar(s);
264 	for (vp = *vpp ; vp ; vp = vp->next) {
265 		if (varequal(s, vp->text)) {
266 			if (vp->flags & VREADONLY) {
267 				int len = strchr(s, '=') - s;
268 				error("%.*s: is read only", len, s);
269 			}
270 			INTOFF;
271 			if (vp == &vpath)
272 				changepath(s + 5);	/* 5 = strlen("PATH=") */
273 			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
274 				ckfree(vp->text);
275 			vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
276 			vp->flags |= flags;
277 			vp->text = s;
278 			if (vp == &vmpath || (vp == &vmail && ! mpathset()))
279 				chkmail(1);
280 #ifndef NO_HISTORY
281 			if (vp == &vhistsize)
282 				sethistsize();
283 #endif
284 			if ((vp->flags & VEXPORT) && localevar(s)) {
285 				putenv(s);
286 				(void) setlocale(LC_ALL, "");
287 			}
288 			INTON;
289 			return;
290 		}
291 	}
292 	/* not found */
293 	vp = ckmalloc(sizeof (*vp));
294 	vp->flags = flags;
295 	vp->text = s;
296 	vp->next = *vpp;
297 	INTOFF;
298 	*vpp = vp;
299 	if ((vp->flags & VEXPORT) && localevar(s)) {
300 		putenv(s);
301 		(void) setlocale(LC_ALL, "");
302 	}
303 	INTON;
304 }
305 
306 
307 
308 /*
309  * Process a linked list of variable assignments.
310  */
311 
312 void
313 listsetvar(list)
314 	struct strlist *list;
315 	{
316 	struct strlist *lp;
317 
318 	INTOFF;
319 	for (lp = list ; lp ; lp = lp->next) {
320 		setvareq(savestr(lp->text), 0);
321 	}
322 	INTON;
323 }
324 
325 
326 
327 /*
328  * Find the value of a variable.  Returns NULL if not set.
329  */
330 
331 char *
332 lookupvar(name)
333 	char *name;
334 	{
335 	struct var *v;
336 
337 	for (v = *hashvar(name) ; v ; v = v->next) {
338 		if (varequal(v->text, name)) {
339 			if (v->flags & VUNSET)
340 				return NULL;
341 			return strchr(v->text, '=') + 1;
342 		}
343 	}
344 	return NULL;
345 }
346 
347 
348 
349 /*
350  * Search the environment of a builtin command.  If the second argument
351  * is nonzero, return the value of a variable even if it hasn't been
352  * exported.
353  */
354 
355 char *
356 bltinlookup(name, doall)
357 	char *name;
358 	int doall;
359 {
360 	struct strlist *sp;
361 	struct var *v;
362 
363 	for (sp = cmdenviron ; sp ; sp = sp->next) {
364 		if (varequal(sp->text, name))
365 			return strchr(sp->text, '=') + 1;
366 	}
367 	for (v = *hashvar(name) ; v ; v = v->next) {
368 		if (varequal(v->text, name)) {
369 			if ((v->flags & VUNSET)
370 			 || (!doall && (v->flags & VEXPORT) == 0))
371 				return NULL;
372 			return strchr(v->text, '=') + 1;
373 		}
374 	}
375 	return NULL;
376 }
377 
378 
379 
380 /*
381  * Generate a list of exported variables.  This routine is used to construct
382  * the third argument to execve when executing a program.
383  */
384 
385 char **
386 environment() {
387 	int nenv;
388 	struct var **vpp;
389 	struct var *vp;
390 	char **env, **ep;
391 
392 	nenv = 0;
393 	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
394 		for (vp = *vpp ; vp ; vp = vp->next)
395 			if (vp->flags & VEXPORT)
396 				nenv++;
397 	}
398 	ep = env = stalloc((nenv + 1) * sizeof *env);
399 	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
400 		for (vp = *vpp ; vp ; vp = vp->next)
401 			if (vp->flags & VEXPORT)
402 				*ep++ = vp->text;
403 	}
404 	*ep = NULL;
405 	return env;
406 }
407 
408 
409 /*
410  * Called when a shell procedure is invoked to clear out nonexported
411  * variables.  It is also necessary to reallocate variables of with
412  * VSTACK set since these are currently allocated on the stack.
413  */
414 
415 #ifdef mkinit
416 MKINIT void shprocvar();
417 
418 SHELLPROC {
419 	shprocvar();
420 }
421 #endif
422 
423 void
424 shprocvar() {
425 	struct var **vpp;
426 	struct var *vp, **prev;
427 
428 	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
429 		for (prev = vpp ; (vp = *prev) != NULL ; ) {
430 			if ((vp->flags & VEXPORT) == 0) {
431 				*prev = vp->next;
432 				if ((vp->flags & VTEXTFIXED) == 0)
433 					ckfree(vp->text);
434 				if ((vp->flags & VSTRFIXED) == 0)
435 					ckfree(vp);
436 			} else {
437 				if (vp->flags & VSTACK) {
438 					vp->text = savestr(vp->text);
439 					vp->flags &=~ VSTACK;
440 				}
441 				prev = &vp->next;
442 			}
443 		}
444 	}
445 	initvar();
446 }
447 
448 
449 
450 /*
451  * Command to list all variables which are set.  Currently this command
452  * is invoked from the set command when the set command is called without
453  * any variables.
454  */
455 
456 int
457 showvarscmd(argc, argv)
458 	int argc;
459 	char **argv;
460 {
461 	struct var **vpp;
462 	struct var *vp;
463 
464 	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
465 		for (vp = *vpp ; vp ; vp = vp->next) {
466 			if ((vp->flags & VUNSET) == 0)
467 				out1fmt("%s\n", vp->text);
468 		}
469 	}
470 	return 0;
471 }
472 
473 
474 
475 /*
476  * The export and readonly commands.
477  */
478 
479 int
480 exportcmd(argc, argv)
481 	int argc;
482 	char **argv;
483 {
484 	struct var **vpp;
485 	struct var *vp;
486 	char *name;
487 	char *p;
488 	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
489 
490 	listsetvar(cmdenviron);
491 	if (argc > 1) {
492 		while ((name = *argptr++) != NULL) {
493 			if ((p = strchr(name, '=')) != NULL) {
494 				p++;
495 			} else {
496 				vpp = hashvar(name);
497 				for (vp = *vpp ; vp ; vp = vp->next) {
498 					if (varequal(vp->text, name)) {
499 						vp->flags |= flag;
500 						if ((vp->flags & VEXPORT) && localevar(vp->text)) {
501 							putenv(vp->text);
502 							(void) setlocale(LC_ALL, "");
503 						}
504 						goto found;
505 					}
506 				}
507 			}
508 			setvar(name, p, flag);
509 found:;
510 		}
511 	} else {
512 		for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
513 			for (vp = *vpp ; vp ; vp = vp->next) {
514 				if (vp->flags & flag) {
515 					for (p = vp->text ; *p != '=' ; p++)
516 						out1c(*p);
517 					out1c('\n');
518 				}
519 			}
520 		}
521 	}
522 	return 0;
523 }
524 
525 
526 /*
527  * The "local" command.
528  */
529 
530 int
531 localcmd(argc, argv)
532 	int argc;
533 	char **argv;
534 {
535 	char *name;
536 
537 	if (! in_function())
538 		error("Not in a function");
539 	while ((name = *argptr++) != NULL) {
540 		mklocal(name);
541 	}
542 	return 0;
543 }
544 
545 
546 /*
547  * Make a variable a local variable.  When a variable is made local, it's
548  * value and flags are saved in a localvar structure.  The saved values
549  * will be restored when the shell function returns.  We handle the name
550  * "-" as a special case.
551  */
552 
553 void
554 mklocal(name)
555 	char *name;
556 	{
557 	struct localvar *lvp;
558 	struct var **vpp;
559 	struct var *vp;
560 
561 	INTOFF;
562 	lvp = ckmalloc(sizeof (struct localvar));
563 	if (name[0] == '-' && name[1] == '\0') {
564 		lvp->text = ckmalloc(sizeof optlist);
565 		memcpy(lvp->text, optlist, sizeof optlist);
566 		vp = NULL;
567 	} else {
568 		vpp = hashvar(name);
569 		for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
570 		if (vp == NULL) {
571 			if (strchr(name, '='))
572 				setvareq(savestr(name), VSTRFIXED);
573 			else
574 				setvar(name, NULL, VSTRFIXED);
575 			vp = *vpp;	/* the new variable */
576 			lvp->text = NULL;
577 			lvp->flags = VUNSET;
578 		} else {
579 			lvp->text = vp->text;
580 			lvp->flags = vp->flags;
581 			vp->flags |= VSTRFIXED|VTEXTFIXED;
582 			if (strchr(name, '='))
583 				setvareq(savestr(name), 0);
584 		}
585 	}
586 	lvp->vp = vp;
587 	lvp->next = localvars;
588 	localvars = lvp;
589 	INTON;
590 }
591 
592 
593 /*
594  * Called after a function returns.
595  */
596 
597 void
598 poplocalvars() {
599 	struct localvar *lvp;
600 	struct var *vp;
601 
602 	while ((lvp = localvars) != NULL) {
603 		localvars = lvp->next;
604 		vp = lvp->vp;
605 		if (vp == NULL) {	/* $- saved */
606 			memcpy(optlist, lvp->text, sizeof optlist);
607 			ckfree(lvp->text);
608 		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
609 			(void)unsetvar(vp->text);
610 		} else {
611 			if ((vp->flags & VTEXTFIXED) == 0)
612 				ckfree(vp->text);
613 			vp->flags = lvp->flags;
614 			vp->text = lvp->text;
615 		}
616 		ckfree(lvp);
617 	}
618 }
619 
620 
621 int
622 setvarcmd(argc, argv)
623 	int argc;
624 	char **argv;
625 {
626 	if (argc <= 2)
627 		return unsetcmd(argc, argv);
628 	else if (argc == 3)
629 		setvar(argv[1], argv[2], 0);
630 	else
631 		error("List assignment not implemented");
632 	return 0;
633 }
634 
635 
636 /*
637  * The unset builtin command.  We unset the function before we unset the
638  * variable to allow a function to be unset when there is a readonly variable
639  * with the same name.
640  */
641 
642 int
643 unsetcmd(argc, argv)
644 	int argc;
645 	char **argv;
646 {
647 	char **ap;
648 	int i;
649 	int flg_func = 0;
650 	int flg_var = 0;
651 	int ret = 0;
652 
653 	while ((i = nextopt("vf")) != '\0') {
654 		if (i == 'f')
655 			flg_func = 1;
656 		else
657 			flg_var = 1;
658 	}
659 	if (flg_func == 0 && flg_var == 0)
660 		flg_var = 1;
661 
662 	for (ap = argptr; *ap ; ap++) {
663 		if (flg_func)
664 			ret |= unsetfunc(*ap);
665 		if (flg_var)
666 			ret |= unsetvar(*ap);
667 	}
668 	return ret;
669 }
670 
671 
672 /*
673  * Unset the specified variable.
674  */
675 
676 STATIC int
677 unsetvar(s)
678 	char *s;
679 	{
680 	struct var **vpp;
681 	struct var *vp;
682 
683 	vpp = hashvar(s);
684 	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
685 		if (varequal(vp->text, s)) {
686 			if (vp->flags & VREADONLY)
687 				return (1);
688 			INTOFF;
689 			if (*(strchr(vp->text, '=') + 1) != '\0')
690 				setvar(s, nullstr, 0);
691 			if ((vp->flags & VEXPORT) && localevar(vp->text)) {
692 				unsetenv(s);
693 				setlocale(LC_ALL, "");
694 			}
695 			vp->flags &=~ VEXPORT;
696 			vp->flags |= VUNSET;
697 			if ((vp->flags & VSTRFIXED) == 0) {
698 				if ((vp->flags & VTEXTFIXED) == 0)
699 					ckfree(vp->text);
700 				*vpp = vp->next;
701 				ckfree(vp);
702 			}
703 			INTON;
704 			return (0);
705 		}
706 	}
707 
708 	return (1);
709 }
710 
711 
712 
713 /*
714  * Find the appropriate entry in the hash table from the name.
715  */
716 
717 STATIC struct var **
718 hashvar(p)
719 	register char *p;
720 	{
721 	unsigned int hashval;
722 
723 	hashval = ((unsigned char)*p) << 4;
724 	while (*p && *p != '=')
725 		hashval += (unsigned char)*p++;
726 	return &vartab[hashval % VTABSIZE];
727 }
728 
729 
730 
731 /*
732  * Returns true if the two strings specify the same varable.  The first
733  * variable name is terminated by '='; the second may be terminated by
734  * either '=' or '\0'.
735  */
736 
737 STATIC int
738 varequal(p, q)
739 	register char *p, *q;
740 	{
741 	while (*p == *q++) {
742 		if (*p++ == '=')
743 			return 1;
744 	}
745 	if (*p == '=' && *(q - 1) == '\0')
746 		return 1;
747 	return 0;
748 }
749