1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $Id: var.c,v 1.10 1997/04/28 03:06:39 steve Exp $ 37 */ 38 39 #ifndef lint 40 static char const sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 41 #endif /* not lint */ 42 43 #include <unistd.h> 44 #include <stdlib.h> 45 46 /* 47 * Shell variables. 48 */ 49 50 #include <locale.h> 51 52 #include "shell.h" 53 #include "output.h" 54 #include "expand.h" 55 #include "nodes.h" /* for other headers */ 56 #include "eval.h" /* defines cmdenviron */ 57 #include "exec.h" 58 #include "syntax.h" 59 #include "options.h" 60 #include "mail.h" 61 #include "var.h" 62 #include "memalloc.h" 63 #include "error.h" 64 #include "mystring.h" 65 #include "parser.h" 66 #ifndef NO_HISTORY 67 #include "myhistedit.h" 68 #endif 69 70 71 #define VTABSIZE 39 72 73 74 struct varinit { 75 struct var *var; 76 int flags; 77 char *text; 78 void (*func) __P((const char *)); 79 }; 80 81 82 #if ATTY 83 struct var vatty; 84 #endif 85 #ifndef NO_HISTORY 86 struct var vhistsize; 87 #endif 88 struct var vifs; 89 struct var vmail; 90 struct var vmpath; 91 struct var vpath; 92 struct var vps1; 93 struct var vps2; 94 struct var vvers; 95 #if ATTY 96 struct var vterm; 97 #endif 98 struct var voptind; 99 100 const struct varinit varinit[] = { 101 #if ATTY 102 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", 103 NULL }, 104 #endif 105 #ifndef NO_HISTORY 106 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 107 sethistsize }, 108 #endif 109 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 110 NULL }, 111 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", 112 NULL }, 113 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 114 NULL }, 115 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=/bin:/usr/bin", 116 changepath }, 117 /* 118 * vps1 depends on uid 119 */ 120 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 121 NULL }, 122 #if ATTY 123 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 124 NULL }, 125 #endif 126 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", 127 getoptsreset }, 128 { NULL, 0, NULL, 129 NULL } 130 }; 131 132 struct var *vartab[VTABSIZE]; 133 134 STATIC struct var **hashvar __P((char *)); 135 STATIC int varequal __P((char *, char *)); 136 STATIC int localevar __P((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 #if __GNUC__ 204 /* Avoid longjmp clobbering */ 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 char *name, *val; 226 int flags; 227 { 228 char *p, *q; 229 int len; 230 int namelen; 231 char *nameeq; 232 int isbad; 233 234 isbad = 0; 235 p = name; 236 if (! is_name(*p)) 237 isbad = 1; 238 p++; 239 for (;;) { 240 if (! is_in_name(*p)) { 241 if (*p == '\0' || *p == '=') 242 break; 243 isbad = 1; 244 } 245 p++; 246 } 247 namelen = p - name; 248 if (isbad) 249 error("%.*s: bad variable name", namelen, name); 250 len = namelen + 2; /* 2 is space for '=' and '\0' */ 251 if (val == NULL) { 252 flags |= VUNSET; 253 } else { 254 len += strlen(val); 255 } 256 p = nameeq = ckmalloc(len); 257 q = name; 258 while (--namelen >= 0) 259 *p++ = *q++; 260 *p++ = '='; 261 *p = '\0'; 262 if (val) 263 scopy(val, p); 264 setvareq(nameeq, flags); 265 } 266 267 STATIC int 268 localevar(s) 269 char *s; 270 { 271 static char *lnames[7] = { 272 "ALL", "COLLATE", "CTYPE", "MONETARY", 273 "NUMERIC", "TIME", NULL 274 }; 275 char **ss; 276 277 if (*s != 'L') 278 return 0; 279 if (varequal(s + 1, "ANG")) 280 return 1; 281 if (strncmp(s + 1, "C_", 2) != 0) 282 return 0; 283 for (ss = lnames; *ss ; ss++) 284 if (varequal(s + 3, *ss)) 285 return 1; 286 return 0; 287 } 288 289 /* 290 * Same as setvar except that the variable and value are passed in 291 * the first argument as name=value. Since the first argument will 292 * be actually stored in the table, it should not be a string that 293 * will go away. 294 */ 295 296 void 297 setvareq(s, flags) 298 char *s; 299 int flags; 300 { 301 struct var *vp, **vpp; 302 303 vpp = hashvar(s); 304 for (vp = *vpp ; vp ; vp = vp->next) { 305 if (varequal(s, vp->text)) { 306 if (vp->flags & VREADONLY) { 307 size_t len = strchr(s, '=') - s; 308 error("%.*s: is read only", len, s); 309 } 310 INTOFF; 311 312 if (vp->func && (flags & VNOFUNC) == 0) 313 (*vp->func)(strchr(s, '=') + 1); 314 315 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 316 ckfree(vp->text); 317 318 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 319 vp->flags |= flags; 320 vp->text = s; 321 322 /* 323 * We could roll this to a function, to handle it as 324 * a regular variable function callback, but why bother? 325 */ 326 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 327 chkmail(1); 328 if ((vp->flags & VEXPORT) && localevar(s)) { 329 putenv(s); 330 (void) setlocale(LC_ALL, ""); 331 } 332 INTON; 333 return; 334 } 335 } 336 /* not found */ 337 vp = ckmalloc(sizeof (*vp)); 338 vp->flags = flags; 339 vp->text = s; 340 vp->next = *vpp; 341 vp->func = NULL; 342 INTOFF; 343 *vpp = vp; 344 if ((vp->flags & VEXPORT) && localevar(s)) { 345 putenv(s); 346 (void) setlocale(LC_ALL, ""); 347 } 348 INTON; 349 } 350 351 352 353 /* 354 * Process a linked list of variable assignments. 355 */ 356 357 void 358 listsetvar(list) 359 struct strlist *list; 360 { 361 struct strlist *lp; 362 363 INTOFF; 364 for (lp = list ; lp ; lp = lp->next) { 365 setvareq(savestr(lp->text), 0); 366 } 367 INTON; 368 } 369 370 371 372 /* 373 * Find the value of a variable. Returns NULL if not set. 374 */ 375 376 char * 377 lookupvar(name) 378 char *name; 379 { 380 struct var *v; 381 382 for (v = *hashvar(name) ; v ; v = v->next) { 383 if (varequal(v->text, name)) { 384 if (v->flags & VUNSET) 385 return NULL; 386 return strchr(v->text, '=') + 1; 387 } 388 } 389 return NULL; 390 } 391 392 393 394 /* 395 * Search the environment of a builtin command. If the second argument 396 * is nonzero, return the value of a variable even if it hasn't been 397 * exported. 398 */ 399 400 char * 401 bltinlookup(name, doall) 402 char *name; 403 int doall; 404 { 405 struct strlist *sp; 406 struct var *v; 407 408 for (sp = cmdenviron ; sp ; sp = sp->next) { 409 if (varequal(sp->text, name)) 410 return strchr(sp->text, '=') + 1; 411 } 412 for (v = *hashvar(name) ; v ; v = v->next) { 413 if (varequal(v->text, name)) { 414 if ((v->flags & VUNSET) 415 || (!doall && (v->flags & VEXPORT) == 0)) 416 return NULL; 417 return strchr(v->text, '=') + 1; 418 } 419 } 420 return NULL; 421 } 422 423 424 425 /* 426 * Generate a list of exported variables. This routine is used to construct 427 * the third argument to execve when executing a program. 428 */ 429 430 char ** 431 environment() { 432 int nenv; 433 struct var **vpp; 434 struct var *vp; 435 char **env, **ep; 436 437 nenv = 0; 438 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 439 for (vp = *vpp ; vp ; vp = vp->next) 440 if (vp->flags & VEXPORT) 441 nenv++; 442 } 443 ep = env = stalloc((nenv + 1) * sizeof *env); 444 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 445 for (vp = *vpp ; vp ; vp = vp->next) 446 if (vp->flags & VEXPORT) 447 *ep++ = vp->text; 448 } 449 *ep = NULL; 450 return env; 451 } 452 453 454 /* 455 * Called when a shell procedure is invoked to clear out nonexported 456 * variables. It is also necessary to reallocate variables of with 457 * VSTACK set since these are currently allocated on the stack. 458 */ 459 460 #ifdef mkinit 461 MKINIT void shprocvar(); 462 463 SHELLPROC { 464 shprocvar(); 465 } 466 #endif 467 468 void 469 shprocvar() { 470 struct var **vpp; 471 struct var *vp, **prev; 472 473 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 474 for (prev = vpp ; (vp = *prev) != NULL ; ) { 475 if ((vp->flags & VEXPORT) == 0) { 476 *prev = vp->next; 477 if ((vp->flags & VTEXTFIXED) == 0) 478 ckfree(vp->text); 479 if ((vp->flags & VSTRFIXED) == 0) 480 ckfree(vp); 481 } else { 482 if (vp->flags & VSTACK) { 483 vp->text = savestr(vp->text); 484 vp->flags &=~ VSTACK; 485 } 486 prev = &vp->next; 487 } 488 } 489 } 490 initvar(); 491 } 492 493 494 495 /* 496 * Command to list all variables which are set. Currently this command 497 * is invoked from the set command when the set command is called without 498 * any variables. 499 */ 500 501 int 502 showvarscmd(argc, argv) 503 int argc __unused; 504 char **argv __unused; 505 { 506 struct var **vpp; 507 struct var *vp; 508 509 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 510 for (vp = *vpp ; vp ; vp = vp->next) { 511 if ((vp->flags & VUNSET) == 0) 512 out1fmt("%s\n", vp->text); 513 } 514 } 515 return 0; 516 } 517 518 519 520 /* 521 * The export and readonly commands. 522 */ 523 524 int 525 exportcmd(argc, argv) 526 int argc; 527 char **argv; 528 { 529 struct var **vpp; 530 struct var *vp; 531 char *name; 532 char *p; 533 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 534 535 listsetvar(cmdenviron); 536 if (argc > 1) { 537 while ((name = *argptr++) != NULL) { 538 if ((p = strchr(name, '=')) != NULL) { 539 p++; 540 } else { 541 vpp = hashvar(name); 542 for (vp = *vpp ; vp ; vp = vp->next) { 543 if (varequal(vp->text, name)) { 544 vp->flags |= flag; 545 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 546 putenv(vp->text); 547 (void) setlocale(LC_ALL, ""); 548 } 549 goto found; 550 } 551 } 552 } 553 setvar(name, p, flag); 554 found:; 555 } 556 } else { 557 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 558 for (vp = *vpp ; vp ; vp = vp->next) { 559 if (vp->flags & flag) { 560 for (p = vp->text ; *p != '=' ; p++) 561 out1c(*p); 562 out1c('\n'); 563 } 564 } 565 } 566 } 567 return 0; 568 } 569 570 571 /* 572 * The "local" command. 573 */ 574 575 int 576 localcmd(argc, argv) 577 int argc __unused; 578 char **argv __unused; 579 { 580 char *name; 581 582 if (! in_function()) 583 error("Not in a function"); 584 while ((name = *argptr++) != NULL) { 585 mklocal(name); 586 } 587 return 0; 588 } 589 590 591 /* 592 * Make a variable a local variable. When a variable is made local, it's 593 * value and flags are saved in a localvar structure. The saved values 594 * will be restored when the shell function returns. We handle the name 595 * "-" as a special case. 596 */ 597 598 void 599 mklocal(name) 600 char *name; 601 { 602 struct localvar *lvp; 603 struct var **vpp; 604 struct var *vp; 605 606 INTOFF; 607 lvp = ckmalloc(sizeof (struct localvar)); 608 if (name[0] == '-' && name[1] == '\0') { 609 lvp->text = ckmalloc(sizeof optlist); 610 memcpy(lvp->text, optlist, sizeof optlist); 611 vp = NULL; 612 } else { 613 vpp = hashvar(name); 614 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); 615 if (vp == NULL) { 616 if (strchr(name, '=')) 617 setvareq(savestr(name), VSTRFIXED); 618 else 619 setvar(name, NULL, VSTRFIXED); 620 vp = *vpp; /* the new variable */ 621 lvp->text = NULL; 622 lvp->flags = VUNSET; 623 } else { 624 lvp->text = vp->text; 625 lvp->flags = vp->flags; 626 vp->flags |= VSTRFIXED|VTEXTFIXED; 627 if (strchr(name, '=')) 628 setvareq(savestr(name), 0); 629 } 630 } 631 lvp->vp = vp; 632 lvp->next = localvars; 633 localvars = lvp; 634 INTON; 635 } 636 637 638 /* 639 * Called after a function returns. 640 */ 641 642 void 643 poplocalvars() { 644 struct localvar *lvp; 645 struct var *vp; 646 647 while ((lvp = localvars) != NULL) { 648 localvars = lvp->next; 649 vp = lvp->vp; 650 if (vp == NULL) { /* $- saved */ 651 memcpy(optlist, lvp->text, sizeof optlist); 652 ckfree(lvp->text); 653 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 654 (void)unsetvar(vp->text); 655 } else { 656 if ((vp->flags & VTEXTFIXED) == 0) 657 ckfree(vp->text); 658 vp->flags = lvp->flags; 659 vp->text = lvp->text; 660 } 661 ckfree(lvp); 662 } 663 } 664 665 666 int 667 setvarcmd(argc, argv) 668 int argc; 669 char **argv; 670 { 671 if (argc <= 2) 672 return unsetcmd(argc, argv); 673 else if (argc == 3) 674 setvar(argv[1], argv[2], 0); 675 else 676 error("List assignment not implemented"); 677 return 0; 678 } 679 680 681 /* 682 * The unset builtin command. We unset the function before we unset the 683 * variable to allow a function to be unset when there is a readonly variable 684 * with the same name. 685 */ 686 687 int 688 unsetcmd(argc, argv) 689 int argc __unused; 690 char **argv __unused; 691 { 692 char **ap; 693 int i; 694 int flg_func = 0; 695 int flg_var = 0; 696 int ret = 0; 697 698 while ((i = nextopt("vf")) != '\0') { 699 if (i == 'f') 700 flg_func = 1; 701 else 702 flg_var = 1; 703 } 704 if (flg_func == 0 && flg_var == 0) 705 flg_var = 1; 706 707 for (ap = argptr; *ap ; ap++) { 708 if (flg_func) 709 ret |= unsetfunc(*ap); 710 if (flg_var) 711 ret |= unsetvar(*ap); 712 } 713 return ret; 714 } 715 716 717 /* 718 * Unset the specified variable. 719 */ 720 721 int 722 unsetvar(s) 723 char *s; 724 { 725 struct var **vpp; 726 struct var *vp; 727 728 vpp = hashvar(s); 729 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 730 if (varequal(vp->text, s)) { 731 if (vp->flags & VREADONLY) 732 return (1); 733 INTOFF; 734 if (*(strchr(vp->text, '=') + 1) != '\0') 735 setvar(s, nullstr, 0); 736 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 737 unsetenv(s); 738 setlocale(LC_ALL, ""); 739 } 740 vp->flags &= ~VEXPORT; 741 vp->flags |= VUNSET; 742 if ((vp->flags & VSTRFIXED) == 0) { 743 if ((vp->flags & VTEXTFIXED) == 0) 744 ckfree(vp->text); 745 *vpp = vp->next; 746 ckfree(vp); 747 } 748 INTON; 749 return (0); 750 } 751 } 752 753 return (1); 754 } 755 756 757 758 /* 759 * Find the appropriate entry in the hash table from the name. 760 */ 761 762 STATIC struct var ** 763 hashvar(p) 764 char *p; 765 { 766 unsigned int hashval; 767 768 hashval = ((unsigned char) *p) << 4; 769 while (*p && *p != '=') 770 hashval += (unsigned char) *p++; 771 return &vartab[hashval % VTABSIZE]; 772 } 773 774 775 776 /* 777 * Returns true if the two strings specify the same varable. The first 778 * variable name is terminated by '='; the second may be terminated by 779 * either '=' or '\0'. 780 */ 781 782 STATIC int 783 varequal(p, q) 784 char *p, *q; 785 { 786 while (*p == *q++) { 787 if (*p++ == '=') 788 return 1; 789 } 790 if (*p == '=' && *(q - 1) == '\0') 791 return 1; 792 return 0; 793 } 794