1 /* $NetBSD: var.c,v 1.28 2002/05/15 19:43:29 bjh21 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.28 2002/05/15 19:43:29 bjh21 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 if (aflag) 286 flags |= VEXPORT; 287 vpp = hashvar(s); 288 for (vp = *vpp ; vp ; vp = vp->next) { 289 if (varequal(s, vp->text)) { 290 if (vp->flags & VREADONLY) { 291 size_t len = strchr(s, '=') - s; 292 error("%.*s: is read only", len, s); 293 } 294 INTOFF; 295 296 if (vp->func && (flags & VNOFUNC) == 0) 297 (*vp->func)(strchr(s, '=') + 1); 298 299 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 300 ckfree(vp->text); 301 302 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 303 vp->flags |= flags; 304 vp->text = s; 305 306 /* 307 * We could roll this to a function, to handle it as 308 * a regular variable function callback, but why bother? 309 */ 310 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 311 chkmail(1); 312 INTON; 313 return; 314 } 315 } 316 /* not found */ 317 vp = ckmalloc(sizeof (*vp)); 318 vp->flags = flags; 319 vp->text = s; 320 vp->next = *vpp; 321 vp->func = NULL; 322 *vpp = vp; 323 } 324 325 326 327 /* 328 * Process a linked list of variable assignments. 329 */ 330 331 void 332 listsetvar(list) 333 struct strlist *list; 334 { 335 struct strlist *lp; 336 337 INTOFF; 338 for (lp = list ; lp ; lp = lp->next) { 339 setvareq(savestr(lp->text), 0); 340 } 341 INTON; 342 } 343 344 345 346 /* 347 * Find the value of a variable. Returns NULL if not set. 348 */ 349 350 char * 351 lookupvar(name) 352 const char *name; 353 { 354 struct var *v; 355 356 for (v = *hashvar(name) ; v ; v = v->next) { 357 if (varequal(v->text, name)) { 358 if (v->flags & VUNSET) 359 return NULL; 360 return strchr(v->text, '=') + 1; 361 } 362 } 363 return NULL; 364 } 365 366 367 368 /* 369 * Search the environment of a builtin command. If the second argument 370 * is nonzero, return the value of a variable even if it hasn't been 371 * exported. 372 */ 373 374 char * 375 bltinlookup(name, doall) 376 const char *name; 377 int doall; 378 { 379 struct strlist *sp; 380 struct var *v; 381 382 for (sp = cmdenviron ; sp ; sp = sp->next) { 383 if (varequal(sp->text, name)) 384 return strchr(sp->text, '=') + 1; 385 } 386 for (v = *hashvar(name) ; v ; v = v->next) { 387 if (varequal(v->text, name)) { 388 if ((v->flags & VUNSET) 389 || (!doall && (v->flags & VEXPORT) == 0)) 390 return NULL; 391 return strchr(v->text, '=') + 1; 392 } 393 } 394 return NULL; 395 } 396 397 398 399 /* 400 * Generate a list of exported variables. This routine is used to construct 401 * the third argument to execve when executing a program. 402 */ 403 404 char ** 405 environment() { 406 int nenv; 407 struct var **vpp; 408 struct var *vp; 409 char **env; 410 char **ep; 411 412 nenv = 0; 413 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 414 for (vp = *vpp ; vp ; vp = vp->next) 415 if (vp->flags & VEXPORT) 416 nenv++; 417 } 418 ep = env = stalloc((nenv + 1) * sizeof *env); 419 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 420 for (vp = *vpp ; vp ; vp = vp->next) 421 if (vp->flags & VEXPORT) 422 *ep++ = vp->text; 423 } 424 *ep = NULL; 425 return env; 426 } 427 428 429 /* 430 * Called when a shell procedure is invoked to clear out nonexported 431 * variables. It is also necessary to reallocate variables of with 432 * VSTACK set since these are currently allocated on the stack. 433 */ 434 435 #ifdef mkinit 436 void shprocvar __P((void)); 437 438 SHELLPROC { 439 shprocvar(); 440 } 441 #endif 442 443 void 444 shprocvar() { 445 struct var **vpp; 446 struct var *vp, **prev; 447 448 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 449 for (prev = vpp ; (vp = *prev) != NULL ; ) { 450 if ((vp->flags & VEXPORT) == 0) { 451 *prev = vp->next; 452 if ((vp->flags & VTEXTFIXED) == 0) 453 ckfree(vp->text); 454 if ((vp->flags & VSTRFIXED) == 0) 455 ckfree(vp); 456 } else { 457 if (vp->flags & VSTACK) { 458 vp->text = savestr(vp->text); 459 vp->flags &=~ VSTACK; 460 } 461 prev = &vp->next; 462 } 463 } 464 } 465 initvar(); 466 } 467 468 469 470 /* 471 * Command to list all variables which are set. Currently this command 472 * is invoked from the set command when the set command is called without 473 * any variables. 474 */ 475 476 int 477 showvarscmd(argc, argv) 478 int argc; 479 char **argv; 480 { 481 struct var **vpp; 482 struct var *vp; 483 484 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 485 for (vp = *vpp ; vp ; vp = vp->next) { 486 if ((vp->flags & VUNSET) == 0) 487 out1fmt("%s\n", vp->text); 488 } 489 } 490 return 0; 491 } 492 493 494 495 /* 496 * The export and readonly commands. 497 */ 498 499 int 500 exportcmd(argc, argv) 501 int argc; 502 char **argv; 503 { 504 struct var **vpp; 505 struct var *vp; 506 char *name; 507 const char *p; 508 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 509 int pflag; 510 511 listsetvar(cmdenviron); 512 pflag = (nextopt("p") == 'p'); 513 if (argc > 1 && !pflag) { 514 while ((name = *argptr++) != NULL) { 515 if ((p = strchr(name, '=')) != NULL) { 516 p++; 517 } else { 518 vpp = hashvar(name); 519 for (vp = *vpp ; vp ; vp = vp->next) { 520 if (varequal(vp->text, name)) { 521 vp->flags |= flag; 522 goto found; 523 } 524 } 525 } 526 setvar(name, p, flag); 527 found:; 528 } 529 } else { 530 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 531 for (vp = *vpp ; vp ; vp = vp->next) { 532 if ((vp->flags & flag) == 0) 533 continue; 534 if (pflag) { 535 out1fmt("%s %s\n", argv[0], vp->text); 536 } else { 537 for (p = vp->text ; *p != '=' ; p++) 538 out1c(*p); 539 out1c('\n'); 540 } 541 } 542 } 543 } 544 return 0; 545 } 546 547 548 /* 549 * The "local" command. 550 */ 551 552 int 553 localcmd(argc, argv) 554 int argc; 555 char **argv; 556 { 557 char *name; 558 559 if (! in_function()) 560 error("Not in a function"); 561 while ((name = *argptr++) != NULL) { 562 mklocal(name); 563 } 564 return 0; 565 } 566 567 568 /* 569 * Make a variable a local variable. When a variable is made local, it's 570 * value and flags are saved in a localvar structure. The saved values 571 * will be restored when the shell function returns. We handle the name 572 * "-" as a special case. 573 */ 574 575 void 576 mklocal(name) 577 char *name; 578 { 579 struct localvar *lvp; 580 struct var **vpp; 581 struct var *vp; 582 583 INTOFF; 584 lvp = ckmalloc(sizeof (struct localvar)); 585 if (name[0] == '-' && name[1] == '\0') { 586 char *p; 587 p = ckmalloc(sizeof optlist); 588 lvp->text = memcpy(p, optlist, sizeof optlist); 589 vp = NULL; 590 } else { 591 vpp = hashvar(name); 592 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); 593 if (vp == NULL) { 594 if (strchr(name, '=')) 595 setvareq(savestr(name), VSTRFIXED); 596 else 597 setvar(name, NULL, VSTRFIXED); 598 vp = *vpp; /* the new variable */ 599 lvp->text = NULL; 600 lvp->flags = VUNSET; 601 } else { 602 lvp->text = vp->text; 603 lvp->flags = vp->flags; 604 vp->flags |= VSTRFIXED|VTEXTFIXED; 605 if (strchr(name, '=')) 606 setvareq(savestr(name), 0); 607 } 608 } 609 lvp->vp = vp; 610 lvp->next = localvars; 611 localvars = lvp; 612 INTON; 613 } 614 615 616 /* 617 * Called after a function returns. 618 */ 619 620 void 621 poplocalvars() { 622 struct localvar *lvp; 623 struct var *vp; 624 625 while ((lvp = localvars) != NULL) { 626 localvars = lvp->next; 627 vp = lvp->vp; 628 if (vp == NULL) { /* $- saved */ 629 memcpy(optlist, lvp->text, sizeof optlist); 630 ckfree(lvp->text); 631 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 632 (void)unsetvar(vp->text); 633 } else { 634 if ((vp->flags & VTEXTFIXED) == 0) 635 ckfree(vp->text); 636 vp->flags = lvp->flags; 637 vp->text = lvp->text; 638 } 639 ckfree(lvp); 640 } 641 } 642 643 644 int 645 setvarcmd(argc, argv) 646 int argc; 647 char **argv; 648 { 649 if (argc <= 2) 650 return unsetcmd(argc, argv); 651 else if (argc == 3) 652 setvar(argv[1], argv[2], 0); 653 else 654 error("List assignment not implemented"); 655 return 0; 656 } 657 658 659 /* 660 * The unset builtin command. We unset the function before we unset the 661 * variable to allow a function to be unset when there is a readonly variable 662 * with the same name. 663 */ 664 665 int 666 unsetcmd(argc, argv) 667 int argc; 668 char **argv; 669 { 670 char **ap; 671 int i; 672 int flg_func = 0; 673 int flg_var = 0; 674 int ret = 0; 675 676 while ((i = nextopt("vf")) != '\0') { 677 if (i == 'f') 678 flg_func = 1; 679 else 680 flg_var = 1; 681 } 682 if (flg_func == 0 && flg_var == 0) 683 flg_var = 1; 684 685 for (ap = argptr; *ap ; ap++) { 686 if (flg_func) 687 ret |= unsetfunc(*ap); 688 if (flg_var) 689 ret |= unsetvar(*ap); 690 } 691 return ret; 692 } 693 694 695 /* 696 * Unset the specified variable. 697 */ 698 699 int 700 unsetvar(s) 701 const char *s; 702 { 703 struct var **vpp; 704 struct var *vp; 705 706 vpp = hashvar(s); 707 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 708 if (varequal(vp->text, s)) { 709 if (vp->flags & VREADONLY) 710 return (1); 711 INTOFF; 712 if (*(strchr(vp->text, '=') + 1) != '\0') 713 setvar(s, nullstr, 0); 714 vp->flags &= ~VEXPORT; 715 vp->flags |= VUNSET; 716 if ((vp->flags & VSTRFIXED) == 0) { 717 if ((vp->flags & VTEXTFIXED) == 0) 718 ckfree(vp->text); 719 *vpp = vp->next; 720 ckfree(vp); 721 } 722 INTON; 723 return (0); 724 } 725 } 726 727 return (1); 728 } 729 730 731 732 /* 733 * Find the appropriate entry in the hash table from the name. 734 */ 735 736 STATIC struct var ** 737 hashvar(p) 738 const char *p; 739 { 740 unsigned int hashval; 741 742 hashval = ((unsigned char) *p) << 4; 743 while (*p && *p != '=') 744 hashval += (unsigned char) *p++; 745 return &vartab[hashval % VTABSIZE]; 746 } 747 748 749 750 /* 751 * Returns true if the two strings specify the same varable. The first 752 * variable name is terminated by '='; the second may be terminated by 753 * either '=' or '\0'. 754 */ 755 756 STATIC int 757 varequal(p, q) 758 const char *p, *q; 759 { 760 while (*p == *q++) { 761 if (*p++ == '=') 762 return 1; 763 } 764 if (*p == '=' && *(q - 1) == '\0') 765 return 1; 766 return 0; 767 } 768