var.c revision 223060
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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef lint
34#if 0
35static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
36#endif
37#endif /* not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/bin/sh/var.c 223060 2011-06-13 21:03:27Z jilles $");
40
41#include <unistd.h>
42#include <stdlib.h>
43#include <paths.h>
44
45/*
46 * Shell variables.
47 */
48
49#include <locale.h>
50#include <langinfo.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#include "builtins.h"
67#ifndef NO_HISTORY
68#include "myhistedit.h"
69#endif
70
71
72#define VTABSIZE 39
73
74
75struct varinit {
76	struct var *var;
77	int flags;
78	const char *text;
79	void (*func)(const char *);
80};
81
82
83#ifndef NO_HISTORY
84struct var vhistsize;
85struct var vterm;
86#endif
87struct var vifs;
88struct var vmail;
89struct var vmpath;
90struct var vpath;
91struct var vppid;
92struct var vps1;
93struct var vps2;
94struct var vps4;
95struct var vvers;
96static struct var voptind;
97
98int forcelocal;
99
100static const struct varinit varinit[] = {
101#ifndef NO_HISTORY
102	{ &vhistsize,	VUNSET,				"HISTSIZE=",
103	  sethistsize },
104#endif
105	{ &vifs,	0,				"IFS= \t\n",
106	  NULL },
107	{ &vmail,	VUNSET,				"MAIL=",
108	  NULL },
109	{ &vmpath,	VUNSET,				"MAILPATH=",
110	  NULL },
111	{ &vpath,	0,				"PATH=" _PATH_DEFPATH,
112	  changepath },
113	{ &vppid,	VUNSET,				"PPID=",
114	  NULL },
115	/*
116	 * vps1 depends on uid
117	 */
118	{ &vps2,	0,				"PS2=> ",
119	  NULL },
120	{ &vps4,	0,				"PS4=+ ",
121	  NULL },
122#ifndef NO_HISTORY
123	{ &vterm,	VUNSET,				"TERM=",
124	  setterm },
125#endif
126	{ &voptind,	0,				"OPTIND=1",
127	  getoptsreset },
128	{ NULL,	0,				NULL,
129	  NULL }
130};
131
132static struct var *vartab[VTABSIZE];
133
134static const char *const locale_names[7] = {
135	"LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
136	"LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL
137};
138static const int locale_categories[7] = {
139	LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0
140};
141
142static int varequal(const char *, const char *);
143static struct var *find_var(const char *, struct var ***, int *);
144static int localevar(const char *);
145
146/*
147 * Initialize the variable symbol tables and import the environment.
148 */
149
150#ifdef mkinit
151INCLUDE "var.h"
152MKINIT char **environ;
153INIT {
154	char **envp;
155
156	initvar();
157	for (envp = environ ; *envp ; envp++) {
158		if (strchr(*envp, '=')) {
159			setvareq(*envp, VEXPORT|VTEXTFIXED);
160		}
161	}
162}
163#endif
164
165
166/*
167 * This routine initializes the builtin variables.  It is called when the
168 * shell is initialized.
169 */
170
171void
172initvar(void)
173{
174	char ppid[20];
175	const struct varinit *ip;
176	struct var *vp;
177	struct var **vpp;
178
179	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
180		if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
181			continue;
182		vp->next = *vpp;
183		*vpp = vp;
184		vp->text = __DECONST(char *, ip->text);
185		vp->flags = ip->flags | VSTRFIXED | VTEXTFIXED;
186		vp->func = ip->func;
187	}
188	/*
189	 * PS1 depends on uid
190	 */
191	if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
192		vps1.next = *vpp;
193		*vpp = &vps1;
194		vps1.text = __DECONST(char *, geteuid() ? "PS1=$ " : "PS1=# ");
195		vps1.flags = VSTRFIXED|VTEXTFIXED;
196	}
197	if ((vppid.flags & VEXPORT) == 0) {
198		fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
199		setvarsafe("PPID", ppid, 0);
200	}
201}
202
203/*
204 * Safe version of setvar, returns 1 on success 0 on failure.
205 */
206
207int
208setvarsafe(const char *name, const char *val, int flags)
209{
210	struct jmploc jmploc;
211	struct jmploc *const savehandler = handler;
212	int err = 0;
213	int inton;
214
215	inton = is_int_on();
216	if (setjmp(jmploc.loc))
217		err = 1;
218	else {
219		handler = &jmploc;
220		setvar(name, val, flags);
221	}
222	handler = savehandler;
223	SETINTON(inton);
224	return err;
225}
226
227/*
228 * Set the value of a variable.  The flags argument is stored with the
229 * flags of the variable.  If val is NULL, the variable is unset.
230 */
231
232void
233setvar(const char *name, const char *val, int flags)
234{
235	const char *p;
236	int len;
237	int namelen;
238	char *nameeq;
239	int isbad;
240
241	isbad = 0;
242	p = name;
243	if (! is_name(*p))
244		isbad = 1;
245	p++;
246	for (;;) {
247		if (! is_in_name(*p)) {
248			if (*p == '\0' || *p == '=')
249				break;
250			isbad = 1;
251		}
252		p++;
253	}
254	namelen = p - name;
255	if (isbad)
256		error("%.*s: bad variable name", namelen, name);
257	len = namelen + 2;		/* 2 is space for '=' and '\0' */
258	if (val == NULL) {
259		flags |= VUNSET;
260	} else {
261		len += strlen(val);
262	}
263	nameeq = ckmalloc(len);
264	memcpy(nameeq, name, namelen);
265	nameeq[namelen] = '=';
266	if (val)
267		scopy(val, nameeq + namelen + 1);
268	else
269		nameeq[namelen + 1] = '\0';
270	setvareq(nameeq, flags);
271}
272
273static int
274localevar(const char *s)
275{
276	const char *const *ss;
277
278	if (*s != 'L')
279		return 0;
280	if (varequal(s + 1, "ANG"))
281		return 1;
282	if (strncmp(s + 1, "C_", 2) != 0)
283		return 0;
284	if (varequal(s + 3, "ALL"))
285		return 1;
286	for (ss = locale_names; *ss ; ss++)
287		if (varequal(s + 3, *ss + 3))
288			return 1;
289	return 0;
290}
291
292
293/*
294 * Sets/unsets an environment variable from a pointer that may actually be a
295 * pointer into environ where the string should not be manipulated.
296 */
297static void
298change_env(const char *s, int set)
299{
300	char *eqp;
301	char *ss;
302
303	ss = savestr(s);
304	if ((eqp = strchr(ss, '=')) != NULL)
305		*eqp = '\0';
306	if (set && eqp != NULL)
307		(void) setenv(ss, eqp + 1, 1);
308	else
309		(void) unsetenv(ss);
310	ckfree(ss);
311
312	return;
313}
314
315
316/*
317 * Same as setvar except that the variable and value are passed in
318 * the first argument as name=value.  Since the first argument will
319 * be actually stored in the table, it should not be a string that
320 * will go away.
321 */
322
323void
324setvareq(char *s, int flags)
325{
326	struct var *vp, **vpp;
327	int nlen;
328
329	if (aflag)
330		flags |= VEXPORT;
331	if (forcelocal && !(flags & (VNOSET | VNOLOCAL)))
332		mklocal(s);
333	vp = find_var(s, &vpp, &nlen);
334	if (vp != NULL) {
335		if (vp->flags & VREADONLY)
336			error("%.*s: is read only", vp->name_len, s);
337		if (flags & VNOSET)
338			return;
339		INTOFF;
340
341		if (vp->func && (flags & VNOFUNC) == 0)
342			(*vp->func)(s + vp->name_len + 1);
343
344		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
345			ckfree(vp->text);
346
347		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
348		vp->flags |= flags;
349		vp->text = s;
350
351		/*
352		 * We could roll this to a function, to handle it as
353		 * a regular variable function callback, but why bother?
354		 *
355		 * Note: this assumes iflag is not set to 1 initially.
356		 * As part of init(), this is called before arguments
357		 * are looked at.
358		 */
359		if ((vp == &vmpath || (vp == &vmail && ! mpathset())) &&
360		    iflag == 1)
361			chkmail(1);
362		if ((vp->flags & VEXPORT) && localevar(s)) {
363			change_env(s, 1);
364			(void) setlocale(LC_ALL, "");
365			updatecharset();
366		}
367		INTON;
368		return;
369	}
370	/* not found */
371	if (flags & VNOSET)
372		return;
373	vp = ckmalloc(sizeof (*vp));
374	vp->flags = flags;
375	vp->text = s;
376	vp->name_len = nlen;
377	vp->next = *vpp;
378	vp->func = NULL;
379	INTOFF;
380	*vpp = vp;
381	if ((vp->flags & VEXPORT) && localevar(s)) {
382		change_env(s, 1);
383		(void) setlocale(LC_ALL, "");
384		updatecharset();
385	}
386	INTON;
387}
388
389
390
391/*
392 * Process a linked list of variable assignments.
393 */
394
395void
396listsetvar(struct strlist *list, int flags)
397{
398	struct strlist *lp;
399
400	INTOFF;
401	for (lp = list ; lp ; lp = lp->next) {
402		setvareq(savestr(lp->text), flags);
403	}
404	INTON;
405}
406
407
408
409/*
410 * Find the value of a variable.  Returns NULL if not set.
411 */
412
413char *
414lookupvar(const char *name)
415{
416	struct var *v;
417
418	v = find_var(name, NULL, NULL);
419	if (v == NULL || v->flags & VUNSET)
420		return NULL;
421	return v->text + v->name_len + 1;
422}
423
424
425
426/*
427 * Search the environment of a builtin command.  If the second argument
428 * is nonzero, return the value of a variable even if it hasn't been
429 * exported.
430 */
431
432char *
433bltinlookup(const char *name, int doall)
434{
435	struct strlist *sp;
436	struct var *v;
437	char *result;
438
439	result = NULL;
440	for (sp = cmdenviron ; sp ; sp = sp->next) {
441		if (varequal(sp->text, name))
442			result = strchr(sp->text, '=') + 1;
443	}
444	if (result != NULL)
445		return result;
446
447	v = find_var(name, NULL, NULL);
448	if (v == NULL || v->flags & VUNSET ||
449	    (!doall && (v->flags & VEXPORT) == 0))
450		return NULL;
451	return v->text + v->name_len + 1;
452}
453
454
455/*
456 * Set up locale for a builtin (LANG/LC_* assignments).
457 */
458void
459bltinsetlocale(void)
460{
461	struct strlist *lp;
462	int act = 0;
463	char *loc, *locdef;
464	int i;
465
466	for (lp = cmdenviron ; lp ; lp = lp->next) {
467		if (localevar(lp->text)) {
468			act = 1;
469			break;
470		}
471	}
472	if (!act)
473		return;
474	loc = bltinlookup("LC_ALL", 0);
475	INTOFF;
476	if (loc != NULL) {
477		setlocale(LC_ALL, loc);
478		INTON;
479		updatecharset();
480		return;
481	}
482	locdef = bltinlookup("LANG", 0);
483	for (i = 0; locale_names[i] != NULL; i++) {
484		loc = bltinlookup(locale_names[i], 0);
485		if (loc == NULL)
486			loc = locdef;
487		if (loc != NULL)
488			setlocale(locale_categories[i], loc);
489	}
490	INTON;
491	updatecharset();
492}
493
494/*
495 * Undo the effect of bltinlocaleset().
496 */
497void
498bltinunsetlocale(void)
499{
500	struct strlist *lp;
501
502	INTOFF;
503	for (lp = cmdenviron ; lp ; lp = lp->next) {
504		if (localevar(lp->text)) {
505			setlocale(LC_ALL, "");
506			updatecharset();
507			return;
508		}
509	}
510	INTON;
511}
512
513/*
514 * Update the localeisutf8 flag.
515 */
516void
517updatecharset(void)
518{
519	char *charset;
520
521	charset = nl_langinfo(CODESET);
522	localeisutf8 = !strcmp(charset, "UTF-8");
523}
524
525void
526initcharset(void)
527{
528	updatecharset();
529	initial_localeisutf8 = localeisutf8;
530}
531
532/*
533 * Generate a list of exported variables.  This routine is used to construct
534 * the third argument to execve when executing a program.
535 */
536
537char **
538environment(void)
539{
540	int nenv;
541	struct var **vpp;
542	struct var *vp;
543	char **env, **ep;
544
545	nenv = 0;
546	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
547		for (vp = *vpp ; vp ; vp = vp->next)
548			if (vp->flags & VEXPORT)
549				nenv++;
550	}
551	ep = env = stalloc((nenv + 1) * sizeof *env);
552	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
553		for (vp = *vpp ; vp ; vp = vp->next)
554			if (vp->flags & VEXPORT)
555				*ep++ = vp->text;
556	}
557	*ep = NULL;
558	return env;
559}
560
561
562static int
563var_compare(const void *a, const void *b)
564{
565	const char *const *sa, *const *sb;
566
567	sa = a;
568	sb = b;
569	/*
570	 * This compares two var=value strings which creates a different
571	 * order from what you would probably expect.  POSIX is somewhat
572	 * ambiguous on what should be sorted exactly.
573	 */
574	return strcoll(*sa, *sb);
575}
576
577
578/*
579 * Command to list all variables which are set.  This is invoked from the
580 * set command when it is called without any options or operands.
581 */
582
583int
584showvarscmd(int argc __unused, char **argv __unused)
585{
586	struct var **vpp;
587	struct var *vp;
588	const char *s;
589	const char **vars;
590	int i, n;
591
592	/*
593	 * POSIX requires us to sort the variables.
594	 */
595	n = 0;
596	for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
597		for (vp = *vpp; vp; vp = vp->next) {
598			if (!(vp->flags & VUNSET))
599				n++;
600		}
601	}
602
603	INTON;
604	vars = ckmalloc(n * sizeof(*vars));
605	i = 0;
606	for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
607		for (vp = *vpp; vp; vp = vp->next) {
608			if (!(vp->flags & VUNSET))
609				vars[i++] = vp->text;
610		}
611	}
612
613	qsort(vars, n, sizeof(*vars), var_compare);
614	for (i = 0; i < n; i++) {
615		s = strchr(vars[i], '=');
616		s++;
617		outbin(vars[i], s - vars[i], out1);
618		out1qstr(s);
619		out1c('\n');
620	}
621	ckfree(vars);
622	INTOFF;
623
624	return 0;
625}
626
627
628
629/*
630 * The export and readonly commands.
631 */
632
633int
634exportcmd(int argc, char **argv)
635{
636	struct var **vpp;
637	struct var *vp;
638	char *name;
639	char *p;
640	char *cmdname;
641	int ch, values;
642	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
643
644	cmdname = argv[0];
645	optreset = optind = 1;
646	opterr = 0;
647	values = 0;
648	while ((ch = getopt(argc, argv, "p")) != -1) {
649		switch (ch) {
650		case 'p':
651			values = 1;
652			break;
653		case '?':
654		default:
655			error("unknown option: -%c", optopt);
656		}
657	}
658	argc -= optind;
659	argv += optind;
660
661	if (values && argc != 0)
662		error("-p requires no arguments");
663	if (argc != 0) {
664		while ((name = *argv++) != NULL) {
665			if ((p = strchr(name, '=')) != NULL) {
666				p++;
667			} else {
668				vp = find_var(name, NULL, NULL);
669				if (vp != NULL) {
670					vp->flags |= flag;
671					if ((vp->flags & VEXPORT) && localevar(vp->text)) {
672						change_env(vp->text, 1);
673						(void) setlocale(LC_ALL, "");
674						updatecharset();
675					}
676					continue;
677				}
678			}
679			setvar(name, p, flag);
680		}
681	} else {
682		for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
683			for (vp = *vpp ; vp ; vp = vp->next) {
684				if (vp->flags & flag) {
685					if (values) {
686						out1str(cmdname);
687						out1c(' ');
688					}
689					if (values && !(vp->flags & VUNSET)) {
690						outbin(vp->text,
691						    vp->name_len + 1, out1);
692						out1qstr(vp->text +
693						    vp->name_len + 1);
694					} else
695						outbin(vp->text, vp->name_len,
696						    out1);
697					out1c('\n');
698				}
699			}
700		}
701	}
702	return 0;
703}
704
705
706/*
707 * The "local" command.
708 */
709
710int
711localcmd(int argc __unused, char **argv __unused)
712{
713	char *name;
714
715	if (! in_function())
716		error("Not in a function");
717	while ((name = *argptr++) != NULL) {
718		mklocal(name);
719	}
720	return 0;
721}
722
723
724/*
725 * Make a variable a local variable.  When a variable is made local, it's
726 * value and flags are saved in a localvar structure.  The saved values
727 * will be restored when the shell function returns.  We handle the name
728 * "-" as a special case.
729 */
730
731void
732mklocal(char *name)
733{
734	struct localvar *lvp;
735	struct var **vpp;
736	struct var *vp;
737
738	INTOFF;
739	lvp = ckmalloc(sizeof (struct localvar));
740	if (name[0] == '-' && name[1] == '\0') {
741		lvp->text = ckmalloc(sizeof optlist);
742		memcpy(lvp->text, optlist, sizeof optlist);
743		vp = NULL;
744	} else {
745		vp = find_var(name, &vpp, NULL);
746		if (vp == NULL) {
747			if (strchr(name, '='))
748				setvareq(savestr(name), VSTRFIXED | VNOLOCAL);
749			else
750				setvar(name, NULL, VSTRFIXED | VNOLOCAL);
751			vp = *vpp;	/* the new variable */
752			lvp->text = NULL;
753			lvp->flags = VUNSET;
754		} else {
755			lvp->text = vp->text;
756			lvp->flags = vp->flags;
757			vp->flags |= VSTRFIXED|VTEXTFIXED;
758			if (name[vp->name_len] == '=')
759				setvareq(savestr(name), VNOLOCAL);
760		}
761	}
762	lvp->vp = vp;
763	lvp->next = localvars;
764	localvars = lvp;
765	INTON;
766}
767
768
769/*
770 * Called after a function returns.
771 */
772
773void
774poplocalvars(void)
775{
776	struct localvar *lvp;
777	struct var *vp;
778
779	while ((lvp = localvars) != NULL) {
780		localvars = lvp->next;
781		vp = lvp->vp;
782		if (vp == NULL) {	/* $- saved */
783			memcpy(optlist, lvp->text, sizeof optlist);
784			ckfree(lvp->text);
785			optschanged();
786		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
787			(void)unsetvar(vp->text);
788		} else {
789			if ((vp->flags & VTEXTFIXED) == 0)
790				ckfree(vp->text);
791			vp->flags = lvp->flags;
792			vp->text = lvp->text;
793		}
794		ckfree(lvp);
795	}
796}
797
798
799int
800setvarcmd(int argc, char **argv)
801{
802	if (argc <= 2)
803		return unsetcmd(argc, argv);
804	else if (argc == 3)
805		setvar(argv[1], argv[2], 0);
806	else
807		error("too many arguments");
808	return 0;
809}
810
811
812/*
813 * The unset builtin command.
814 */
815
816int
817unsetcmd(int argc __unused, char **argv __unused)
818{
819	char **ap;
820	int i;
821	int flg_func = 0;
822	int flg_var = 0;
823	int ret = 0;
824
825	while ((i = nextopt("vf")) != '\0') {
826		if (i == 'f')
827			flg_func = 1;
828		else
829			flg_var = 1;
830	}
831	if (flg_func == 0 && flg_var == 0)
832		flg_var = 1;
833
834	for (ap = argptr; *ap ; ap++) {
835		if (flg_func)
836			ret |= unsetfunc(*ap);
837		if (flg_var)
838			ret |= unsetvar(*ap);
839	}
840	return ret;
841}
842
843
844/*
845 * Unset the specified variable.
846 */
847
848int
849unsetvar(const char *s)
850{
851	struct var **vpp;
852	struct var *vp;
853
854	vp = find_var(s, &vpp, NULL);
855	if (vp == NULL)
856		return (0);
857	if (vp->flags & VREADONLY)
858		return (1);
859	INTOFF;
860	if (vp->text[vp->name_len + 1] != '\0')
861		setvar(s, nullstr, 0);
862	if ((vp->flags & VEXPORT) && localevar(vp->text)) {
863		change_env(s, 0);
864		setlocale(LC_ALL, "");
865		updatecharset();
866	}
867	vp->flags &= ~VEXPORT;
868	vp->flags |= VUNSET;
869	if ((vp->flags & VSTRFIXED) == 0) {
870		if ((vp->flags & VTEXTFIXED) == 0)
871			ckfree(vp->text);
872		*vpp = vp->next;
873		ckfree(vp);
874	}
875	INTON;
876	return (0);
877}
878
879
880
881/*
882 * Returns true if the two strings specify the same varable.  The first
883 * variable name is terminated by '='; the second may be terminated by
884 * either '=' or '\0'.
885 */
886
887static int
888varequal(const char *p, const char *q)
889{
890	while (*p == *q++) {
891		if (*p++ == '=')
892			return 1;
893	}
894	if (*p == '=' && *(q - 1) == '\0')
895		return 1;
896	return 0;
897}
898
899/*
900 * Search for a variable.
901 * 'name' may be terminated by '=' or a NUL.
902 * vppp is set to the pointer to vp, or the list head if vp isn't found
903 * lenp is set to the number of charactets in 'name'
904 */
905
906static struct var *
907find_var(const char *name, struct var ***vppp, int *lenp)
908{
909	unsigned int hashval;
910	int len;
911	struct var *vp, **vpp;
912	const char *p = name;
913
914	hashval = 0;
915	while (*p && *p != '=')
916		hashval = 2 * hashval + (unsigned char)*p++;
917	len = p - name;
918
919	if (lenp)
920		*lenp = len;
921	vpp = &vartab[hashval % VTABSIZE];
922	if (vppp)
923		*vppp = vpp;
924
925	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
926		if (vp->name_len != len)
927			continue;
928		if (memcmp(vp->text, name, len) != 0)
929			continue;
930		if (vppp)
931			*vppp = vpp;
932		return vp;
933	}
934	return NULL;
935}
936