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