• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*	$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $	*/
2  
3  /*-
4   * Copyright (c) 1991, 1993
5   *	The Regents of the University of California.  All rights reserved.
6   *
7   * This code is derived from software contributed to Berkeley by
8   * Kenneth Almquist.
9   *
10   * Redistribution and use in source and binary forms, with or without
11   * modification, are permitted provided that the following conditions
12   * are met:
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in the
17   *    documentation and/or other materials provided with the distribution.
18   * 3. Neither the name of the University nor the names of its contributors
19   *    may be used to endorse or promote products derived from this software
20   *    without specific prior written permission.
21   *
22   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32   * SUCH DAMAGE.
33   */
34  
35  #include <sys/cdefs.h>
36  #ifndef lint
37  #if 0
38  static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
39  #else
40  __RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
41  #endif
42  #endif /* not lint */
43  
44  #include <unistd.h>
45  #include <stdlib.h>
46  #include <paths.h>
47  
48  /*
49   * Shell variables.
50   */
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 "var.h"
61  #include "memalloc.h"
62  #include "error.h"
63  #include "mystring.h"
64  #include "parser.h"
65  #include "show.h"
66  #ifndef SMALL
67  #include "myhistedit.h"
68  #endif
69  
70  #ifdef SMALL
71  #define VTABSIZE 39
72  #else
73  #define VTABSIZE 517
74  #endif
75  
76  
77  struct varinit {
78  	struct var *var;
79  	int flags;
80  	const char *text;
81  	void (*func)(const char *);
82  };
83  
84  
85  #if ATTY
86  struct var vatty;
87  #endif
88  #ifdef WITH_HISTORY
89  struct var vhistsize;
90  struct var vterm;
91  #endif
92  struct var vifs;
93  struct var vmpath;
94  struct var vpath;
95  struct var vps1;
96  struct var vps2;
97  struct var vps4;
98  struct var vvers;
99  struct var voptind;
100  
101  const struct varinit varinit[] = {
102  #if ATTY
103  	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
104  	  NULL },
105  #endif
106  #ifdef WITH_HISTORY
107  	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
108  	  sethistsize },
109  #endif
110  	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
111  	  NULL },
112  	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
113  	  NULL },
114  	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
115  	  changepath },
116  	/*
117  	 * vps1 depends on uid
118  	 */
119  	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
120  	  NULL },
121  	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
122  	  NULL },
123  #ifdef WITH_HISTORY
124  	{ &vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",
125  	  setterm },
126  #endif
127  	{ &voptind,	VSTRFIXED|VTEXTFIXED|VNOFUNC,	"OPTIND=1",
128  	  getoptsreset },
129  	{ NULL,	0,				NULL,
130  	  NULL }
131  };
132  
133  struct var *vartab[VTABSIZE];
134  
135  STATIC int strequal(const char *, const char *);
136  STATIC struct var *find_var(const char *, struct var ***, int *);
137  
138  /*
139   * Initialize the varable symbol tables and import the environment
140   */
141  
142  #ifdef mkinit
143  INCLUDE "var.h"
144  MKINIT char **environ;
145  INIT {
146  	char **envp;
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  
163  void
initvar(void)164  initvar(void)
165  {
166  	const struct varinit *ip;
167  	struct var *vp;
168  	struct var **vpp;
169  
170  	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
171  		if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
172  			continue;
173  		vp->next = *vpp;
174  		*vpp = vp;
175  		vp->text = strdup(ip->text);
176  		vp->flags = ip->flags;
177  		vp->func = ip->func;
178  	}
179  	/*
180  	 * PS1 depends on uid
181  	 */
182  	if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
183  		vps1.next = *vpp;
184  		*vpp = &vps1;
185  		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
186  		vps1.flags = VSTRFIXED|VTEXTFIXED;
187  	}
188  }
189  
190  /*
191   * Safe version of setvar, returns 1 on success 0 on failure.
192   */
193  
194  int
setvarsafe(const char * name,const char * val,int flags)195  setvarsafe(const char *name, const char *val, int flags)
196  {
197  	struct jmploc jmploc;
198  	struct jmploc *volatile savehandler = handler;
199  	int err = 0;
200  #ifdef __GNUC__
201  	(void) &err;
202  #endif
203  
204  	if (setjmp(jmploc.loc))
205  		err = 1;
206  	else {
207  		handler = &jmploc;
208  		setvar(name, val, flags);
209  	}
210  	handler = savehandler;
211  	return err;
212  }
213  
214  /*
215   * Set the value of a variable.  The flags argument is ored with the
216   * flags of the variable.  If val is NULL, the variable is unset.
217   */
218  
219  void
setvar(const char * name,const char * val,int flags)220  setvar(const char *name, const char *val, int flags)
221  {
222  	const char *p;
223  	const char *q;
224  	char *d;
225  	int len;
226  	int namelen;
227  	char *nameeq;
228  	int isbad;
229  
230  	isbad = 0;
231  	p = name;
232  	if (! is_name(*p))
233  		isbad = 1;
234  	p++;
235  	for (;;) {
236  		if (! is_in_name(*p)) {
237  			if (*p == '\0' || *p == '=')
238  				break;
239  			isbad = 1;
240  		}
241  		p++;
242  	}
243  	namelen = p - name;
244  	if (isbad)
245  		error("%.*s: bad variable name", namelen, name);
246  	len = namelen + 2;		/* 2 is space for '=' and '\0' */
247  	if (val == NULL) {
248  		flags |= VUNSET;
249  	} else {
250  		len += strlen(val);
251  	}
252  	d = nameeq = ckmalloc(len);
253  	q = name;
254  	while (--namelen >= 0)
255  		*d++ = *q++;
256  	*d++ = '=';
257  	*d = '\0';
258  	if (val)
259  		scopy(val, d);
260  	setvareq(nameeq, flags);
261  }
262  
263  
264  
265  /*
266   * Same as setvar except that the variable and value are passed in
267   * the first argument as name=value.  Since the first argument will
268   * be actually stored in the table, it should not be a string that
269   * will go away.
270   */
271  
272  void
setvareq(char * s,int flags)273  setvareq(char *s, int flags)
274  {
275  	struct var *vp, **vpp;
276  	int nlen;
277  
278  	if (aflag)
279  		flags |= VEXPORT;
280  	vp = find_var(s, &vpp, &nlen);
281  	if (vp != NULL) {
282  		if (vp->flags & VREADONLY)
283  			error("%.*s: is read only", vp->name_len, s);
284  		if (flags & VNOSET)
285  			return;
286  		INTOFF;
287  
288  		if (vp->func && (flags & VNOFUNC) == 0)
289  			(*vp->func)(s + vp->name_len + 1);
290  
291  		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
292  			ckfree(vp->text);
293  
294  		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
295  		vp->flags |= flags & ~VNOFUNC;
296  		vp->text = s;
297  
298  		INTON;
299  		return;
300  	}
301  	/* not found */
302  	if (flags & VNOSET)
303  		return;
304  	vp = ckmalloc(sizeof (*vp));
305  	vp->flags = flags & ~VNOFUNC;
306  	vp->text = s;
307  	vp->name_len = nlen;
308  	vp->next = *vpp;
309  	vp->func = NULL;
310  	*vpp = vp;
311  }
312  
313  
314  
315  /*
316   * Process a linked list of variable assignments.
317   */
318  
319  void
listsetvar(struct strlist * list,int flags)320  listsetvar(struct strlist *list, int flags)
321  {
322  	struct strlist *lp;
323  
324  	INTOFF;
325  	for (lp = list ; lp ; lp = lp->next) {
326  		setvareq(savestr(lp->text), flags);
327  	}
328  	INTON;
329  }
330  
331  void
listmklocal(struct strlist * list,int flags)332  listmklocal(struct strlist *list, int flags)
333  {
334  	struct strlist *lp;
335  
336  	for (lp = list ; lp ; lp = lp->next)
337  		mklocal(lp->text, flags);
338  }
339  
340  
341  /*
342   * Find the value of a variable.  Returns NULL if not set.
343   */
344  
345  char *
lookupvar(const char * name)346  lookupvar(const char *name)
347  {
348  	struct var *v;
349  
350  	v = find_var(name, NULL, NULL);
351  	if (v == NULL || v->flags & VUNSET)
352  		return NULL;
353  	return v->text + v->name_len + 1;
354  }
355  
356  
357  
358  /*
359   * Search the environment of a builtin command.  If the second argument
360   * is nonzero, return the value of a variable even if it hasn't been
361   * exported.
362   */
363  
364  char *
bltinlookup(const char * name,int doall)365  bltinlookup(const char *name, int doall)
366  {
367  	struct strlist *sp;
368  	struct var *v;
369  
370  	for (sp = cmdenviron ; sp ; sp = sp->next) {
371  		if (strequal(sp->text, name))
372  			return strchr(sp->text, '=') + 1;
373  	}
374  
375  	v = find_var(name, NULL, NULL);
376  
377  	if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
378  		return NULL;
379  	return v->text + v->name_len + 1;
380  }
381  
382  
383  
384  /*
385   * Generate a list of exported variables.  This routine is used to construct
386   * the third argument to execve when executing a program.
387   */
388  
389  char **
environment(void)390  environment(void)
391  {
392  	int nenv;
393  	struct var **vpp;
394  	struct var *vp;
395  	char **env;
396  	char **ep;
397  
398  	nenv = 0;
399  	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
400  		for (vp = *vpp ; vp ; vp = vp->next)
401  			if (vp->flags & VEXPORT)
402  				nenv++;
403  	}
404  	ep = env = stalloc((nenv + 1) * sizeof *env);
405  	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
406  		for (vp = *vpp ; vp ; vp = vp->next)
407  			if (vp->flags & VEXPORT)
408  				*ep++ = vp->text;
409  	}
410  	*ep = NULL;
411  	return env;
412  }
413  
414  
415  /*
416   * Called when a shell procedure is invoked to clear out nonexported
417   * variables.  It is also necessary to reallocate variables of with
418   * VSTACK set since these are currently allocated on the stack.
419   */
420  
421  #ifdef mkinit
422  void shprocvar(void);
423  
424  SHELLPROC {
425  	shprocvar();
426  }
427  #endif
428  
429  void
shprocvar(void)430  shprocvar(void)
431  {
432  	struct var **vpp;
433  	struct var *vp, **prev;
434  
435  	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
436  		for (prev = vpp ; (vp = *prev) != NULL ; ) {
437  			if ((vp->flags & VEXPORT) == 0) {
438  				*prev = vp->next;
439  				if ((vp->flags & VTEXTFIXED) == 0)
440  					ckfree(vp->text);
441  				if ((vp->flags & VSTRFIXED) == 0)
442  					ckfree(vp);
443  			} else {
444  				if (vp->flags & VSTACK) {
445  					vp->text = savestr(vp->text);
446  					vp->flags &=~ VSTACK;
447  				}
448  				prev = &vp->next;
449  			}
450  		}
451  	}
452  	initvar();
453  }
454  
455  
456  
457  /*
458   * Command to list all variables which are set.  Currently this command
459   * is invoked from the set command when the set command is called without
460   * any variables.
461   */
462  
463  void
print_quoted(const char * p)464  print_quoted(const char *p)
465  {
466  	const char *q;
467  
468  	if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
469  		out1fmt("%s", p);
470  		return;
471  	}
472  	while (*p) {
473  		if (*p == '\'') {
474  			out1fmt("\\'");
475  			p++;
476  			continue;
477  		}
478  		q = index(p, '\'');
479  		if (!q) {
480  			out1fmt("'%s'", p );
481  			return;
482  		}
483  		out1fmt("'%.*s'", (int)(q - p), p );
484  		p = q;
485  	}
486  }
487  
488  static int
sort_var(const void * v_v1,const void * v_v2)489  sort_var(const void *v_v1, const void *v_v2)
490  {
491  	const struct var * const *v1 = v_v1;
492  	const struct var * const *v2 = v_v2;
493  
494  	/* XXX Will anyone notice we include the '=' of the shorter name? */
495  	return strcmp((*v1)->text, (*v2)->text);
496  }
497  
498  /*
499   * POSIX requires that 'set' (but not export or readonly) output the
500   * variables in lexicographic order - by the locale's collating order (sigh).
501   * Maybe we could keep them in an ordered balanced binary tree
502   * instead of hashed lists.
503   * For now just roll 'em through qsort for printing...
504   */
505  
506  int
showvars(const char * name,int flag,int show_value)507  showvars(const char *name, int flag, int show_value)
508  {
509  	struct var **vpp;
510  	struct var *vp;
511  	const char *p;
512  
513  	static struct var **list;	/* static in case we are interrupted */
514  	static int list_len;
515  	int count = 0;
516  
517  	if (!list) {
518  		list_len = 32;
519  		list = ckmalloc(list_len * sizeof *list);
520  	}
521  
522  	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
523  		for (vp = *vpp ; vp ; vp = vp->next) {
524  			if (flag && !(vp->flags & flag))
525  				continue;
526  			if (vp->flags & VUNSET && !(show_value & 2))
527  				continue;
528  			if (count >= list_len) {
529  				list = ckrealloc(list,
530  					(list_len << 1) * sizeof *list);
531  				list_len <<= 1;
532  			}
533  			list[count++] = vp;
534  		}
535  	}
536  
537  	qsort(list, count, sizeof *list, sort_var);
538  
539  	for (vpp = list; count--; vpp++) {
540  		vp = *vpp;
541  		if (name)
542  			out1fmt("%s ", name);
543  		for (p = vp->text ; *p != '=' ; p++)
544  			out1c(*p);
545  		if (!(vp->flags & VUNSET) && show_value) {
546  			out1fmt("=");
547  			print_quoted(++p);
548  		}
549  		out1c('\n');
550  	}
551  	return 0;
552  }
553  
554  
555  
556  /*
557   * The export and readonly commands.
558   */
559  
560  int
exportcmd(int argc,char ** argv)561  exportcmd(int argc, char **argv)
562  {
563  	struct var *vp;
564  	char *name;
565  	const char *p;
566  	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
567  	int pflag;
568  
569  	pflag = nextopt("p") == 'p' ? 3 : 0;
570  	if (argc <= 1 || pflag) {
571  		showvars( pflag ? argv[0] : 0, flag, pflag );
572  		return 0;
573  	}
574  
575  	while ((name = *argptr++) != NULL) {
576  		if ((p = strchr(name, '=')) != NULL) {
577  			p++;
578  		} else {
579  			vp = find_var(name, NULL, NULL);
580  			if (vp != NULL) {
581  				vp->flags |= flag;
582  				continue;
583  			}
584  		}
585  		setvar(name, p, flag);
586  	}
587  	return 0;
588  }
589  
590  
591  /*
592   * The "local" command.
593   */
594  
595  int
localcmd(int argc,char ** argv)596  localcmd(int argc, char **argv)
597  {
598  	char *name;
599  
600  	if (! in_function())
601  		error("Not in a function");
602  	while ((name = *argptr++) != NULL) {
603  		mklocal(name, 0);
604  	}
605  	return 0;
606  }
607  
608  
609  /*
610   * Make a variable a local variable.  When a variable is made local, it's
611   * value and flags are saved in a localvar structure.  The saved values
612   * will be restored when the shell function returns.  We handle the name
613   * "-" as a special case.
614   */
615  
616  void
mklocal(const char * name,int flags)617  mklocal(const char *name, int flags)
618  {
619  	struct localvar *lvp;
620  	struct var **vpp;
621  	struct var *vp;
622  
623  	INTOFF;
624  	lvp = ckmalloc(sizeof (struct localvar));
625  	if (name[0] == '-' && name[1] == '\0') {
626  		char *p;
627  		p = ckmalloc(sizeof_optlist);
628  		lvp->text = memcpy(p, optlist, sizeof_optlist);
629  		vp = NULL;
630  	} else {
631  		vp = find_var(name, &vpp, NULL);
632  		if (vp == NULL) {
633  			if (strchr(name, '='))
634  				setvareq(savestr(name), VSTRFIXED|flags);
635  			else
636  				setvar(name, NULL, VSTRFIXED|flags);
637  			vp = *vpp;	/* the new variable */
638  			lvp->text = NULL;
639  			lvp->flags = VUNSET;
640  		} else {
641  			lvp->text = vp->text;
642  			lvp->flags = vp->flags;
643  			vp->flags |= VSTRFIXED|VTEXTFIXED;
644  			if (name[vp->name_len] == '=')
645  				setvareq(savestr(name), flags);
646  		}
647  	}
648  	lvp->vp = vp;
649  	lvp->next = localvars;
650  	localvars = lvp;
651  	INTON;
652  }
653  
654  
655  /*
656   * Called after a function returns.
657   */
658  
659  void
poplocalvars(void)660  poplocalvars(void)
661  {
662  	struct localvar *lvp;
663  	struct var *vp;
664  
665  	while ((lvp = localvars) != NULL) {
666  		localvars = lvp->next;
667  		vp = lvp->vp;
668  		TRACE(("poplocalvar %s", vp ? vp->text : "-"));
669  		if (vp == NULL) {	/* $- saved */
670  			memcpy(optlist, lvp->text, sizeof_optlist);
671  			ckfree(lvp->text);
672  		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
673  			(void)unsetvar(vp->text, 0);
674  		} else {
675  			if (vp->func && (vp->flags & VNOFUNC) == 0)
676  				(*vp->func)(lvp->text + vp->name_len + 1);
677  			if ((vp->flags & VTEXTFIXED) == 0)
678  				ckfree(vp->text);
679  			vp->flags = lvp->flags;
680  			vp->text = lvp->text;
681  		}
682  		ckfree(lvp);
683  	}
684  }
685  
686  
687  int
setvarcmd(int argc,char ** argv)688  setvarcmd(int argc, char **argv)
689  {
690  	if (argc <= 2)
691  		return unsetcmd(argc, argv);
692  	else if (argc == 3)
693  		setvar(argv[1], argv[2], 0);
694  	else
695  		error("List assignment not implemented");
696  	return 0;
697  }
698  
699  
700  /*
701   * The unset builtin command.  We unset the function before we unset the
702   * variable to allow a function to be unset when there is a readonly variable
703   * with the same name.
704   */
705  
706  int
unsetcmd(int argc,char ** argv)707  unsetcmd(int argc, char **argv)
708  {
709  	char **ap;
710  	int i;
711  	int flg_func = 0;
712  	int flg_var = 0;
713  	int ret = 0;
714  
715  	while ((i = nextopt("evf")) != '\0') {
716  		if (i == 'f')
717  			flg_func = 1;
718  		else
719  			flg_var = i;
720  	}
721  	if (flg_func == 0 && flg_var == 0)
722  		flg_var = 1;
723  
724  	for (ap = argptr; *ap ; ap++) {
725  		if (flg_func)
726  			ret |= unsetfunc(*ap);
727  		if (flg_var)
728  			ret |= unsetvar(*ap, flg_var == 'e');
729  	}
730  	return ret;
731  }
732  
733  
734  /*
735   * Unset the specified variable.
736   */
737  
738  int
unsetvar(const char * s,int unexport)739  unsetvar(const char *s, int unexport)
740  {
741  	struct var **vpp;
742  	struct var *vp;
743  
744  	vp = find_var(s, &vpp, NULL);
745  	if (vp == NULL)
746  		return 1;
747  
748  	if (vp->flags & VREADONLY)
749  		return (1);
750  
751  	INTOFF;
752  	if (unexport) {
753  		vp->flags &= ~VEXPORT;
754  	} else {
755  		if (vp->text[vp->name_len + 1] != '\0')
756  			setvar(s, nullstr, 0);
757  		vp->flags &= ~VEXPORT;
758  		vp->flags |= VUNSET;
759  		if ((vp->flags & VSTRFIXED) == 0) {
760  			if ((vp->flags & VTEXTFIXED) == 0)
761  				ckfree(vp->text);
762  			*vpp = vp->next;
763  			ckfree(vp);
764  		}
765  	}
766  	INTON;
767  	return 0;
768  }
769  
770  
771  /*
772   * Returns true if the two strings specify the same varable.  The first
773   * variable name is terminated by '='; the second may be terminated by
774   * either '=' or '\0'.
775   */
776  
777  STATIC int
strequal(const char * p,const char * q)778  strequal(const char *p, const char *q)
779  {
780  	while (*p == *q++) {
781  		if (*p++ == '=')
782  			return 1;
783  	}
784  	if (*p == '=' && *(q - 1) == '\0')
785  		return 1;
786  	return 0;
787  }
788  
789  /*
790   * Search for a variable.
791   * 'name' may be terminated by '=' or a NUL.
792   * vppp is set to the pointer to vp, or the list head if vp isn't found
793   * lenp is set to the number of charactets in 'name'
794   */
795  
796  STATIC struct var *
find_var(const char * name,struct var *** vppp,int * lenp)797  find_var(const char *name, struct var ***vppp, int *lenp)
798  {
799  	unsigned int hashval;
800  	int len;
801  	struct var *vp, **vpp;
802  	const char *p = name;
803  
804  	hashval = 0;
805  	while (*p && *p != '=')
806  		hashval = 2 * hashval + (unsigned char)*p++;
807  	len = p - name;
808  
809  	if (lenp)
810  		*lenp = len;
811  	vpp = &vartab[hashval % VTABSIZE];
812  	if (vppp)
813  		*vppp = vpp;
814  
815  	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
816  		if (vp->name_len != len)
817  			continue;
818  		if (memcmp(vp->text, name, len) != 0)
819  			continue;
820  		if (vppp)
821  			*vppp = vpp;
822  		return vp;
823  	}
824  	return NULL;
825  }
826