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