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