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