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