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