1 /* $NetBSD: var.c,v 1.38 2006/12/18 00:37:33 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 39 #else 40 __RCSID("$NetBSD: var.c,v 1.38 2006/12/18 00:37:33 christos Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <unistd.h> 45 #include <stdlib.h> 46 #include <strings.h> 47 #include <paths.h> 48 49 /* 50 * Shell variables. 51 */ 52 53 #include "shell.h" 54 #include "output.h" 55 #include "expand.h" 56 #include "nodes.h" /* for other headers */ 57 #include "eval.h" /* defines cmdenviron */ 58 #include "exec.h" 59 #include "syntax.h" 60 #include "options.h" 61 #include "mail.h" 62 #include "var.h" 63 #include "memalloc.h" 64 #include "error.h" 65 #include "mystring.h" 66 #include "parser.h" 67 #include "show.h" 68 #ifndef SMALL 69 #include "myhistedit.h" 70 #endif 71 72 #ifdef SMALL 73 #define VTABSIZE 39 74 #else 75 #define VTABSIZE 517 76 #endif 77 78 79 struct varinit { 80 struct var *var; 81 int flags; 82 const char *text; 83 void (*func)(const char *); 84 }; 85 86 87 #if ATTY 88 struct var vatty; 89 #endif 90 #ifndef SMALL 91 struct var vhistsize; 92 struct var vterm; 93 #endif 94 struct var vifs; 95 struct var vmail; 96 struct var vmpath; 97 struct var vpath; 98 struct var vps1; 99 struct var vps2; 100 struct var vps4; 101 struct var vvers; 102 struct var voptind; 103 104 const struct varinit varinit[] = { 105 #if ATTY 106 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", 107 NULL }, 108 #endif 109 #ifndef SMALL 110 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 111 sethistsize }, 112 #endif 113 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 114 NULL }, 115 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", 116 NULL }, 117 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 118 NULL }, 119 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, 120 changepath }, 121 /* 122 * vps1 depends on uid 123 */ 124 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 125 NULL }, 126 { &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 127 NULL }, 128 #ifndef SMALL 129 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 130 setterm }, 131 #endif 132 { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", 133 getoptsreset }, 134 { NULL, 0, NULL, 135 NULL } 136 }; 137 138 struct var *vartab[VTABSIZE]; 139 140 STATIC int strequal(const char *, const char *); 141 STATIC struct var *find_var(const char *, struct var ***, int *); 142 143 /* 144 * Initialize the varable symbol tables and import the environment 145 */ 146 147 #ifdef mkinit 148 INCLUDE "var.h" 149 MKINIT char **environ; 150 INIT { 151 char **envp; 152 153 initvar(); 154 for (envp = environ ; *envp ; envp++) { 155 if (strchr(*envp, '=')) { 156 setvareq(*envp, VEXPORT|VTEXTFIXED); 157 } 158 } 159 } 160 #endif 161 162 163 /* 164 * This routine initializes the builtin variables. It is called when the 165 * shell is initialized and again when a shell procedure is spawned. 166 */ 167 168 void 169 initvar(void) 170 { 171 const struct varinit *ip; 172 struct var *vp; 173 struct var **vpp; 174 175 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 176 if (find_var(ip->text, &vpp, &vp->name_len) != NULL) 177 continue; 178 vp->next = *vpp; 179 *vpp = vp; 180 vp->text = strdup(ip->text); 181 vp->flags = ip->flags; 182 vp->func = ip->func; 183 } 184 /* 185 * PS1 depends on uid 186 */ 187 if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { 188 vps1.next = *vpp; 189 *vpp = &vps1; 190 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); 191 vps1.flags = VSTRFIXED|VTEXTFIXED; 192 } 193 } 194 195 /* 196 * Safe version of setvar, returns 1 on success 0 on failure. 197 */ 198 199 int 200 setvarsafe(const char *name, const char *val, int flags) 201 { 202 struct jmploc jmploc; 203 struct jmploc *volatile savehandler = handler; 204 int volatile err = 0; 205 206 if (setjmp(jmploc.loc)) 207 err = 1; 208 else { 209 handler = &jmploc; 210 setvar(name, val, flags); 211 } 212 handler = savehandler; 213 return err; 214 } 215 216 /* 217 * Set the value of a variable. The flags argument is ored with the 218 * flags of the variable. If val is NULL, the variable is unset. 219 */ 220 221 void 222 setvar(const char *name, const char *val, int flags) 223 { 224 const char *p; 225 const char *q; 226 char *d; 227 int len; 228 int namelen; 229 char *nameeq; 230 int isbad; 231 232 isbad = 0; 233 p = name; 234 if (! is_name(*p)) 235 isbad = 1; 236 p++; 237 for (;;) { 238 if (! is_in_name(*p)) { 239 if (*p == '\0' || *p == '=') 240 break; 241 isbad = 1; 242 } 243 p++; 244 } 245 namelen = p - name; 246 if (isbad) 247 error("%.*s: bad variable name", namelen, name); 248 len = namelen + 2; /* 2 is space for '=' and '\0' */ 249 if (val == NULL) { 250 flags |= VUNSET; 251 } else { 252 len += strlen(val); 253 } 254 d = nameeq = ckmalloc(len); 255 q = name; 256 while (--namelen >= 0) 257 *d++ = *q++; 258 *d++ = '='; 259 *d = '\0'; 260 if (val) 261 scopy(val, d); 262 setvareq(nameeq, flags); 263 } 264 265 266 267 /* 268 * Same as setvar except that the variable and value are passed in 269 * the first argument as name=value. Since the first argument will 270 * be actually stored in the table, it should not be a string that 271 * will go away. 272 */ 273 274 void 275 setvareq(char *s, int flags) 276 { 277 struct var *vp, **vpp; 278 int nlen; 279 280 if (aflag) 281 flags |= VEXPORT; 282 vp = find_var(s, &vpp, &nlen); 283 if (vp != NULL) { 284 if (vp->flags & VREADONLY) 285 error("%.*s: is read only", vp->name_len, s); 286 if (flags & VNOSET) 287 return; 288 INTOFF; 289 290 if (vp->func && (flags & VNOFUNC) == 0) 291 (*vp->func)(s + vp->name_len + 1); 292 293 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 294 ckfree(vp->text); 295 296 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 297 vp->flags |= flags & ~VNOFUNC; 298 vp->text = s; 299 300 /* 301 * We could roll this to a function, to handle it as 302 * a regular variable function callback, but why bother? 303 */ 304 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 305 chkmail(1); 306 INTON; 307 return; 308 } 309 /* not found */ 310 if (flags & VNOSET) 311 return; 312 vp = ckmalloc(sizeof (*vp)); 313 vp->flags = flags & ~VNOFUNC; 314 vp->text = s; 315 vp->name_len = nlen; 316 vp->next = *vpp; 317 vp->func = NULL; 318 *vpp = vp; 319 } 320 321 322 323 /* 324 * Process a linked list of variable assignments. 325 */ 326 327 void 328 listsetvar(struct strlist *list, int flags) 329 { 330 struct strlist *lp; 331 332 INTOFF; 333 for (lp = list ; lp ; lp = lp->next) { 334 setvareq(savestr(lp->text), flags); 335 } 336 INTON; 337 } 338 339 void 340 listmklocal(struct strlist *list, int flags) 341 { 342 struct strlist *lp; 343 344 for (lp = list ; lp ; lp = lp->next) 345 mklocal(lp->text, flags); 346 } 347 348 349 /* 350 * Find the value of a variable. Returns NULL if not set. 351 */ 352 353 char * 354 lookupvar(const char *name) 355 { 356 struct var *v; 357 358 v = find_var(name, NULL, NULL); 359 if (v == NULL || v->flags & VUNSET) 360 return NULL; 361 return v->text + v->name_len + 1; 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(const char *name, int doall) 374 { 375 struct strlist *sp; 376 struct var *v; 377 378 for (sp = cmdenviron ; sp ; sp = sp->next) { 379 if (strequal(sp->text, name)) 380 return strchr(sp->text, '=') + 1; 381 } 382 383 v = find_var(name, NULL, NULL); 384 385 if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) 386 return NULL; 387 return v->text + v->name_len + 1; 388 } 389 390 391 392 /* 393 * Generate a list of exported variables. This routine is used to construct 394 * the third argument to execve when executing a program. 395 */ 396 397 char ** 398 environment(void) 399 { 400 int nenv; 401 struct var **vpp; 402 struct var *vp; 403 char **env; 404 char **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 void shprocvar(void); 431 432 SHELLPROC { 433 shprocvar(); 434 } 435 #endif 436 437 void 438 shprocvar(void) 439 { 440 struct var **vpp; 441 struct var *vp, **prev; 442 443 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 444 for (prev = vpp ; (vp = *prev) != NULL ; ) { 445 if ((vp->flags & VEXPORT) == 0) { 446 *prev = vp->next; 447 if ((vp->flags & VTEXTFIXED) == 0) 448 ckfree(vp->text); 449 if ((vp->flags & VSTRFIXED) == 0) 450 ckfree(vp); 451 } else { 452 if (vp->flags & VSTACK) { 453 vp->text = savestr(vp->text); 454 vp->flags &=~ VSTACK; 455 } 456 prev = &vp->next; 457 } 458 } 459 } 460 initvar(); 461 } 462 463 464 465 /* 466 * Command to list all variables which are set. Currently this command 467 * is invoked from the set command when the set command is called without 468 * any variables. 469 */ 470 471 void 472 print_quoted(const char *p) 473 { 474 const char *q; 475 476 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 477 out1fmt("%s", p); 478 return; 479 } 480 while (*p) { 481 if (*p == '\'') { 482 out1fmt("\\'"); 483 p++; 484 continue; 485 } 486 q = index(p, '\''); 487 if (!q) { 488 out1fmt("'%s'", p ); 489 return; 490 } 491 out1fmt("'%.*s'", (int)(q - p), p ); 492 p = q; 493 } 494 } 495 496 static int 497 sort_var(const void *v_v1, const void *v_v2) 498 { 499 const struct var * const *v1 = v_v1; 500 const struct var * const *v2 = v_v2; 501 502 /* XXX Will anyone notice we include the '=' of the shorter name? */ 503 return strcoll((*v1)->text, (*v2)->text); 504 } 505 506 /* 507 * POSIX requires that 'set' (but not export or readonly) output the 508 * variables in lexicographic order - by the locale's collating order (sigh). 509 * Maybe we could keep them in an ordered balanced binary tree 510 * instead of hashed lists. 511 * For now just roll 'em through qsort for printing... 512 */ 513 514 int 515 showvars(const char *name, int flag, int show_value) 516 { 517 struct var **vpp; 518 struct var *vp; 519 const char *p; 520 521 static struct var **list; /* static in case we are interrupted */ 522 static int list_len; 523 int count = 0; 524 525 if (!list) { 526 list_len = 32; 527 list = ckmalloc(list_len * sizeof *list); 528 } 529 530 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 531 for (vp = *vpp ; vp ; vp = vp->next) { 532 if (flag && !(vp->flags & flag)) 533 continue; 534 if (vp->flags & VUNSET && !(show_value & 2)) 535 continue; 536 if (count >= list_len) { 537 list = ckrealloc(list, 538 (list_len << 1) * sizeof *list); 539 list_len <<= 1; 540 } 541 list[count++] = vp; 542 } 543 } 544 545 qsort(list, count, sizeof *list, sort_var); 546 547 for (vpp = list; count--; vpp++) { 548 vp = *vpp; 549 if (name) 550 out1fmt("%s ", name); 551 for (p = vp->text ; *p != '=' ; p++) 552 out1c(*p); 553 if (!(vp->flags & VUNSET) && show_value) { 554 out1fmt("="); 555 print_quoted(++p); 556 } 557 out1c('\n'); 558 } 559 return 0; 560 } 561 562 563 564 /* 565 * The export and readonly commands. 566 */ 567 568 int 569 exportcmd(int argc, char **argv) 570 { 571 struct var *vp; 572 char *name; 573 const char *p; 574 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 575 int pflag; 576 577 pflag = nextopt("p") == 'p' ? 3 : 0; 578 if (argc <= 1 || pflag) { 579 showvars( pflag ? argv[0] : 0, flag, pflag ); 580 return 0; 581 } 582 583 while ((name = *argptr++) != NULL) { 584 if ((p = strchr(name, '=')) != NULL) { 585 p++; 586 } else { 587 vp = find_var(name, NULL, NULL); 588 if (vp != NULL) { 589 vp->flags |= flag; 590 continue; 591 } 592 } 593 setvar(name, p, flag); 594 } 595 return 0; 596 } 597 598 599 /* 600 * The "local" command. 601 */ 602 603 int 604 localcmd(int argc, char **argv) 605 { 606 char *name; 607 608 if (! in_function()) 609 error("Not in a function"); 610 while ((name = *argptr++) != NULL) { 611 mklocal(name, 0); 612 } 613 return 0; 614 } 615 616 617 /* 618 * Make a variable a local variable. When a variable is made local, its 619 * value and flags are saved in a localvar structure. The saved values 620 * will be restored when the shell function returns. We handle the name 621 * "-" as a special case. 622 */ 623 624 void 625 mklocal(const char *name, int flags) 626 { 627 struct localvar *lvp; 628 struct var **vpp; 629 struct var *vp; 630 631 INTOFF; 632 lvp = ckmalloc(sizeof (struct localvar)); 633 if (name[0] == '-' && name[1] == '\0') { 634 char *p; 635 p = ckmalloc(sizeof_optlist); 636 lvp->text = memcpy(p, optlist, sizeof_optlist); 637 vp = NULL; 638 } else { 639 vp = find_var(name, &vpp, NULL); 640 if (vp == NULL) { 641 if (strchr(name, '=')) 642 setvareq(savestr(name), VSTRFIXED|flags); 643 else 644 setvar(name, NULL, VSTRFIXED|flags); 645 vp = *vpp; /* the new variable */ 646 lvp->text = NULL; 647 lvp->flags = VUNSET; 648 } else { 649 lvp->text = vp->text; 650 lvp->flags = vp->flags; 651 vp->flags |= VSTRFIXED|VTEXTFIXED; 652 if (name[vp->name_len] == '=') 653 setvareq(savestr(name), flags); 654 } 655 } 656 lvp->vp = vp; 657 lvp->next = localvars; 658 localvars = lvp; 659 INTON; 660 } 661 662 663 /* 664 * Called after a function returns. 665 */ 666 667 void 668 poplocalvars(void) 669 { 670 struct localvar *lvp; 671 struct var *vp; 672 673 while ((lvp = localvars) != NULL) { 674 localvars = lvp->next; 675 vp = lvp->vp; 676 TRACE(("poplocalvar %s", vp ? vp->text : "-")); 677 if (vp == NULL) { /* $- saved */ 678 memcpy(optlist, lvp->text, sizeof_optlist); 679 ckfree(lvp->text); 680 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 681 (void)unsetvar(vp->text, 0); 682 } else { 683 if (vp->func && (vp->flags & VNOFUNC) == 0) 684 (*vp->func)(lvp->text + vp->name_len + 1); 685 if ((vp->flags & VTEXTFIXED) == 0) 686 ckfree(vp->text); 687 vp->flags = lvp->flags; 688 vp->text = lvp->text; 689 } 690 ckfree(lvp); 691 } 692 } 693 694 695 int 696 setvarcmd(int argc, char **argv) 697 { 698 if (argc <= 2) 699 return unsetcmd(argc, argv); 700 else if (argc == 3) 701 setvar(argv[1], argv[2], 0); 702 else 703 error("List assignment not implemented"); 704 return 0; 705 } 706 707 708 /* 709 * The unset builtin command. We unset the function before we unset the 710 * variable to allow a function to be unset when there is a readonly variable 711 * with the same name. 712 */ 713 714 int 715 unsetcmd(int argc, char **argv) 716 { 717 char **ap; 718 int i; 719 int flg_func = 0; 720 int flg_var = 0; 721 int ret = 0; 722 723 while ((i = nextopt("evf")) != '\0') { 724 if (i == 'f') 725 flg_func = 1; 726 else 727 flg_var = i; 728 } 729 if (flg_func == 0 && flg_var == 0) 730 flg_var = 1; 731 732 for (ap = argptr; *ap ; ap++) { 733 if (flg_func) 734 ret |= unsetfunc(*ap); 735 if (flg_var) 736 ret |= unsetvar(*ap, flg_var == 'e'); 737 } 738 return ret; 739 } 740 741 742 /* 743 * Unset the specified variable. 744 */ 745 746 int 747 unsetvar(const char *s, int unexport) 748 { 749 struct var **vpp; 750 struct var *vp; 751 752 vp = find_var(s, &vpp, NULL); 753 if (vp == NULL) 754 return 1; 755 756 if (vp->flags & VREADONLY) 757 return (1); 758 759 INTOFF; 760 if (unexport) { 761 vp->flags &= ~VEXPORT; 762 } else { 763 if (vp->text[vp->name_len + 1] != '\0') 764 setvar(s, nullstr, 0); 765 vp->flags &= ~VEXPORT; 766 vp->flags |= VUNSET; 767 if ((vp->flags & VSTRFIXED) == 0) { 768 if ((vp->flags & VTEXTFIXED) == 0) 769 ckfree(vp->text); 770 *vpp = vp->next; 771 ckfree(vp); 772 } 773 } 774 INTON; 775 return 0; 776 } 777 778 779 /* 780 * Returns true if the two strings specify the same varable. The first 781 * variable name is terminated by '='; the second may be terminated by 782 * either '=' or '\0'. 783 */ 784 785 STATIC int 786 strequal(const char *p, const char *q) 787 { 788 while (*p == *q++) { 789 if (*p++ == '=') 790 return 1; 791 } 792 if (*p == '=' && *(q - 1) == '\0') 793 return 1; 794 return 0; 795 } 796 797 /* 798 * Search for a variable. 799 * 'name' may be terminated by '=' or a NUL. 800 * vppp is set to the pointer to vp, or the list head if vp isn't found 801 * lenp is set to the number of charactets in 'name' 802 */ 803 804 STATIC struct var * 805 find_var(const char *name, struct var ***vppp, int *lenp) 806 { 807 unsigned int hashval; 808 int len; 809 struct var *vp, **vpp; 810 const char *p = name; 811 812 hashval = 0; 813 while (*p && *p != '=') 814 hashval = 2 * hashval + (unsigned char)*p++; 815 len = p - name; 816 817 if (lenp) 818 *lenp = len; 819 vpp = &vartab[hashval % VTABSIZE]; 820 if (vppp) 821 *vppp = vpp; 822 823 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 824 if (vp->name_len != len) 825 continue; 826 if (memcmp(vp->text, name, len) != 0) 827 continue; 828 if (vppp) 829 *vppp = vpp; 830 return vp; 831 } 832 return NULL; 833 } 834