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