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