1 /* $NetBSD: var.c,v 1.15 1996/10/16 15:24:31 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. 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 #ifndef lint 40 #if 0 41 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 42 #else 43 static char rcsid[] = "$NetBSD: var.c,v 1.15 1996/10/16 15:24:31 christos Exp $"; 44 #endif 45 #endif /* not lint */ 46 47 #include <unistd.h> 48 #include <stdlib.h> 49 50 /* 51 * Shell variables. 52 */ 53 54 #include "shell.h" 55 #include "output.h" 56 #include "expand.h" 57 #include "nodes.h" /* for other headers */ 58 #include "eval.h" /* defines cmdenviron */ 59 #include "exec.h" 60 #include "syntax.h" 61 #include "options.h" 62 #include "mail.h" 63 #include "var.h" 64 #include "memalloc.h" 65 #include "error.h" 66 #include "mystring.h" 67 #include "parser.h" 68 #ifndef NO_HISTORY 69 #include "myhistedit.h" 70 #endif 71 72 73 #define VTABSIZE 39 74 75 76 struct varinit { 77 struct var *var; 78 int flags; 79 char *text; 80 void (*func) __P((const char *)); 81 }; 82 83 84 #if ATTY 85 struct var vatty; 86 #endif 87 #ifndef NO_HISTORY 88 struct var vhistsize; 89 #endif 90 struct var vifs; 91 struct var vmail; 92 struct var vmpath; 93 struct var vpath; 94 struct var vps1; 95 struct var vps2; 96 struct var vvers; 97 #if ATTY 98 struct var vterm; 99 #endif 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 NO_HISTORY 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=/bin:/usr/bin", 118 changepath }, 119 /* 120 * vps1 depends on uid 121 */ 122 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 123 NULL }, 124 #if ATTY 125 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 126 NULL }, 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((char *)); 137 STATIC int varequal __P((char *, char *)); 138 139 /* 140 * Initialize the varable symbol tables and import the environment 141 */ 142 143 #ifdef mkinit 144 INCLUDE "var.h" 145 INIT { 146 char **envp; 147 extern char **environ; 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 = 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 = 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 char *name, *val; 199 int flags; 200 { 201 struct jmploc jmploc; 202 struct jmploc *volatile savehandler = handler; 203 int err = 0; 204 205 if (setjmp(jmploc.loc)) 206 err = 1; 207 else { 208 handler = &jmploc; 209 setvar(name, val, flags); 210 } 211 handler = savehandler; 212 return err; 213 } 214 215 /* 216 * Set the value of a variable. The flags argument is ored with the 217 * flags of the variable. If val is NULL, the variable is unset. 218 */ 219 220 void 221 setvar(name, val, flags) 222 char *name, *val; 223 int flags; 224 { 225 char *p, *q; 226 int len; 227 int namelen; 228 char *nameeq; 229 int isbad; 230 231 isbad = 0; 232 p = name; 233 if (! is_name(*p)) 234 isbad = 1; 235 p++; 236 for (;;) { 237 if (! is_in_name(*p)) { 238 if (*p == '\0' || *p == '=') 239 break; 240 isbad = 1; 241 } 242 p++; 243 } 244 namelen = p - name; 245 if (isbad) 246 error("%.*s: bad variable name", namelen, name); 247 len = namelen + 2; /* 2 is space for '=' and '\0' */ 248 if (val == NULL) { 249 flags |= VUNSET; 250 } else { 251 len += strlen(val); 252 } 253 p = nameeq = ckmalloc(len); 254 q = name; 255 while (--namelen >= 0) 256 *p++ = *q++; 257 *p++ = '='; 258 *p = '\0'; 259 if (val) 260 scopy(val, p); 261 setvareq(nameeq, flags); 262 } 263 264 265 266 /* 267 * Same as setvar except that the variable and value are passed in 268 * the first argument as name=value. Since the first argument will 269 * be actually stored in the table, it should not be a string that 270 * will go away. 271 */ 272 273 void 274 setvareq(s, flags) 275 char *s; 276 int flags; 277 { 278 struct var *vp, **vpp; 279 280 vpp = hashvar(s); 281 for (vp = *vpp ; vp ; vp = vp->next) { 282 if (varequal(s, vp->text)) { 283 if (vp->flags & VREADONLY) { 284 size_t len = strchr(s, '=') - s; 285 error("%.*s: is read only", len, s); 286 } 287 INTOFF; 288 289 if (vp->func && (flags & VNOFUNC) == 0) 290 (*vp->func)(strchr(s, '=') + 1); 291 292 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 293 ckfree(vp->text); 294 295 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 296 vp->flags |= flags; 297 vp->text = s; 298 299 /* 300 * We could roll this to a function, to handle it as 301 * a regular variable function callback, but why bother? 302 */ 303 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 304 chkmail(1); 305 INTON; 306 return; 307 } 308 } 309 /* not found */ 310 vp = ckmalloc(sizeof (*vp)); 311 vp->flags = flags; 312 vp->text = s; 313 vp->next = *vpp; 314 vp->func = NULL; 315 *vpp = vp; 316 } 317 318 319 320 /* 321 * Process a linked list of variable assignments. 322 */ 323 324 void 325 listsetvar(list) 326 struct strlist *list; 327 { 328 struct strlist *lp; 329 330 INTOFF; 331 for (lp = list ; lp ; lp = lp->next) { 332 setvareq(savestr(lp->text), 0); 333 } 334 INTON; 335 } 336 337 338 339 /* 340 * Find the value of a variable. Returns NULL if not set. 341 */ 342 343 char * 344 lookupvar(name) 345 char *name; 346 { 347 struct var *v; 348 349 for (v = *hashvar(name) ; v ; v = v->next) { 350 if (varequal(v->text, name)) { 351 if (v->flags & VUNSET) 352 return NULL; 353 return strchr(v->text, '=') + 1; 354 } 355 } 356 return NULL; 357 } 358 359 360 361 /* 362 * Search the environment of a builtin command. If the second argument 363 * is nonzero, return the value of a variable even if it hasn't been 364 * exported. 365 */ 366 367 char * 368 bltinlookup(name, doall) 369 char *name; 370 int doall; 371 { 372 struct strlist *sp; 373 struct var *v; 374 375 for (sp = cmdenviron ; sp ; sp = sp->next) { 376 if (varequal(sp->text, name)) 377 return strchr(sp->text, '=') + 1; 378 } 379 for (v = *hashvar(name) ; v ; v = v->next) { 380 if (varequal(v->text, name)) { 381 if ((v->flags & VUNSET) 382 || (!doall && (v->flags & VEXPORT) == 0)) 383 return NULL; 384 return strchr(v->text, '=') + 1; 385 } 386 } 387 return NULL; 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() { 399 int nenv; 400 struct var **vpp; 401 struct var *vp; 402 char **env, **ep; 403 404 nenv = 0; 405 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 406 for (vp = *vpp ; vp ; vp = vp->next) 407 if (vp->flags & VEXPORT) 408 nenv++; 409 } 410 ep = env = stalloc((nenv + 1) * sizeof *env); 411 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 412 for (vp = *vpp ; vp ; vp = vp->next) 413 if (vp->flags & VEXPORT) 414 *ep++ = vp->text; 415 } 416 *ep = NULL; 417 return env; 418 } 419 420 421 /* 422 * Called when a shell procedure is invoked to clear out nonexported 423 * variables. It is also necessary to reallocate variables of with 424 * VSTACK set since these are currently allocated on the stack. 425 */ 426 427 #ifdef mkinit 428 MKINIT void shprocvar(); 429 430 SHELLPROC { 431 shprocvar(); 432 } 433 #endif 434 435 void 436 shprocvar() { 437 struct var **vpp; 438 struct var *vp, **prev; 439 440 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 441 for (prev = vpp ; (vp = *prev) != NULL ; ) { 442 if ((vp->flags & VEXPORT) == 0) { 443 *prev = vp->next; 444 if ((vp->flags & VTEXTFIXED) == 0) 445 ckfree(vp->text); 446 if ((vp->flags & VSTRFIXED) == 0) 447 ckfree(vp); 448 } else { 449 if (vp->flags & VSTACK) { 450 vp->text = savestr(vp->text); 451 vp->flags &=~ VSTACK; 452 } 453 prev = &vp->next; 454 } 455 } 456 } 457 initvar(); 458 } 459 460 461 462 /* 463 * Command to list all variables which are set. Currently this command 464 * is invoked from the set command when the set command is called without 465 * any variables. 466 */ 467 468 int 469 showvarscmd(argc, argv) 470 int argc; 471 char **argv; 472 { 473 struct var **vpp; 474 struct var *vp; 475 476 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 477 for (vp = *vpp ; vp ; vp = vp->next) { 478 if ((vp->flags & VUNSET) == 0) 479 out1fmt("%s\n", vp->text); 480 } 481 } 482 return 0; 483 } 484 485 486 487 /* 488 * The export and readonly commands. 489 */ 490 491 int 492 exportcmd(argc, argv) 493 int argc; 494 char **argv; 495 { 496 struct var **vpp; 497 struct var *vp; 498 char *name; 499 char *p; 500 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 501 502 listsetvar(cmdenviron); 503 if (argc > 1) { 504 while ((name = *argptr++) != NULL) { 505 if ((p = strchr(name, '=')) != NULL) { 506 p++; 507 } else { 508 vpp = hashvar(name); 509 for (vp = *vpp ; vp ; vp = vp->next) { 510 if (varequal(vp->text, name)) { 511 vp->flags |= flag; 512 goto found; 513 } 514 } 515 } 516 setvar(name, p, flag); 517 found:; 518 } 519 } else { 520 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 521 for (vp = *vpp ; vp ; vp = vp->next) { 522 if (vp->flags & flag) { 523 for (p = vp->text ; *p != '=' ; p++) 524 out1c(*p); 525 out1c('\n'); 526 } 527 } 528 } 529 } 530 return 0; 531 } 532 533 534 /* 535 * The "local" command. 536 */ 537 538 int 539 localcmd(argc, argv) 540 int argc; 541 char **argv; 542 { 543 char *name; 544 545 if (! in_function()) 546 error("Not in a function"); 547 while ((name = *argptr++) != NULL) { 548 mklocal(name); 549 } 550 return 0; 551 } 552 553 554 /* 555 * Make a variable a local variable. When a variable is made local, it's 556 * value and flags are saved in a localvar structure. The saved values 557 * will be restored when the shell function returns. We handle the name 558 * "-" as a special case. 559 */ 560 561 void 562 mklocal(name) 563 char *name; 564 { 565 struct localvar *lvp; 566 struct var **vpp; 567 struct var *vp; 568 569 INTOFF; 570 lvp = ckmalloc(sizeof (struct localvar)); 571 if (name[0] == '-' && name[1] == '\0') { 572 lvp->text = ckmalloc(sizeof optlist); 573 memcpy(lvp->text, optlist, sizeof optlist); 574 vp = NULL; 575 } else { 576 vpp = hashvar(name); 577 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); 578 if (vp == NULL) { 579 if (strchr(name, '=')) 580 setvareq(savestr(name), VSTRFIXED); 581 else 582 setvar(name, NULL, VSTRFIXED); 583 vp = *vpp; /* the new variable */ 584 lvp->text = NULL; 585 lvp->flags = VUNSET; 586 } else { 587 lvp->text = vp->text; 588 lvp->flags = vp->flags; 589 vp->flags |= VSTRFIXED|VTEXTFIXED; 590 if (strchr(name, '=')) 591 setvareq(savestr(name), 0); 592 } 593 } 594 lvp->vp = vp; 595 lvp->next = localvars; 596 localvars = lvp; 597 INTON; 598 } 599 600 601 /* 602 * Called after a function returns. 603 */ 604 605 void 606 poplocalvars() { 607 struct localvar *lvp; 608 struct var *vp; 609 610 while ((lvp = localvars) != NULL) { 611 localvars = lvp->next; 612 vp = lvp->vp; 613 if (vp == NULL) { /* $- saved */ 614 memcpy(optlist, lvp->text, sizeof optlist); 615 ckfree(lvp->text); 616 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 617 (void)unsetvar(vp->text); 618 } else { 619 if ((vp->flags & VTEXTFIXED) == 0) 620 ckfree(vp->text); 621 vp->flags = lvp->flags; 622 vp->text = lvp->text; 623 } 624 ckfree(lvp); 625 } 626 } 627 628 629 int 630 setvarcmd(argc, argv) 631 int argc; 632 char **argv; 633 { 634 if (argc <= 2) 635 return unsetcmd(argc, argv); 636 else if (argc == 3) 637 setvar(argv[1], argv[2], 0); 638 else 639 error("List assignment not implemented"); 640 return 0; 641 } 642 643 644 /* 645 * The unset builtin command. We unset the function before we unset the 646 * variable to allow a function to be unset when there is a readonly variable 647 * with the same name. 648 */ 649 650 int 651 unsetcmd(argc, argv) 652 int argc; 653 char **argv; 654 { 655 char **ap; 656 int i; 657 int flg_func = 0; 658 int flg_var = 0; 659 int ret = 0; 660 661 while ((i = nextopt("vf")) != '\0') { 662 if (i == 'f') 663 flg_func = 1; 664 else 665 flg_var = 1; 666 } 667 if (flg_func == 0 && flg_var == 0) 668 flg_var = 1; 669 670 for (ap = argptr; *ap ; ap++) { 671 if (flg_func) 672 ret |= unsetfunc(*ap); 673 if (flg_var) 674 ret |= unsetvar(*ap); 675 } 676 return ret; 677 } 678 679 680 /* 681 * Unset the specified variable. 682 */ 683 684 int 685 unsetvar(s) 686 char *s; 687 { 688 struct var **vpp; 689 struct var *vp; 690 691 vpp = hashvar(s); 692 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 693 if (varequal(vp->text, s)) { 694 if (vp->flags & VREADONLY) 695 return (1); 696 INTOFF; 697 if (*(strchr(vp->text, '=') + 1) != '\0') 698 setvar(s, nullstr, 0); 699 vp->flags &= ~VEXPORT; 700 vp->flags |= VUNSET; 701 if ((vp->flags & VSTRFIXED) == 0) { 702 if ((vp->flags & VTEXTFIXED) == 0) 703 ckfree(vp->text); 704 *vpp = vp->next; 705 ckfree(vp); 706 } 707 INTON; 708 return (0); 709 } 710 } 711 712 return (1); 713 } 714 715 716 717 /* 718 * Find the appropriate entry in the hash table from the name. 719 */ 720 721 STATIC struct var ** 722 hashvar(p) 723 register char *p; 724 { 725 unsigned int hashval; 726 727 hashval = ((unsigned char) *p) << 4; 728 while (*p && *p != '=') 729 hashval += (unsigned char) *p++; 730 return &vartab[hashval % VTABSIZE]; 731 } 732 733 734 735 /* 736 * Returns true if the two strings specify the same varable. The first 737 * variable name is terminated by '='; the second may be terminated by 738 * either '=' or '\0'. 739 */ 740 741 STATIC int 742 varequal(p, q) 743 register char *p, *q; 744 { 745 while (*p == *q++) { 746 if (*p++ == '=') 747 return 1; 748 } 749 if (*p == '=' && *(q - 1) == '\0') 750 return 1; 751 return 0; 752 } 753