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