2 * Copyright (c) 1991 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
38 static char sccsid
[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
48 #include "nodes.h" /* for other headers */
49 #include "eval.h" /* defines cmdenviron */
85 const struct varinit varinit
[] = {
87 {&vatty
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "ATTY="},
89 {&vifs
, VSTRFIXED
|VTEXTFIXED
, "IFS= \t\n"},
90 {&vmail
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAIL="},
91 {&vmpath
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAILPATH="},
92 {&vpath
, VSTRFIXED
|VTEXTFIXED
, "PATH=:/bin:/usr/bin"},
96 {&vps2
, VSTRFIXED
|VTEXTFIXED
, "PS2=> "},
97 {&vpse
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "PSE="},
99 {&vterm
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "TERM="},
104 struct var
*vartab
[VTABSIZE
];
106 STATIC
void unsetvar
__P((char *));
107 STATIC
struct var
**hashvar
__P((char *));
108 STATIC
int varequal
__P((char *, char *));
111 * Initialize the varable symbol tables and import the environment
118 extern char **environ
;
121 for (envp
= environ
; *envp
; envp
++) {
122 if (strchr(*envp
, '=')) {
123 setvareq(*envp
, VEXPORT
|VTEXTFIXED
);
131 * This routine initializes the builtin variables. It is called when the
132 * shell is initialized and again when a shell procedure is spawned.
137 register const struct varinit
*ip
;
138 register struct var
*vp
;
141 for (ip
= varinit
; (vp
= ip
->var
) != NULL
; ip
++) {
142 if ((vp
->flags
& VEXPORT
) == 0) {
143 vpp
= hashvar(ip
->text
);
147 vp
->flags
= ip
->flags
;
153 if ((vps1
.flags
& VEXPORT
) == 0) {
154 vpp
= hashvar("PS1=");
157 vps1
.text
= getuid() ? "PS1=$ " : "PS1=# ";
158 vps1
.flags
= VSTRFIXED
|VTEXTFIXED
;
163 * Set the value of a variable. The flags argument is ored with the
164 * flags of the variable. If val is NULL, the variable is unset.
168 setvar(name
, val
, flags
)
184 if (! is_in_name(*p
)) {
185 if (*p
== '\0' || *p
== '=')
193 error("%.*s: is read only", namelen
, name
);
194 len
= namelen
+ 2; /* 2 is space for '=' and '\0' */
200 p
= nameeq
= ckmalloc(len
);
202 while (--namelen
>= 0)
208 setvareq(nameeq
, flags
);
214 * Same as setvar except that the variable and value are passed in
215 * the first argument as name=value. Since the first argument will
216 * be actually stored in the table, it should not be a string that
224 register struct var
*vp
;
225 register struct var
**vpp
;
228 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
229 if (varequal(s
, vp
->text
)) {
230 if (vp
->flags
& VREADONLY
) {
231 int len
= strchr(s
, '=') - s
;
232 error("%.*s: is read only", len
, s
);
236 changepath(s
+ 5); /* 5 = strlen("PATH=") */
237 if ((vp
->flags
& (VTEXTFIXED
|VSTACK
)) == 0)
239 vp
->flags
&=~ (VTEXTFIXED
|VSTACK
|VUNSET
);
243 if (vp
== &vmpath
|| (vp
== &vmail
&& ! mpathset()))
251 vp
= ckmalloc(sizeof (*vp
));
261 * Process a linked list of variable assignments.
266 struct strlist
*list
;
268 register struct strlist
*lp
;
271 for (lp
= list
; lp
; lp
= lp
->next
) {
272 setvareq(savestr(lp
->text
), 0);
280 * Find the value of a variable. Returns NULL if not set.
287 register struct var
*v
;
289 for (v
= *hashvar(name
) ; v
; v
= v
->next
) {
290 if (varequal(v
->text
, name
)) {
291 if (v
->flags
& VUNSET
)
293 return strchr(v
->text
, '=') + 1;
302 * Search the environment of a builtin command. If the second argument
303 * is nonzero, return the value of a variable even if it hasn't been
308 bltinlookup(name
, doall
)
311 register struct strlist
*sp
;
312 register struct var
*v
;
314 for (sp
= cmdenviron
; sp
; sp
= sp
->next
) {
315 if (varequal(sp
->text
, name
))
316 return strchr(sp
->text
, '=') + 1;
318 for (v
= *hashvar(name
) ; v
; v
= v
->next
) {
319 if (varequal(v
->text
, name
)) {
320 if (v
->flags
& VUNSET
321 || ! doall
&& (v
->flags
& VEXPORT
) == 0)
323 return strchr(v
->text
, '=') + 1;
332 * Generate a list of exported variables. This routine is used to construct
333 * the third argument to execve when executing a program.
339 register struct var
**vpp
;
340 register struct var
*vp
;
345 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
346 for (vp
= *vpp
; vp
; vp
= vp
->next
)
347 if (vp
->flags
& VEXPORT
)
350 ep
= env
= stalloc((nenv
+ 1) * sizeof *env
);
351 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
352 for (vp
= *vpp
; vp
; vp
= vp
->next
)
353 if (vp
->flags
& VEXPORT
)
362 * Called when a shell procedure is invoked to clear out nonexported
363 * variables. It is also necessary to reallocate variables of with
364 * VSTACK set since these are currently allocated on the stack.
368 MKINIT
void shprocvar();
377 register struct var
**vpp
;
378 register struct var
*vp
;
381 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
382 for (prev
= vpp
; (vp
= *prev
) != NULL
; ) {
383 if ((vp
->flags
& VEXPORT
) == 0) {
385 if ((vp
->flags
& VTEXTFIXED
) == 0)
387 if ((vp
->flags
& VSTRFIXED
) == 0)
390 if (vp
->flags
& VSTACK
) {
391 vp
->text
= savestr(vp
->text
);
392 vp
->flags
&=~ VSTACK
;
404 * Command to list all variables which are set. Currently this command
405 * is invoked from the set command when the set command is called without
410 showvarscmd(argc
, argv
) char **argv
; {
411 register struct var
**vpp
;
412 register struct var
*vp
;
414 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
415 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
416 if ((vp
->flags
& VUNSET
) == 0)
417 out1fmt("%s\n", vp
->text
);
426 * The export and readonly commands.
430 exportcmd(argc
, argv
) char **argv
; {
432 register struct var
*vp
;
435 int flag
= argv
[0][0] == 'r'? VREADONLY
: VEXPORT
;
437 listsetvar(cmdenviron
);
439 while ((name
= *argptr
++) != NULL
) {
440 if ((p
= strchr(name
, '=')) != NULL
) {
444 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
445 if (varequal(vp
->text
, name
)) {
451 setvar(name
, p
, flag
);
455 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
456 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
457 if (vp
->flags
& flag
) {
458 for (p
= vp
->text
; *p
!= '=' ; p
++)
470 * The "local" command.
473 localcmd(argc
, argv
) char **argv
; {
477 error("Not in a function");
478 while ((name
= *argptr
++) != NULL
) {
486 * Make a variable a local variable. When a variable is made local, it's
487 * value and flags are saved in a localvar structure. The saved values
488 * will be restored when the shell function returns. We handle the name
489 * "-" as a special case.
496 register struct localvar
*lvp
;
498 register struct var
*vp
;
501 lvp
= ckmalloc(sizeof (struct localvar
));
502 if (name
[0] == '-' && name
[1] == '\0') {
503 lvp
->text
= ckmalloc(sizeof optval
);
504 bcopy(optval
, lvp
->text
, sizeof optval
);
508 for (vp
= *vpp
; vp
&& ! varequal(vp
->text
, name
) ; vp
= vp
->next
);
510 if (strchr(name
, '='))
511 setvareq(savestr(name
), VSTRFIXED
);
513 setvar(name
, NULL
, VSTRFIXED
);
514 vp
= *vpp
; /* the new variable */
518 lvp
->text
= vp
->text
;
519 lvp
->flags
= vp
->flags
;
520 vp
->flags
|= VSTRFIXED
|VTEXTFIXED
;
521 if (strchr(name
, '='))
522 setvareq(savestr(name
), 0);
526 lvp
->next
= localvars
;
533 * Called after a function returns.
538 register struct localvar
*lvp
;
539 register struct var
*vp
;
541 while ((lvp
= localvars
) != NULL
) {
542 localvars
= lvp
->next
;
544 if (vp
== NULL
) { /* $- saved */
545 bcopy(lvp
->text
, optval
, sizeof optval
);
547 } else if ((lvp
->flags
& (VUNSET
|VSTRFIXED
)) == VUNSET
) {
550 if ((vp
->flags
& VTEXTFIXED
) == 0)
552 vp
->flags
= lvp
->flags
;
553 vp
->text
= lvp
->text
;
560 setvarcmd(argc
, argv
) register char **argv
; {
562 return unsetcmd(argc
, argv
);
564 setvar(argv
[1], argv
[2], 0);
566 error("List assignment not implemented");
572 * The unset builtin command. We unset the function before we unset the
573 * variable to allow a function to be unset when there is a readonly variable
574 * with the same name.
577 unsetcmd(argc
, argv
) char **argv
; {
580 for (ap
= argv
+ 1 ; *ap
; ap
++) {
589 * Unset the specified variable.
596 register struct var
**vpp
;
597 register struct var
*vp
;
600 for (vp
= *vpp
; vp
; vpp
= &vp
->next
, vp
= *vpp
) {
601 if (varequal(vp
->text
, s
)) {
603 if (*(strchr(vp
->text
, '=') + 1) != '\0'
604 || vp
->flags
& VREADONLY
) {
605 setvar(s
, nullstr
, 0);
607 vp
->flags
&=~ VEXPORT
;
609 if ((vp
->flags
& VSTRFIXED
) == 0) {
610 if ((vp
->flags
& VTEXTFIXED
) == 0)
624 * Find the appropriate entry in the hash table from the name.
631 unsigned int hashval
;
634 while (*p
&& *p
!= '=')
636 return &vartab
[hashval
% VTABSIZE
];
642 * Returns true if the two strings specify the same varable. The first
643 * variable name is terminated by '='; the second may be terminated by
644 * either '=' or '\0'.
649 register char *p
, *q
;
655 if (*p
== '=' && *(q
- 1) == '\0')