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