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