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