1/* $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $ */ 2 3/*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36#ifndef lint 37#if 0 38static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 39#else 40__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $"); 41#endif 42#endif /* not lint */ 43 44#include <unistd.h> 45#include <stdlib.h> 46#include <paths.h> 47 48/* 49 * Shell variables. 50 */ 51 52#include "shell.h" 53#include "output.h" 54#include "expand.h" 55#include "nodes.h" /* for other headers */ 56#include "eval.h" /* defines cmdenviron */ 57#include "exec.h" 58#include "syntax.h" 59#include "options.h" 60#include "var.h" 61#include "memalloc.h" 62#include "error.h" 63#include "mystring.h" 64#include "parser.h" 65#include "show.h" 66#ifndef SMALL 67#include "myhistedit.h" 68#endif 69 70#ifdef SMALL 71#define VTABSIZE 39 72#else 73#define VTABSIZE 517 74#endif 75 76 77struct varinit { 78 struct var *var; 79 int flags; 80 const char *text; 81 void (*func)(const char *); 82}; 83 84 85#if ATTY 86struct var vatty; 87#endif 88#ifdef WITH_HISTORY 89struct var vhistsize; 90struct var vterm; 91#endif 92struct var vifs; 93struct var vmpath; 94struct var vpath; 95struct var vps1; 96struct var vps2; 97struct var vps4; 98struct var vvers; 99struct var voptind; 100 101const struct varinit varinit[] = { 102#if ATTY 103 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", 104 NULL }, 105#endif 106#ifdef WITH_HISTORY 107 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 108 sethistsize }, 109#endif 110 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 111 NULL }, 112 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 113 NULL }, 114 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, 115 changepath }, 116 /* 117 * vps1 depends on uid 118 */ 119 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 120 NULL }, 121 { &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 122 NULL }, 123#ifdef WITH_HISTORY 124 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 125 setterm }, 126#endif 127 { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", 128 getoptsreset }, 129 { NULL, 0, NULL, 130 NULL } 131}; 132 133struct var *vartab[VTABSIZE]; 134 135STATIC int strequal(const char *, const char *); 136STATIC struct var *find_var(const char *, struct var ***, int *); 137 138/* 139 * Initialize the varable symbol tables and import the environment 140 */ 141 142#ifdef mkinit 143INCLUDE "var.h" 144MKINIT char **environ; 145INIT { 146 char **envp; 147 148 initvar(); 149 for (envp = environ ; *envp ; envp++) { 150 if (strchr(*envp, '=')) { 151 setvareq(*envp, VEXPORT|VTEXTFIXED); 152 } 153 } 154} 155#endif 156 157 158/* 159 * This routine initializes the builtin variables. It is called when the 160 * shell is initialized and again when a shell procedure is spawned. 161 */ 162 163void 164initvar(void) 165{ 166 const struct varinit *ip; 167 struct var *vp; 168 struct var **vpp; 169 170 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 171 if (find_var(ip->text, &vpp, &vp->name_len) != NULL) 172 continue; 173 vp->next = *vpp; 174 *vpp = vp; 175 vp->text = strdup(ip->text); 176 vp->flags = ip->flags; 177 vp->func = ip->func; 178 } 179 /* 180 * PS1 depends on uid 181 */ 182 if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { 183 vps1.next = *vpp; 184 *vpp = &vps1; 185 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); 186 vps1.flags = VSTRFIXED|VTEXTFIXED; 187 } 188} 189 190/* 191 * Safe version of setvar, returns 1 on success 0 on failure. 192 */ 193 194int 195setvarsafe(const char *name, const char *val, int flags) 196{ 197 struct jmploc jmploc; 198 struct jmploc *volatile savehandler = handler; 199 int err = 0; 200#ifdef __GNUC__ 201 (void) &err; 202#endif 203 204 if (setjmp(jmploc.loc)) 205 err = 1; 206 else { 207 handler = &jmploc; 208 setvar(name, val, flags); 209 } 210 handler = savehandler; 211 return err; 212} 213 214/* 215 * Set the value of a variable. The flags argument is ored with the 216 * flags of the variable. If val is NULL, the variable is unset. 217 */ 218 219void 220setvar(const char *name, const char *val, int flags) 221{ 222 const char *p; 223 const char *q; 224 char *d; 225 int len; 226 int namelen; 227 char *nameeq; 228 int isbad; 229 230 isbad = 0; 231 p = name; 232 if (! is_name(*p)) 233 isbad = 1; 234 p++; 235 for (;;) { 236 if (! is_in_name(*p)) { 237 if (*p == '\0' || *p == '=') 238 break; 239 isbad = 1; 240 } 241 p++; 242 } 243 namelen = p - name; 244 if (isbad) 245 error("%.*s: bad variable name", namelen, name); 246 len = namelen + 2; /* 2 is space for '=' and '\0' */ 247 if (val == NULL) { 248 flags |= VUNSET; 249 } else { 250 len += strlen(val); 251 } 252 d = nameeq = ckmalloc(len); 253 q = name; 254 while (--namelen >= 0) 255 *d++ = *q++; 256 *d++ = '='; 257 *d = '\0'; 258 if (val) 259 scopy(val, d); 260 setvareq(nameeq, flags); 261} 262 263 264 265/* 266 * Same as setvar except that the variable and value are passed in 267 * the first argument as name=value. Since the first argument will 268 * be actually stored in the table, it should not be a string that 269 * will go away. 270 */ 271 272void 273setvareq(char *s, int flags) 274{ 275 struct var *vp, **vpp; 276 int nlen; 277 278 if (aflag) 279 flags |= VEXPORT; 280 vp = find_var(s, &vpp, &nlen); 281 if (vp != NULL) { 282 if (vp->flags & VREADONLY) 283 error("%.*s: is read only", vp->name_len, s); 284 if (flags & VNOSET) 285 return; 286 INTOFF; 287 288 if (vp->func && (flags & VNOFUNC) == 0) 289 (*vp->func)(s + vp->name_len + 1); 290 291 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 292 ckfree(vp->text); 293 294 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 295 vp->flags |= flags & ~VNOFUNC; 296 vp->text = s; 297 298 INTON; 299 return; 300 } 301 /* not found */ 302 if (flags & VNOSET) 303 return; 304 vp = ckmalloc(sizeof (*vp)); 305 vp->flags = flags & ~VNOFUNC; 306 vp->text = s; 307 vp->name_len = nlen; 308 vp->next = *vpp; 309 vp->func = NULL; 310 *vpp = vp; 311} 312 313 314 315/* 316 * Process a linked list of variable assignments. 317 */ 318 319void 320listsetvar(struct strlist *list, int flags) 321{ 322 struct strlist *lp; 323 324 INTOFF; 325 for (lp = list ; lp ; lp = lp->next) { 326 setvareq(savestr(lp->text), flags); 327 } 328 INTON; 329} 330 331void 332listmklocal(struct strlist *list, int flags) 333{ 334 struct strlist *lp; 335 336 for (lp = list ; lp ; lp = lp->next) 337 mklocal(lp->text, flags); 338} 339 340 341/* 342 * Find the value of a variable. Returns NULL if not set. 343 */ 344 345char * 346lookupvar(const char *name) 347{ 348 struct var *v; 349 350 v = find_var(name, NULL, NULL); 351 if (v == NULL || v->flags & VUNSET) 352 return NULL; 353 return v->text + v->name_len + 1; 354} 355 356 357 358/* 359 * Search the environment of a builtin command. If the second argument 360 * is nonzero, return the value of a variable even if it hasn't been 361 * exported. 362 */ 363 364char * 365bltinlookup(const char *name, int doall) 366{ 367 struct strlist *sp; 368 struct var *v; 369 370 for (sp = cmdenviron ; sp ; sp = sp->next) { 371 if (strequal(sp->text, name)) 372 return strchr(sp->text, '=') + 1; 373 } 374 375 v = find_var(name, NULL, NULL); 376 377 if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) 378 return NULL; 379 return v->text + v->name_len + 1; 380} 381 382 383 384/* 385 * Generate a list of exported variables. This routine is used to construct 386 * the third argument to execve when executing a program. 387 */ 388 389char ** 390environment(void) 391{ 392 int nenv; 393 struct var **vpp; 394 struct var *vp; 395 char **env; 396 char **ep; 397 398 nenv = 0; 399 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 400 for (vp = *vpp ; vp ; vp = vp->next) 401 if (vp->flags & VEXPORT) 402 nenv++; 403 } 404 ep = env = stalloc((nenv + 1) * sizeof *env); 405 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 406 for (vp = *vpp ; vp ; vp = vp->next) 407 if (vp->flags & VEXPORT) 408 *ep++ = vp->text; 409 } 410 *ep = NULL; 411 return env; 412} 413 414 415/* 416 * Called when a shell procedure is invoked to clear out nonexported 417 * variables. It is also necessary to reallocate variables of with 418 * VSTACK set since these are currently allocated on the stack. 419 */ 420 421#ifdef mkinit 422void shprocvar(void); 423 424SHELLPROC { 425 shprocvar(); 426} 427#endif 428 429void 430shprocvar(void) 431{ 432 struct var **vpp; 433 struct var *vp, **prev; 434 435 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 436 for (prev = vpp ; (vp = *prev) != NULL ; ) { 437 if ((vp->flags & VEXPORT) == 0) { 438 *prev = vp->next; 439 if ((vp->flags & VTEXTFIXED) == 0) 440 ckfree(vp->text); 441 if ((vp->flags & VSTRFIXED) == 0) 442 ckfree(vp); 443 } else { 444 if (vp->flags & VSTACK) { 445 vp->text = savestr(vp->text); 446 vp->flags &=~ VSTACK; 447 } 448 prev = &vp->next; 449 } 450 } 451 } 452 initvar(); 453} 454 455 456 457/* 458 * Command to list all variables which are set. Currently this command 459 * is invoked from the set command when the set command is called without 460 * any variables. 461 */ 462 463void 464print_quoted(const char *p) 465{ 466 const char *q; 467 468 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 469 out1fmt("%s", p); 470 return; 471 } 472 while (*p) { 473 if (*p == '\'') { 474 out1fmt("\\'"); 475 p++; 476 continue; 477 } 478 q = index(p, '\''); 479 if (!q) { 480 out1fmt("'%s'", p ); 481 return; 482 } 483 out1fmt("'%.*s'", (int)(q - p), p ); 484 p = q; 485 } 486} 487 488static int 489sort_var(const void *v_v1, const void *v_v2) 490{ 491 const struct var * const *v1 = v_v1; 492 const struct var * const *v2 = v_v2; 493 494 /* XXX Will anyone notice we include the '=' of the shorter name? */ 495 return strcmp((*v1)->text, (*v2)->text); 496} 497 498/* 499 * POSIX requires that 'set' (but not export or readonly) output the 500 * variables in lexicographic order - by the locale's collating order (sigh). 501 * Maybe we could keep them in an ordered balanced binary tree 502 * instead of hashed lists. 503 * For now just roll 'em through qsort for printing... 504 */ 505 506int 507showvars(const char *name, int flag, int show_value) 508{ 509 struct var **vpp; 510 struct var *vp; 511 const char *p; 512 513 static struct var **list; /* static in case we are interrupted */ 514 static int list_len; 515 int count = 0; 516 517 if (!list) { 518 list_len = 32; 519 list = ckmalloc(list_len * sizeof *list); 520 } 521 522 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 523 for (vp = *vpp ; vp ; vp = vp->next) { 524 if (flag && !(vp->flags & flag)) 525 continue; 526 if (vp->flags & VUNSET && !(show_value & 2)) 527 continue; 528 if (count >= list_len) { 529 list = ckrealloc(list, 530 (list_len << 1) * sizeof *list); 531 list_len <<= 1; 532 } 533 list[count++] = vp; 534 } 535 } 536 537 qsort(list, count, sizeof *list, sort_var); 538 539 for (vpp = list; count--; vpp++) { 540 vp = *vpp; 541 if (name) 542 out1fmt("%s ", name); 543 for (p = vp->text ; *p != '=' ; p++) 544 out1c(*p); 545 if (!(vp->flags & VUNSET) && show_value) { 546 out1fmt("="); 547 print_quoted(++p); 548 } 549 out1c('\n'); 550 } 551 return 0; 552} 553 554 555 556/* 557 * The export and readonly commands. 558 */ 559 560int 561exportcmd(int argc, char **argv) 562{ 563 struct var *vp; 564 char *name; 565 const char *p; 566 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 567 int pflag; 568 569 pflag = nextopt("p") == 'p' ? 3 : 0; 570 if (argc <= 1 || pflag) { 571 showvars( pflag ? argv[0] : 0, flag, pflag ); 572 return 0; 573 } 574 575 while ((name = *argptr++) != NULL) { 576 if ((p = strchr(name, '=')) != NULL) { 577 p++; 578 } else { 579 vp = find_var(name, NULL, NULL); 580 if (vp != NULL) { 581 vp->flags |= flag; 582 continue; 583 } 584 } 585 setvar(name, p, flag); 586 } 587 return 0; 588} 589 590 591/* 592 * The "local" command. 593 */ 594 595int 596localcmd(int argc, char **argv) 597{ 598 char *name; 599 600 if (! in_function()) 601 error("Not in a function"); 602 while ((name = *argptr++) != NULL) { 603 mklocal(name, 0); 604 } 605 return 0; 606} 607 608 609/* 610 * Make a variable a local variable. When a variable is made local, it's 611 * value and flags are saved in a localvar structure. The saved values 612 * will be restored when the shell function returns. We handle the name 613 * "-" as a special case. 614 */ 615 616void 617mklocal(const char *name, int flags) 618{ 619 struct localvar *lvp; 620 struct var **vpp; 621 struct var *vp; 622 623 INTOFF; 624 lvp = ckmalloc(sizeof (struct localvar)); 625 if (name[0] == '-' && name[1] == '\0') { 626 char *p; 627 p = ckmalloc(sizeof_optlist); 628 lvp->text = memcpy(p, optlist, sizeof_optlist); 629 vp = NULL; 630 } else { 631 vp = find_var(name, &vpp, NULL); 632 if (vp == NULL) { 633 if (strchr(name, '=')) 634 setvareq(savestr(name), VSTRFIXED|flags); 635 else 636 setvar(name, NULL, VSTRFIXED|flags); 637 vp = *vpp; /* the new variable */ 638 lvp->text = NULL; 639 lvp->flags = VUNSET; 640 } else { 641 lvp->text = vp->text; 642 lvp->flags = vp->flags; 643 vp->flags |= VSTRFIXED|VTEXTFIXED; 644 if (name[vp->name_len] == '=') 645 setvareq(savestr(name), flags); 646 } 647 } 648 lvp->vp = vp; 649 lvp->next = localvars; 650 localvars = lvp; 651 INTON; 652} 653 654 655/* 656 * Called after a function returns. 657 */ 658 659void 660poplocalvars(void) 661{ 662 struct localvar *lvp; 663 struct var *vp; 664 665 while ((lvp = localvars) != NULL) { 666 localvars = lvp->next; 667 vp = lvp->vp; 668 TRACE(("poplocalvar %s", vp ? vp->text : "-")); 669 if (vp == NULL) { /* $- saved */ 670 memcpy(optlist, lvp->text, sizeof_optlist); 671 ckfree(lvp->text); 672 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 673 (void)unsetvar(vp->text, 0); 674 } else { 675 if (vp->func && (vp->flags & VNOFUNC) == 0) 676 (*vp->func)(lvp->text + vp->name_len + 1); 677 if ((vp->flags & VTEXTFIXED) == 0) 678 ckfree(vp->text); 679 vp->flags = lvp->flags; 680 vp->text = lvp->text; 681 } 682 ckfree(lvp); 683 } 684} 685 686 687int 688setvarcmd(int argc, char **argv) 689{ 690 if (argc <= 2) 691 return unsetcmd(argc, argv); 692 else if (argc == 3) 693 setvar(argv[1], argv[2], 0); 694 else 695 error("List assignment not implemented"); 696 return 0; 697} 698 699 700/* 701 * The unset builtin command. We unset the function before we unset the 702 * variable to allow a function to be unset when there is a readonly variable 703 * with the same name. 704 */ 705 706int 707unsetcmd(int argc, char **argv) 708{ 709 char **ap; 710 int i; 711 int flg_func = 0; 712 int flg_var = 0; 713 int ret = 0; 714 715 while ((i = nextopt("evf")) != '\0') { 716 if (i == 'f') 717 flg_func = 1; 718 else 719 flg_var = i; 720 } 721 if (flg_func == 0 && flg_var == 0) 722 flg_var = 1; 723 724 for (ap = argptr; *ap ; ap++) { 725 if (flg_func) 726 ret |= unsetfunc(*ap); 727 if (flg_var) 728 ret |= unsetvar(*ap, flg_var == 'e'); 729 } 730 return ret; 731} 732 733 734/* 735 * Unset the specified variable. 736 */ 737 738int 739unsetvar(const char *s, int unexport) 740{ 741 struct var **vpp; 742 struct var *vp; 743 744 vp = find_var(s, &vpp, NULL); 745 if (vp == NULL) 746 return 1; 747 748 if (vp->flags & VREADONLY) 749 return (1); 750 751 INTOFF; 752 if (unexport) { 753 vp->flags &= ~VEXPORT; 754 } else { 755 if (vp->text[vp->name_len + 1] != '\0') 756 setvar(s, nullstr, 0); 757 vp->flags &= ~VEXPORT; 758 vp->flags |= VUNSET; 759 if ((vp->flags & VSTRFIXED) == 0) { 760 if ((vp->flags & VTEXTFIXED) == 0) 761 ckfree(vp->text); 762 *vpp = vp->next; 763 ckfree(vp); 764 } 765 } 766 INTON; 767 return 0; 768} 769 770 771/* 772 * Returns true if the two strings specify the same varable. The first 773 * variable name is terminated by '='; the second may be terminated by 774 * either '=' or '\0'. 775 */ 776 777STATIC int 778strequal(const char *p, const char *q) 779{ 780 while (*p == *q++) { 781 if (*p++ == '=') 782 return 1; 783 } 784 if (*p == '=' && *(q - 1) == '\0') 785 return 1; 786 return 0; 787} 788 789/* 790 * Search for a variable. 791 * 'name' may be terminated by '=' or a NUL. 792 * vppp is set to the pointer to vp, or the list head if vp isn't found 793 * lenp is set to the number of charactets in 'name' 794 */ 795 796STATIC struct var * 797find_var(const char *name, struct var ***vppp, int *lenp) 798{ 799 unsigned int hashval; 800 int len; 801 struct var *vp, **vpp; 802 const char *p = name; 803 804 hashval = 0; 805 while (*p && *p != '=') 806 hashval = 2 * hashval + (unsigned char)*p++; 807 len = p - name; 808 809 if (lenp) 810 *lenp = len; 811 vpp = &vartab[hashval % VTABSIZE]; 812 if (vppp) 813 *vppp = vpp; 814 815 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 816 if (vp->name_len != len) 817 continue; 818 if (memcmp(vp->text, name, len) != 0) 819 continue; 820 if (vppp) 821 *vppp = vpp; 822 return vp; 823 } 824 return NULL; 825} 826