var.c revision 90112
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
39static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
40#endif
41static const char rcsid[] =
42  "$FreeBSD: head/bin/sh/var.c 90112 2002-02-02 07:06:58Z imp $";
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
76struct varinit {
77	struct var *var;
78	int flags;
79	char *text;
80	void (*func)(const char *);
81};
82
83
84#if ATTY
85struct var vatty;
86#endif
87#ifndef NO_HISTORY
88struct var vhistsize;
89#endif
90struct var vifs;
91struct var vmail;
92struct var vmpath;
93struct var vpath;
94struct var vps1;
95struct var vps2;
96struct var vvers;
97#if ATTY
98struct var vterm;
99#endif
100struct var voptind;
101
102const 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
134struct var *vartab[VTABSIZE];
135
136STATIC struct var **hashvar(char *);
137STATIC int varequal(char *, char *);
138STATIC int localevar(char *);
139
140/*
141 * Initialize the varable symbol tables and import the environment
142 */
143
144#ifdef mkinit
145INCLUDE "var.h"
146INIT {
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
165void
166initvar(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
198int
199setvarsafe(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
224void
225setvar(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
266STATIC int
267localevar(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
294void
295setvareq(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
356void
357listsetvar(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
374char *
375lookupvar(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
397char *
398bltinlookup(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
425char **
426environment(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
457MKINIT void shprocvar();
458
459SHELLPROC {
460	shprocvar();
461}
462#endif
463
464void
465shprocvar(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
498int
499showvarscmd(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
519int
520exportcmd(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);
548found:;
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
569int
570localcmd(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
590void
591mklocal(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
633void
634poplocalvars(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
658int
659setvarcmd(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
677int
678unsetcmd(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
709int
710unsetvar(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
749STATIC struct var **
750hashvar(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
768STATIC int
769varequal(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