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