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