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