1 /* $NetBSD: var.c,v 1.31 2002/11/25 12:13:03 agc 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.31 2002/11/25 12:13:03 agc 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)(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(const char *); 137 STATIC int varequal(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(void) 166 { 167 const struct varinit *ip; 168 struct var *vp; 169 struct var **vpp; 170 171 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 172 if ((vp->flags & VEXPORT) == 0) { 173 vpp = hashvar(ip->text); 174 vp->next = *vpp; 175 *vpp = vp; 176 vp->text = strdup(ip->text); 177 vp->flags = ip->flags; 178 vp->func = ip->func; 179 } 180 } 181 /* 182 * PS1 depends on uid 183 */ 184 if ((vps1.flags & VEXPORT) == 0) { 185 vpp = hashvar("PS1="); 186 vps1.next = *vpp; 187 *vpp = &vps1; 188 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); 189 vps1.flags = VSTRFIXED|VTEXTFIXED; 190 } 191 } 192 193 /* 194 * Safe version of setvar, returns 1 on success 0 on failure. 195 */ 196 197 int 198 setvarsafe(const char *name, const char *val, 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(const char *name, const char *val, int flags) 224 { 225 const char *p; 226 const char *q; 227 char *d; 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 d = nameeq = ckmalloc(len); 256 q = name; 257 while (--namelen >= 0) 258 *d++ = *q++; 259 *d++ = '='; 260 *d = '\0'; 261 if (val) 262 scopy(val, d); 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(char *s, int flags) 277 { 278 struct var *vp, **vpp; 279 280 if (aflag) 281 flags |= VEXPORT; 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 if (flags & VNOSET) 290 return; 291 INTOFF; 292 293 if (vp->func && (flags & VNOFUNC) == 0) 294 (*vp->func)(strchr(s, '=') + 1); 295 296 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 297 ckfree(vp->text); 298 299 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 300 vp->flags |= flags; 301 vp->text = s; 302 303 /* 304 * We could roll this to a function, to handle it as 305 * a regular variable function callback, but why bother? 306 */ 307 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 308 chkmail(1); 309 INTON; 310 return; 311 } 312 } 313 /* not found */ 314 if (flags & VNOSET) 315 return; 316 vp = ckmalloc(sizeof (*vp)); 317 vp->flags = flags; 318 vp->text = s; 319 vp->next = *vpp; 320 vp->func = NULL; 321 *vpp = vp; 322 } 323 324 325 326 /* 327 * Process a linked list of variable assignments. 328 */ 329 330 void 331 listsetvar(struct strlist *list, int flags) 332 { 333 struct strlist *lp; 334 335 INTOFF; 336 for (lp = list ; lp ; lp = lp->next) { 337 setvareq(savestr(lp->text), flags); 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(const char *name) 350 { 351 struct var *v; 352 353 for (v = *hashvar(name) ; v ; v = v->next) { 354 if (varequal(v->text, name)) { 355 if (v->flags & VUNSET) 356 return NULL; 357 return strchr(v->text, '=') + 1; 358 } 359 } 360 return NULL; 361 } 362 363 364 365 /* 366 * Search the environment of a builtin command. If the second argument 367 * is nonzero, return the value of a variable even if it hasn't been 368 * exported. 369 */ 370 371 char * 372 bltinlookup(const char *name, 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(void) 401 { 402 int nenv; 403 struct var **vpp; 404 struct var *vp; 405 char **env; 406 char **ep; 407 408 nenv = 0; 409 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 410 for (vp = *vpp ; vp ; vp = vp->next) 411 if (vp->flags & VEXPORT) 412 nenv++; 413 } 414 ep = env = stalloc((nenv + 1) * sizeof *env); 415 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 416 for (vp = *vpp ; vp ; vp = vp->next) 417 if (vp->flags & VEXPORT) 418 *ep++ = vp->text; 419 } 420 *ep = NULL; 421 return env; 422 } 423 424 425 /* 426 * Called when a shell procedure is invoked to clear out nonexported 427 * variables. It is also necessary to reallocate variables of with 428 * VSTACK set since these are currently allocated on the stack. 429 */ 430 431 #ifdef mkinit 432 void shprocvar(void); 433 434 SHELLPROC { 435 shprocvar(); 436 } 437 #endif 438 439 void 440 shprocvar(void) 441 { 442 struct var **vpp; 443 struct var *vp, **prev; 444 445 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 446 for (prev = vpp ; (vp = *prev) != NULL ; ) { 447 if ((vp->flags & VEXPORT) == 0) { 448 *prev = vp->next; 449 if ((vp->flags & VTEXTFIXED) == 0) 450 ckfree(vp->text); 451 if ((vp->flags & VSTRFIXED) == 0) 452 ckfree(vp); 453 } else { 454 if (vp->flags & VSTACK) { 455 vp->text = savestr(vp->text); 456 vp->flags &=~ VSTACK; 457 } 458 prev = &vp->next; 459 } 460 } 461 } 462 initvar(); 463 } 464 465 466 467 /* 468 * Command to list all variables which are set. Currently this command 469 * is invoked from the set command when the set command is called without 470 * any variables. 471 */ 472 473 void 474 print_quoted(const char *p) 475 { 476 const char *q; 477 478 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 479 out1fmt("%s", p); 480 return; 481 } 482 while (*p) { 483 if (*p == '\'') { 484 out1fmt("\\'"); 485 p++; 486 continue; 487 } 488 q = index(p, '\''); 489 if (!q) { 490 out1fmt("'%s'", p ); 491 return; 492 } 493 out1fmt("'%.*s'", (int)(q - p), p ); 494 p = q; 495 } 496 } 497 498 static int 499 sort_var(const void *v_v1, const void *v_v2) 500 { 501 const struct var * const *v1 = v_v1; 502 const struct var * const *v2 = v_v2; 503 504 /* XXX Will anyone notice we include the '=' of the shorter name? */ 505 return strcoll((*v1)->text, (*v2)->text); 506 } 507 508 /* 509 * POSIX requires that 'set' (but not export or readonly) output the 510 * variables in lexicographic order - by the locale's collating order (sigh). 511 * Maybe we could keep them in an ordered balanced binary tree 512 * instead of hashed lists. 513 * For now just roll 'em through qsort for printing... 514 */ 515 516 int 517 showvars(const char *name, int flag, int show_value) 518 { 519 struct var **vpp; 520 struct var *vp; 521 const char *p; 522 523 static struct var **list; /* static in case we are interrupted */ 524 static int list_len; 525 int count = 0; 526 527 if (!list) { 528 list_len = 32; 529 list = ckmalloc(list_len * sizeof *list); 530 } 531 532 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 533 for (vp = *vpp ; vp ; vp = vp->next) { 534 if (flag && !(vp->flags & flag)) 535 continue; 536 if (vp->flags & VUNSET && !(show_value & 2)) 537 continue; 538 if (count >= list_len) { 539 list = ckrealloc(list, 540 (list_len << 1) * sizeof *list); 541 list_len <<= 1; 542 } 543 list[count++] = vp; 544 } 545 } 546 547 qsort(list, count, sizeof *list, sort_var); 548 549 for (vpp = list; count--; vpp++) { 550 vp = *vpp; 551 if (name) 552 out1fmt("%s ", name); 553 for (p = vp->text ; *p != '=' ; p++) 554 out1c(*p); 555 if (!(vp->flags & VUNSET) && show_value) { 556 out1fmt("="); 557 print_quoted(++p); 558 } 559 out1c('\n'); 560 } 561 return 0; 562 } 563 564 565 566 /* 567 * The export and readonly commands. 568 */ 569 570 int 571 exportcmd(int argc, char **argv) 572 { 573 struct var **vpp; 574 struct var *vp; 575 char *name; 576 const char *p; 577 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 578 int pflag; 579 580 pflag = nextopt("p") == 'p' ? 3 : 0; 581 if (argc <= 1 || pflag) { 582 showvars( pflag ? argv[0] : 0, flag, pflag ); 583 return 0; 584 } 585 586 while ((name = *argptr++) != NULL) { 587 if ((p = strchr(name, '=')) != NULL) { 588 p++; 589 } else { 590 vpp = hashvar(name); 591 for (vp = *vpp ; vp ; vp = vp->next) { 592 if (varequal(vp->text, name)) { 593 vp->flags |= flag; 594 goto found; 595 } 596 } 597 } 598 setvar(name, p, flag); 599 found:; 600 } 601 return 0; 602 } 603 604 605 /* 606 * The "local" command. 607 */ 608 609 int 610 localcmd(int argc, char **argv) 611 { 612 char *name; 613 614 if (! in_function()) 615 error("Not in a function"); 616 while ((name = *argptr++) != NULL) { 617 mklocal(name, 0); 618 } 619 return 0; 620 } 621 622 623 /* 624 * Make a variable a local variable. When a variable is made local, it's 625 * value and flags are saved in a localvar structure. The saved values 626 * will be restored when the shell function returns. We handle the name 627 * "-" as a special case. 628 */ 629 630 void 631 mklocal(char *name, int flags) 632 { 633 struct localvar *lvp; 634 struct var **vpp; 635 struct var *vp; 636 637 INTOFF; 638 lvp = ckmalloc(sizeof (struct localvar)); 639 if (name[0] == '-' && name[1] == '\0') { 640 char *p; 641 p = ckmalloc(sizeof_optlist); 642 lvp->text = memcpy(p, optlist, sizeof_optlist); 643 vp = NULL; 644 } else { 645 vpp = hashvar(name); 646 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); 647 if (vp == NULL) { 648 if (strchr(name, '=')) 649 setvareq(savestr(name), VSTRFIXED|flags); 650 else 651 setvar(name, NULL, VSTRFIXED|flags); 652 vp = *vpp; /* the new variable */ 653 lvp->text = NULL; 654 lvp->flags = VUNSET; 655 } else { 656 lvp->text = vp->text; 657 lvp->flags = vp->flags; 658 vp->flags |= VSTRFIXED|VTEXTFIXED; 659 if (strchr(name, '=')) 660 setvareq(savestr(name), flags); 661 } 662 } 663 lvp->vp = vp; 664 lvp->next = localvars; 665 localvars = lvp; 666 INTON; 667 } 668 669 670 /* 671 * Called after a function returns. 672 */ 673 674 void 675 poplocalvars(void) 676 { 677 struct localvar *lvp; 678 struct var *vp; 679 680 while ((lvp = localvars) != NULL) { 681 localvars = lvp->next; 682 vp = lvp->vp; 683 if (vp == NULL) { /* $- saved */ 684 memcpy(optlist, lvp->text, sizeof_optlist); 685 ckfree(lvp->text); 686 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 687 (void)unsetvar(vp->text, 0); 688 } else { 689 if ((vp->flags & VTEXTFIXED) == 0) 690 ckfree(vp->text); 691 vp->flags = lvp->flags; 692 vp->text = lvp->text; 693 } 694 ckfree(lvp); 695 } 696 } 697 698 699 int 700 setvarcmd(int argc, char **argv) 701 { 702 if (argc <= 2) 703 return unsetcmd(argc, argv); 704 else if (argc == 3) 705 setvar(argv[1], argv[2], 0); 706 else 707 error("List assignment not implemented"); 708 return 0; 709 } 710 711 712 /* 713 * The unset builtin command. We unset the function before we unset the 714 * variable to allow a function to be unset when there is a readonly variable 715 * with the same name. 716 */ 717 718 int 719 unsetcmd(int argc, char **argv) 720 { 721 char **ap; 722 int i; 723 int flg_func = 0; 724 int flg_var = 0; 725 int ret = 0; 726 727 while ((i = nextopt("evf")) != '\0') { 728 if (i == 'f') 729 flg_func = 1; 730 else 731 flg_var = i; 732 } 733 if (flg_func == 0 && flg_var == 0) 734 flg_var = 1; 735 736 for (ap = argptr; *ap ; ap++) { 737 if (flg_func) 738 ret |= unsetfunc(*ap); 739 if (flg_var) 740 ret |= unsetvar(*ap, flg_var == 'e'); 741 } 742 return ret; 743 } 744 745 746 /* 747 * Unset the specified variable. 748 */ 749 750 int 751 unsetvar(const char *s, int unexport) 752 { 753 struct var **vpp; 754 struct var *vp; 755 756 vpp = hashvar(s); 757 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 758 if (varequal(vp->text, s)) { 759 if (vp->flags & VREADONLY) 760 return (1); 761 INTOFF; 762 if (unexport) { 763 vp->flags &= ~VEXPORT; 764 } else { 765 if (*(strchr(vp->text, '=') + 1) != '\0') 766 setvar(s, nullstr, 0); 767 vp->flags &= ~VEXPORT; 768 vp->flags |= VUNSET; 769 if ((vp->flags & VSTRFIXED) == 0) { 770 if ((vp->flags & VTEXTFIXED) == 0) 771 ckfree(vp->text); 772 *vpp = vp->next; 773 ckfree(vp); 774 } 775 } 776 INTON; 777 return (0); 778 } 779 } 780 781 return (1); 782 } 783 784 785 786 /* 787 * Find the appropriate entry in the hash table from the name. 788 */ 789 790 STATIC struct var ** 791 hashvar(const char *p) 792 { 793 unsigned int hashval; 794 795 hashval = ((unsigned char) *p) << 4; 796 while (*p && *p != '=') 797 hashval += (unsigned char) *p++; 798 return &vartab[hashval % VTABSIZE]; 799 } 800 801 802 803 /* 804 * Returns true if the two strings specify the same varable. The first 805 * variable name is terminated by '='; the second may be terminated by 806 * either '=' or '\0'. 807 */ 808 809 STATIC int 810 varequal(const char *p, const char *q) 811 { 812 while (*p == *q++) { 813 if (*p++ == '=') 814 return 1; 815 } 816 if (*p == '=' && *(q - 1) == '\0') 817 return 1; 818 return 0; 819 } 820