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