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