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 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 05/04/95";
13 #endif /* not lint */
14
15 #include <unistd.h>
16 #include <stdlib.h>
17
18 /*
19 * Shell variables.
20 */
21
22 #include "shell.h"
23 #include "output.h"
24 #include "expand.h"
25 #include "nodes.h" /* for other headers */
26 #include "eval.h" /* defines cmdenviron */
27 #include "exec.h"
28 #include "syntax.h"
29 #include "options.h"
30 #include "mail.h"
31 #include "var.h"
32 #include "memalloc.h"
33 #include "error.h"
34 #include "mystring.h"
35 #ifndef NO_HISTORY
36 #include "myhistedit.h"
37 #endif
38
39
40 #define VTABSIZE 39
41
42
43 struct varinit {
44 struct var *var;
45 int flags;
46 char *text;
47 };
48
49
50 #if ATTY
51 struct var vatty;
52 #endif
53 #ifndef NO_HISTORY
54 struct var vhistsize;
55 #endif
56 struct var vifs;
57 struct var vmail;
58 struct var vmpath;
59 struct var vpath;
60 struct var vps1;
61 struct var vps2;
62 struct var vvers;
63 #if ATTY
64 struct var vterm;
65 #endif
66
67 const struct varinit varinit[] = {
68 #if ATTY
69 {&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
70 #endif
71 #ifndef NO_HISTORY
72 {&vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE="},
73 #endif
74 {&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
75 {&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
76 {&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
77 {&vpath, VSTRFIXED|VTEXTFIXED, "PATH=/bin:/usr/bin"},
78 /*
79 * vps1 depends on uid
80 */
81 {&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
82 #if ATTY
83 {&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
84 #endif
85 {NULL, 0, NULL}
86 };
87
88 struct var *vartab[VTABSIZE];
89
90 STATIC int unsetvar __P((char *));
91 STATIC struct var **hashvar __P((char *));
92 STATIC int varequal __P((char *, char *));
93
94 /*
95 * Initialize the varable symbol tables and import the environment
96 */
97
98 #ifdef mkinit
99 INCLUDE "var.h"
100 INIT {
101 char **envp;
102 extern char **environ;
103
104 initvar();
105 for (envp = environ ; *envp ; envp++) {
106 if (strchr(*envp, '=')) {
107 setvareq(*envp, VEXPORT|VTEXTFIXED);
108 }
109 }
110 }
111 #endif
112
113
114 /*
115 * This routine initializes the builtin variables. It is called when the
116 * shell is initialized and again when a shell procedure is spawned.
117 */
118
119 void
initvar()120 initvar() {
121 const struct varinit *ip;
122 struct var *vp;
123 struct var **vpp;
124
125 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
126 if ((vp->flags & VEXPORT) == 0) {
127 vpp = hashvar(ip->text);
128 vp->next = *vpp;
129 *vpp = vp;
130 vp->text = ip->text;
131 vp->flags = ip->flags;
132 }
133 }
134 /*
135 * PS1 depends on uid
136 */
137 if ((vps1.flags & VEXPORT) == 0) {
138 vpp = hashvar("PS1=");
139 vps1.next = *vpp;
140 *vpp = &vps1;
141 vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
142 vps1.flags = VSTRFIXED|VTEXTFIXED;
143 }
144 }
145
146 /*
147 * Set the value of a variable. The flags argument is ored with the
148 * flags of the variable. If val is NULL, the variable is unset.
149 */
150
151 void
setvar(name,val,flags)152 setvar(name, val, flags)
153 char *name, *val;
154 int flags;
155 {
156 char *p, *q;
157 int len;
158 int namelen;
159 char *nameeq;
160 int isbad;
161
162 isbad = 0;
163 p = name;
164 if (! is_name(*p++))
165 isbad = 1;
166 for (;;) {
167 if (! is_in_name(*p)) {
168 if (*p == '\0' || *p == '=')
169 break;
170 isbad = 1;
171 }
172 p++;
173 }
174 namelen = p - name;
175 if (isbad)
176 error("%.*s: bad variable name", namelen, name);
177 len = namelen + 2; /* 2 is space for '=' and '\0' */
178 if (val == NULL) {
179 flags |= VUNSET;
180 } else {
181 len += strlen(val);
182 }
183 p = nameeq = ckmalloc(len);
184 q = name;
185 while (--namelen >= 0)
186 *p++ = *q++;
187 *p++ = '=';
188 *p = '\0';
189 if (val)
190 scopy(val, p);
191 setvareq(nameeq, flags);
192 }
193
194
195
196 /*
197 * Same as setvar except that the variable and value are passed in
198 * the first argument as name=value. Since the first argument will
199 * be actually stored in the table, it should not be a string that
200 * will go away.
201 */
202
203 void
setvareq(s,flags)204 setvareq(s, flags)
205 char *s;
206 int flags;
207 {
208 struct var *vp, **vpp;
209
210 vpp = hashvar(s);
211 for (vp = *vpp ; vp ; vp = vp->next) {
212 if (varequal(s, vp->text)) {
213 if (vp->flags & VREADONLY) {
214 int len = strchr(s, '=') - s;
215 error("%.*s: is read only", len, s);
216 }
217 INTOFF;
218 if (vp == &vpath)
219 changepath(s + 5); /* 5 = strlen("PATH=") */
220 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
221 ckfree(vp->text);
222 vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
223 vp->flags |= flags;
224 vp->text = s;
225 if (vp == &vmpath || (vp == &vmail && ! mpathset()))
226 chkmail(1);
227 #ifndef NO_HISTORY
228 if (vp == &vhistsize)
229 sethistsize();
230 #endif
231 INTON;
232 return;
233 }
234 }
235 /* not found */
236 vp = ckmalloc(sizeof (*vp));
237 vp->flags = flags;
238 vp->text = s;
239 vp->next = *vpp;
240 *vpp = vp;
241 }
242
243
244
245 /*
246 * Process a linked list of variable assignments.
247 */
248
249 void
listsetvar(list)250 listsetvar(list)
251 struct strlist *list;
252 {
253 struct strlist *lp;
254
255 INTOFF;
256 for (lp = list ; lp ; lp = lp->next) {
257 setvareq(savestr(lp->text), 0);
258 }
259 INTON;
260 }
261
262
263
264 /*
265 * Find the value of a variable. Returns NULL if not set.
266 */
267
268 char *
lookupvar(name)269 lookupvar(name)
270 char *name;
271 {
272 struct var *v;
273
274 for (v = *hashvar(name) ; v ; v = v->next) {
275 if (varequal(v->text, name)) {
276 if (v->flags & VUNSET)
277 return NULL;
278 return strchr(v->text, '=') + 1;
279 }
280 }
281 return NULL;
282 }
283
284
285
286 /*
287 * Search the environment of a builtin command. If the second argument
288 * is nonzero, return the value of a variable even if it hasn't been
289 * exported.
290 */
291
292 char *
bltinlookup(name,doall)293 bltinlookup(name, doall)
294 char *name;
295 int doall;
296 {
297 struct strlist *sp;
298 struct var *v;
299
300 for (sp = cmdenviron ; sp ; sp = sp->next) {
301 if (varequal(sp->text, name))
302 return strchr(sp->text, '=') + 1;
303 }
304 for (v = *hashvar(name) ; v ; v = v->next) {
305 if (varequal(v->text, name)) {
306 if ((v->flags & VUNSET)
307 || (!doall && (v->flags & VEXPORT) == 0))
308 return NULL;
309 return strchr(v->text, '=') + 1;
310 }
311 }
312 return NULL;
313 }
314
315
316
317 /*
318 * Generate a list of exported variables. This routine is used to construct
319 * the third argument to execve when executing a program.
320 */
321
322 char **
environment()323 environment() {
324 int nenv;
325 struct var **vpp;
326 struct var *vp;
327 char **env, **ep;
328
329 nenv = 0;
330 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
331 for (vp = *vpp ; vp ; vp = vp->next)
332 if (vp->flags & VEXPORT)
333 nenv++;
334 }
335 ep = env = stalloc((nenv + 1) * sizeof *env);
336 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
337 for (vp = *vpp ; vp ; vp = vp->next)
338 if (vp->flags & VEXPORT)
339 *ep++ = vp->text;
340 }
341 *ep = NULL;
342 return env;
343 }
344
345
346 /*
347 * Called when a shell procedure is invoked to clear out nonexported
348 * variables. It is also necessary to reallocate variables of with
349 * VSTACK set since these are currently allocated on the stack.
350 */
351
352 #ifdef mkinit
353 MKINIT void shprocvar();
354
355 SHELLPROC {
356 shprocvar();
357 }
358 #endif
359
360 void
shprocvar()361 shprocvar() {
362 struct var **vpp;
363 struct var *vp, **prev;
364
365 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
366 for (prev = vpp ; (vp = *prev) != NULL ; ) {
367 if ((vp->flags & VEXPORT) == 0) {
368 *prev = vp->next;
369 if ((vp->flags & VTEXTFIXED) == 0)
370 ckfree(vp->text);
371 if ((vp->flags & VSTRFIXED) == 0)
372 ckfree(vp);
373 } else {
374 if (vp->flags & VSTACK) {
375 vp->text = savestr(vp->text);
376 vp->flags &=~ VSTACK;
377 }
378 prev = &vp->next;
379 }
380 }
381 }
382 initvar();
383 }
384
385
386
387 /*
388 * Command to list all variables which are set. Currently this command
389 * is invoked from the set command when the set command is called without
390 * any variables.
391 */
392
393 int
showvarscmd(argc,argv)394 showvarscmd(argc, argv)
395 int argc;
396 char **argv;
397 {
398 struct var **vpp;
399 struct var *vp;
400
401 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
402 for (vp = *vpp ; vp ; vp = vp->next) {
403 if ((vp->flags & VUNSET) == 0)
404 out1fmt("%s\n", vp->text);
405 }
406 }
407 return 0;
408 }
409
410
411
412 /*
413 * The export and readonly commands.
414 */
415
416 int
exportcmd(argc,argv)417 exportcmd(argc, argv)
418 int argc;
419 char **argv;
420 {
421 struct var **vpp;
422 struct var *vp;
423 char *name;
424 char *p;
425 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
426
427 listsetvar(cmdenviron);
428 if (argc > 1) {
429 while ((name = *argptr++) != NULL) {
430 if ((p = strchr(name, '=')) != NULL) {
431 p++;
432 } else {
433 vpp = hashvar(name);
434 for (vp = *vpp ; vp ; vp = vp->next) {
435 if (varequal(vp->text, name)) {
436 vp->flags |= flag;
437 goto found;
438 }
439 }
440 }
441 setvar(name, p, flag);
442 found:;
443 }
444 } else {
445 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
446 for (vp = *vpp ; vp ; vp = vp->next) {
447 if (vp->flags & flag) {
448 for (p = vp->text ; *p != '=' ; p++)
449 out1c(*p);
450 out1c('\n');
451 }
452 }
453 }
454 }
455 return 0;
456 }
457
458
459 /*
460 * The "local" command.
461 */
462
463 int
localcmd(argc,argv)464 localcmd(argc, argv)
465 int argc;
466 char **argv;
467 {
468 char *name;
469
470 if (! in_function())
471 error("Not in a function");
472 while ((name = *argptr++) != NULL) {
473 mklocal(name);
474 }
475 return 0;
476 }
477
478
479 /*
480 * Make a variable a local variable. When a variable is made local, it's
481 * value and flags are saved in a localvar structure. The saved values
482 * will be restored when the shell function returns. We handle the name
483 * "-" as a special case.
484 */
485
486 void
mklocal(name)487 mklocal(name)
488 char *name;
489 {
490 struct localvar *lvp;
491 struct var **vpp;
492 struct var *vp;
493
494 INTOFF;
495 lvp = ckmalloc(sizeof (struct localvar));
496 if (name[0] == '-' && name[1] == '\0') {
497 lvp->text = ckmalloc(sizeof optlist);
498 memcpy(lvp->text, optlist, sizeof optlist);
499 vp = NULL;
500 } else {
501 vpp = hashvar(name);
502 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
503 if (vp == NULL) {
504 if (strchr(name, '='))
505 setvareq(savestr(name), VSTRFIXED);
506 else
507 setvar(name, NULL, VSTRFIXED);
508 vp = *vpp; /* the new variable */
509 lvp->text = NULL;
510 lvp->flags = VUNSET;
511 } else {
512 lvp->text = vp->text;
513 lvp->flags = vp->flags;
514 vp->flags |= VSTRFIXED|VTEXTFIXED;
515 if (strchr(name, '='))
516 setvareq(savestr(name), 0);
517 }
518 }
519 lvp->vp = vp;
520 lvp->next = localvars;
521 localvars = lvp;
522 INTON;
523 }
524
525
526 /*
527 * Called after a function returns.
528 */
529
530 void
poplocalvars()531 poplocalvars() {
532 struct localvar *lvp;
533 struct var *vp;
534
535 while ((lvp = localvars) != NULL) {
536 localvars = lvp->next;
537 vp = lvp->vp;
538 if (vp == NULL) { /* $- saved */
539 memcpy(optlist, lvp->text, sizeof optlist);
540 ckfree(lvp->text);
541 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
542 (void)unsetvar(vp->text);
543 } else {
544 if ((vp->flags & VTEXTFIXED) == 0)
545 ckfree(vp->text);
546 vp->flags = lvp->flags;
547 vp->text = lvp->text;
548 }
549 ckfree(lvp);
550 }
551 }
552
553
554 int
setvarcmd(argc,argv)555 setvarcmd(argc, argv)
556 int argc;
557 char **argv;
558 {
559 if (argc <= 2)
560 return unsetcmd(argc, argv);
561 else if (argc == 3)
562 setvar(argv[1], argv[2], 0);
563 else
564 error("List assignment not implemented");
565 return 0;
566 }
567
568
569 /*
570 * The unset builtin command. We unset the function before we unset the
571 * variable to allow a function to be unset when there is a readonly variable
572 * with the same name.
573 */
574
575 int
unsetcmd(argc,argv)576 unsetcmd(argc, argv)
577 int argc;
578 char **argv;
579 {
580 char **ap;
581 int i;
582 int flg_func = 0;
583 int flg_var = 0;
584 int ret = 0;
585
586 while ((i = nextopt("vf")) != '\0') {
587 if (i == 'f')
588 flg_func = 1;
589 else
590 flg_var = 1;
591 }
592 if (flg_func == 0 && flg_var == 0)
593 flg_var = 1;
594
595 for (ap = argptr; *ap ; ap++) {
596 if (flg_func)
597 ret |= unsetfunc(*ap);
598 if (flg_var)
599 ret |= unsetvar(*ap);
600 }
601 return ret;
602 }
603
604
605 /*
606 * Unset the specified variable.
607 */
608
609 STATIC int
unsetvar(s)610 unsetvar(s)
611 char *s;
612 {
613 struct var **vpp;
614 struct var *vp;
615
616 vpp = hashvar(s);
617 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
618 if (varequal(vp->text, s)) {
619 if (vp->flags & VREADONLY)
620 return (1);
621 INTOFF;
622 if (*(strchr(vp->text, '=') + 1) != '\0')
623 setvar(s, nullstr, 0);
624 vp->flags &=~ VEXPORT;
625 vp->flags |= VUNSET;
626 if ((vp->flags & VSTRFIXED) == 0) {
627 if ((vp->flags & VTEXTFIXED) == 0)
628 ckfree(vp->text);
629 *vpp = vp->next;
630 ckfree(vp);
631 }
632 INTON;
633 return (0);
634 }
635 }
636
637 return (1);
638 }
639
640
641
642 /*
643 * Find the appropriate entry in the hash table from the name.
644 */
645
646 STATIC struct var **
hashvar(p)647 hashvar(p)
648 register char *p;
649 {
650 unsigned int hashval;
651
652 hashval = *p << 4;
653 while (*p && *p != '=')
654 hashval += *p++;
655 return &vartab[hashval % VTABSIZE];
656 }
657
658
659
660 /*
661 * Returns true if the two strings specify the same varable. The first
662 * variable name is terminated by '='; the second may be terminated by
663 * either '=' or '\0'.
664 */
665
666 STATIC int
varequal(p,q)667 varequal(p, q)
668 register char *p, *q;
669 {
670 while (*p == *q++) {
671 if (*p++ == '=')
672 return 1;
673 }
674 if (*p == '=' && *(q - 1) == '\0')
675 return 1;
676 return 0;
677 }
678