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