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