Merge: FreeBSD (RELENG_4) ip_fw2.c rev. 1.6.2.19
[dragonfly.git] / bin / sh / var.c
... / ...
CommitLineData
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.3 2003/08/24 16:26:00 drhodus 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
72struct varinit {
73 struct var *var;
74 int flags;
75 char *text;
76 void (*func)(const char *);
77};
78
79
80#if ATTY
81struct var vatty;
82#endif
83#ifndef NO_HISTORY
84struct var vhistsize;
85#endif
86struct var vifs;
87struct var vmail;
88struct var vmpath;
89struct var vpath;
90struct var vppid;
91struct var vps1;
92struct var vps2;
93struct var vvers;
94#if ATTY
95STATIC struct var vterm;
96#endif
97STATIC struct var voptind;
98
99STATIC 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
133STATIC struct var *vartab[VTABSIZE];
134
135STATIC struct var **hashvar(char *);
136STATIC int varequal(char *, char *);
137STATIC int localevar(char *);
138
139/*
140 * Initialize the varable symbol tables and import the environment
141 */
142
143#ifdef mkinit
144INCLUDE "var.h"
145INIT {
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
164void
165initvar(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
202int
203setvarsafe(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
228void
229setvar(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
270STATIC int
271localevar(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
298void
299setvareq(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
360void
361listsetvar(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
378char *
379lookupvar(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
401char *
402bltinlookup(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
429char **
430environment(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
461MKINIT void shprocvar();
462
463SHELLPROC {
464 shprocvar();
465}
466#endif
467
468void
469shprocvar(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
502int
503showvarscmd(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
529int
530exportcmd(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);
577found:;
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
606int
607localcmd(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
627void
628mklocal(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
670void
671poplocalvars(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
695int
696setvarcmd(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
714int
715unsetcmd(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
746int
747unsetvar(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
786STATIC struct var **
787hashvar(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
805STATIC int
806varequal(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}