var.c revision 216870
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Kenneth Almquist. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 4. Neither the name of the University nor the names of its contributors 171590Srgrimes * may be used to endorse or promote products derived from this software 181590Srgrimes * without specific prior written permission. 191590Srgrimes * 201590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301590Srgrimes * SUCH DAMAGE. 311590Srgrimes */ 321590Srgrimes 331590Srgrimes#ifndef lint 341590Srgrimes#if 0 351590Srgrimesstatic char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 361590Srgrimes#endif 371590Srgrimes#endif /* not lint */ 381590Srgrimes#include <sys/cdefs.h> 391590Srgrimes__FBSDID("$FreeBSD: head/bin/sh/var.c 216870 2011-01-01 13:26:18Z jilles $"); 401590Srgrimes 411590Srgrimes#include <unistd.h> 421590Srgrimes#include <stdlib.h> 431590Srgrimes#include <paths.h> 441590Srgrimes 451590Srgrimes/* 461590Srgrimes * Shell variables. 4718485Sbde */ 481590Srgrimes 499992Sache#include <locale.h> 509992Sache 5111758Sache#include "shell.h" 521590Srgrimes#include "output.h" 531590Srgrimes#include "expand.h" 541590Srgrimes#include "nodes.h" /* for other headers */ 551590Srgrimes#include "eval.h" /* defines cmdenviron */ 561590Srgrimes#include "exec.h" 571590Srgrimes#include "syntax.h" 581590Srgrimes#include "options.h" 591590Srgrimes#include "mail.h" 601590Srgrimes#include "var.h" 611590Srgrimes#include "memalloc.h" 621590Srgrimes#include "error.h" 631590Srgrimes#include "mystring.h" 641590Srgrimes#include "parser.h" 651590Srgrimes#ifndef NO_HISTORY 668874Srgrimes#include "myhistedit.h" 671590Srgrimes#endif 681590Srgrimes 691590Srgrimes 701590Srgrimes#define VTABSIZE 39 711590Srgrimes 721590Srgrimes 731590Srgrimesstruct varinit { 741590Srgrimes struct var *var; 751590Srgrimes int flags; 761590Srgrimes const char *text; 771590Srgrimes void (*func)(const char *); 781590Srgrimes}; 791590Srgrimes 801590Srgrimes 8118485Sbde#ifndef NO_HISTORY 821590Srgrimesstruct var vhistsize; 831590Srgrimesstruct var vterm; 841590Srgrimes#endif 851590Srgrimesstruct var vifs; 861590Srgrimesstruct var vmail; 871590Srgrimesstruct var vmpath; 881590Srgrimesstruct var vpath; 8911758Sachestruct var vppid; 9011758Sachestruct var vps1; 911590Srgrimesstruct var vps2; 921590Srgrimesstruct var vps4; 931590Srgrimesstruct var vvers; 941590Srgrimesstatic struct var voptind; 951590Srgrimes 961590Srgrimesstatic const struct varinit varinit[] = { 971590Srgrimes#ifndef NO_HISTORY 981590Srgrimes { &vhistsize, VUNSET, "HISTSIZE=", 991590Srgrimes sethistsize }, 1001590Srgrimes#endif 1011590Srgrimes { &vifs, 0, "IFS= \t\n", 1021590Srgrimes NULL }, 1031590Srgrimes { &vmail, VUNSET, "MAIL=", 1041590Srgrimes NULL }, 1051590Srgrimes { &vmpath, VUNSET, "MAILPATH=", 1061590Srgrimes NULL }, 1071590Srgrimes { &vpath, 0, "PATH=" _PATH_DEFPATH, 1081590Srgrimes changepath }, 1091590Srgrimes { &vppid, VUNSET, "PPID=", 1101590Srgrimes NULL }, 1111590Srgrimes /* 1121590Srgrimes * vps1 depends on uid 1131590Srgrimes */ 1141590Srgrimes { &vps2, 0, "PS2=> ", 1151590Srgrimes NULL }, 1161590Srgrimes { &vps4, 0, "PS4=+ ", 1171590Srgrimes NULL }, 1181590Srgrimes#ifndef NO_HISTORY 1191590Srgrimes { &vterm, VUNSET, "TERM=", 1201590Srgrimes setterm }, 1211590Srgrimes#endif 1221590Srgrimes { &voptind, 0, "OPTIND=1", 1231590Srgrimes getoptsreset }, 1241590Srgrimes { NULL, 0, NULL, 1251590Srgrimes NULL } 1261590Srgrimes}; 1271590Srgrimes 1281590Srgrimesstatic struct var *vartab[VTABSIZE]; 1291590Srgrimes 1301590Srgrimesstatic const char *const locale_names[7] = { 1311590Srgrimes "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", 1321590Srgrimes "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL 1331590Srgrimes}; 1341590Srgrimesstatic const int locale_categories[7] = { 1351590Srgrimes LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0 1361590Srgrimes}; 1371590Srgrimes 1381590Srgrimesstatic struct var **hashvar(const char *); 1391590Srgrimesstatic int varequal(const char *, const char *); 1401590Srgrimesstatic int localevar(const char *); 1411590Srgrimes 1421590Srgrimes/* 1435239Sats * Initialize the variable symbol tables and import the environment. 1445239Sats */ 1451590Srgrimes 1461590Srgrimes#ifdef mkinit 1471590SrgrimesINCLUDE "var.h" 1481590SrgrimesMKINIT char **environ; 1491590SrgrimesINIT { 1501590Srgrimes char **envp; 1519992Sache 1529992Sache initvar(); 1535239Sats for (envp = environ ; *envp ; envp++) { 1541590Srgrimes if (strchr(*envp, '=')) { 1551590Srgrimes setvareq(*envp, VEXPORT|VTEXTFIXED); 1561590Srgrimes } 1571590Srgrimes } 1589992Sache} 1591590Srgrimes#endif 1601590Srgrimes 1611590Srgrimes 1621590Srgrimes/* 1631590Srgrimes * This routine initializes the builtin variables. It is called when the 1641590Srgrimes * shell is initialized and again when a shell procedure is spawned. 1651590Srgrimes */ 1661590Srgrimes 1671590Srgrimesvoid 1681590Srgrimesinitvar(void) 1691590Srgrimes{ 1701590Srgrimes char ppid[20]; 1711590Srgrimes const struct varinit *ip; 1721590Srgrimes struct var *vp; 1731590Srgrimes struct var **vpp; 1741590Srgrimes 1751590Srgrimes for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 1761590Srgrimes if ((vp->flags & VEXPORT) == 0) { 1771590Srgrimes vpp = hashvar(ip->text); 1781590Srgrimes vp->next = *vpp; 1791590Srgrimes *vpp = vp; 1801590Srgrimes vp->text = __DECONST(char *, ip->text); 1811590Srgrimes vp->flags = ip->flags | VSTRFIXED | VTEXTFIXED; 1821590Srgrimes vp->func = ip->func; 1831590Srgrimes } 1841590Srgrimes } 1851590Srgrimes /* 1861590Srgrimes * PS1 depends on uid 1871590Srgrimes */ 1881590Srgrimes if ((vps1.flags & VEXPORT) == 0) { 1891590Srgrimes vpp = hashvar("PS1="); 1901590Srgrimes vps1.next = *vpp; 191 *vpp = &vps1; 192 vps1.text = __DECONST(char *, geteuid() ? "PS1=$ " : "PS1=# "); 193 vps1.flags = VSTRFIXED|VTEXTFIXED; 194 } 195 if ((vppid.flags & VEXPORT) == 0) { 196 fmtstr(ppid, sizeof(ppid), "%d", (int)getppid()); 197 setvarsafe("PPID", ppid, 0); 198 } 199} 200 201/* 202 * Safe version of setvar, returns 1 on success 0 on failure. 203 */ 204 205int 206setvarsafe(const char *name, const char *val, int flags) 207{ 208 struct jmploc jmploc; 209 struct jmploc *const savehandler = handler; 210 int err = 0; 211 int inton; 212 213 inton = is_int_on(); 214 if (setjmp(jmploc.loc)) 215 err = 1; 216 else { 217 handler = &jmploc; 218 setvar(name, val, flags); 219 } 220 handler = savehandler; 221 SETINTON(inton); 222 return err; 223} 224 225/* 226 * Set the value of a variable. The flags argument is stored with the 227 * flags of the variable. If val is NULL, the variable is unset. 228 */ 229 230void 231setvar(const char *name, const char *val, int flags) 232{ 233 const char *p; 234 int len; 235 int namelen; 236 char *nameeq; 237 int isbad; 238 239 isbad = 0; 240 p = name; 241 if (! is_name(*p)) 242 isbad = 1; 243 p++; 244 for (;;) { 245 if (! is_in_name(*p)) { 246 if (*p == '\0' || *p == '=') 247 break; 248 isbad = 1; 249 } 250 p++; 251 } 252 namelen = p - name; 253 if (isbad) 254 error("%.*s: bad variable name", namelen, name); 255 len = namelen + 2; /* 2 is space for '=' and '\0' */ 256 if (val == NULL) { 257 flags |= VUNSET; 258 } else { 259 len += strlen(val); 260 } 261 nameeq = ckmalloc(len); 262 memcpy(nameeq, name, namelen); 263 nameeq[namelen] = '='; 264 if (val) 265 scopy(val, nameeq + namelen + 1); 266 else 267 nameeq[namelen + 1] = '\0'; 268 setvareq(nameeq, flags); 269} 270 271static int 272localevar(const char *s) 273{ 274 const char *const *ss; 275 276 if (*s != 'L') 277 return 0; 278 if (varequal(s + 1, "ANG")) 279 return 1; 280 if (strncmp(s + 1, "C_", 2) != 0) 281 return 0; 282 if (varequal(s + 3, "ALL")) 283 return 1; 284 for (ss = locale_names; *ss ; ss++) 285 if (varequal(s + 3, *ss + 3)) 286 return 1; 287 return 0; 288} 289 290 291/* 292 * Sets/unsets an environment variable from a pointer that may actually be a 293 * pointer into environ where the string should not be manipulated. 294 */ 295static void 296change_env(const char *s, int set) 297{ 298 char *eqp; 299 char *ss; 300 301 ss = savestr(s); 302 if ((eqp = strchr(ss, '=')) != NULL) 303 *eqp = '\0'; 304 if (set && eqp != NULL) 305 (void) setenv(ss, eqp + 1, 1); 306 else 307 (void) unsetenv(ss); 308 ckfree(ss); 309 310 return; 311} 312 313 314/* 315 * Same as setvar except that the variable and value are passed in 316 * the first argument as name=value. Since the first argument will 317 * be actually stored in the table, it should not be a string that 318 * will go away. 319 */ 320 321void 322setvareq(char *s, int flags) 323{ 324 struct var *vp, **vpp; 325 int len; 326 327 if (aflag) 328 flags |= VEXPORT; 329 vpp = hashvar(s); 330 for (vp = *vpp ; vp ; vp = vp->next) { 331 if (varequal(s, vp->text)) { 332 if (vp->flags & VREADONLY) { 333 len = strchr(s, '=') - s; 334 error("%.*s: is read only", len, s); 335 } 336 if (flags & VNOSET) 337 return; 338 INTOFF; 339 340 if (vp->func && (flags & VNOFUNC) == 0) 341 (*vp->func)(strchr(s, '=') + 1); 342 343 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 344 ckfree(vp->text); 345 346 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 347 vp->flags |= flags; 348 vp->text = s; 349 350 /* 351 * We could roll this to a function, to handle it as 352 * a regular variable function callback, but why bother? 353 * 354 * Note: this assumes iflag is not set to 1 initially. 355 * As part of init(), this is called before arguments 356 * are looked at. 357 */ 358 if ((vp == &vmpath || (vp == &vmail && ! mpathset())) && 359 iflag == 1) 360 chkmail(1); 361 if ((vp->flags & VEXPORT) && localevar(s)) { 362 change_env(s, 1); 363 (void) setlocale(LC_ALL, ""); 364 } 365 INTON; 366 return; 367 } 368 } 369 /* not found */ 370 if (flags & VNOSET) 371 return; 372 vp = ckmalloc(sizeof (*vp)); 373 vp->flags = flags; 374 vp->text = s; 375 vp->next = *vpp; 376 vp->func = NULL; 377 INTOFF; 378 *vpp = vp; 379 if ((vp->flags & VEXPORT) && localevar(s)) { 380 change_env(s, 1); 381 (void) setlocale(LC_ALL, ""); 382 } 383 INTON; 384} 385 386 387 388/* 389 * Process a linked list of variable assignments. 390 */ 391 392void 393listsetvar(struct strlist *list, int flags) 394{ 395 struct strlist *lp; 396 397 INTOFF; 398 for (lp = list ; lp ; lp = lp->next) { 399 setvareq(savestr(lp->text), flags); 400 } 401 INTON; 402} 403 404 405 406/* 407 * Find the value of a variable. Returns NULL if not set. 408 */ 409 410char * 411lookupvar(const char *name) 412{ 413 struct var *v; 414 415 for (v = *hashvar(name) ; v ; v = v->next) { 416 if (varequal(v->text, name)) { 417 if (v->flags & VUNSET) 418 return NULL; 419 return strchr(v->text, '=') + 1; 420 } 421 } 422 return NULL; 423} 424 425 426 427/* 428 * Search the environment of a builtin command. If the second argument 429 * is nonzero, return the value of a variable even if it hasn't been 430 * exported. 431 */ 432 433char * 434bltinlookup(const char *name, int doall) 435{ 436 struct strlist *sp; 437 struct var *v; 438 char *result; 439 440 result = NULL; 441 for (sp = cmdenviron ; sp ; sp = sp->next) { 442 if (varequal(sp->text, name)) 443 result = strchr(sp->text, '=') + 1; 444 } 445 if (result != NULL) 446 return result; 447 for (v = *hashvar(name) ; v ; v = v->next) { 448 if (varequal(v->text, name)) { 449 if ((v->flags & VUNSET) 450 || (!doall && (v->flags & VEXPORT) == 0)) 451 return NULL; 452 return strchr(v->text, '=') + 1; 453 } 454 } 455 return NULL; 456} 457 458 459/* 460 * Set up locale for a builtin (LANG/LC_* assignments). 461 */ 462void 463bltinsetlocale(void) 464{ 465 struct strlist *lp; 466 int act = 0; 467 char *loc, *locdef; 468 int i; 469 470 for (lp = cmdenviron ; lp ; lp = lp->next) { 471 if (localevar(lp->text)) { 472 act = 1; 473 break; 474 } 475 } 476 if (!act) 477 return; 478 loc = bltinlookup("LC_ALL", 0); 479 INTOFF; 480 if (loc != NULL) { 481 setlocale(LC_ALL, loc); 482 INTON; 483 return; 484 } 485 locdef = bltinlookup("LANG", 0); 486 for (i = 0; locale_names[i] != NULL; i++) { 487 loc = bltinlookup(locale_names[i], 0); 488 if (loc == NULL) 489 loc = locdef; 490 if (loc != NULL) 491 setlocale(locale_categories[i], loc); 492 } 493 INTON; 494} 495 496/* 497 * Undo the effect of bltinlocaleset(). 498 */ 499void 500bltinunsetlocale(void) 501{ 502 struct strlist *lp; 503 504 INTOFF; 505 for (lp = cmdenviron ; lp ; lp = lp->next) { 506 if (localevar(lp->text)) { 507 setlocale(LC_ALL, ""); 508 return; 509 } 510 } 511 INTON; 512} 513 514 515/* 516 * Generate a list of exported variables. This routine is used to construct 517 * the third argument to execve when executing a program. 518 */ 519 520char ** 521environment(void) 522{ 523 int nenv; 524 struct var **vpp; 525 struct var *vp; 526 char **env, **ep; 527 528 nenv = 0; 529 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 530 for (vp = *vpp ; vp ; vp = vp->next) 531 if (vp->flags & VEXPORT) 532 nenv++; 533 } 534 ep = env = stalloc((nenv + 1) * sizeof *env); 535 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 536 for (vp = *vpp ; vp ; vp = vp->next) 537 if (vp->flags & VEXPORT) 538 *ep++ = vp->text; 539 } 540 *ep = NULL; 541 return env; 542} 543 544 545/* 546 * Called when a shell procedure is invoked to clear out nonexported 547 * variables. It is also necessary to reallocate variables of with 548 * VSTACK set since these are currently allocated on the stack. 549 */ 550 551MKINIT void shprocvar(void); 552 553#ifdef mkinit 554SHELLPROC { 555 shprocvar(); 556} 557#endif 558 559void 560shprocvar(void) 561{ 562 struct var **vpp; 563 struct var *vp, **prev; 564 565 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 566 for (prev = vpp ; (vp = *prev) != NULL ; ) { 567 if ((vp->flags & VEXPORT) == 0) { 568 *prev = vp->next; 569 if ((vp->flags & VTEXTFIXED) == 0) 570 ckfree(vp->text); 571 if ((vp->flags & VSTRFIXED) == 0) 572 ckfree(vp); 573 } else { 574 if (vp->flags & VSTACK) { 575 vp->text = savestr(vp->text); 576 vp->flags &=~ VSTACK; 577 } 578 prev = &vp->next; 579 } 580 } 581 } 582 initvar(); 583} 584 585 586static int 587var_compare(const void *a, const void *b) 588{ 589 const char *const *sa, *const *sb; 590 591 sa = a; 592 sb = b; 593 /* 594 * This compares two var=value strings which creates a different 595 * order from what you would probably expect. POSIX is somewhat 596 * ambiguous on what should be sorted exactly. 597 */ 598 return strcoll(*sa, *sb); 599} 600 601 602/* 603 * Command to list all variables which are set. Currently this command 604 * is invoked from the set command when the set command is called without 605 * any variables. 606 */ 607 608int 609showvarscmd(int argc __unused, char **argv __unused) 610{ 611 struct var **vpp; 612 struct var *vp; 613 const char *s; 614 const char **vars; 615 int i, n; 616 617 /* 618 * POSIX requires us to sort the variables. 619 */ 620 n = 0; 621 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { 622 for (vp = *vpp; vp; vp = vp->next) { 623 if (!(vp->flags & VUNSET)) 624 n++; 625 } 626 } 627 628 INTON; 629 vars = ckmalloc(n * sizeof(*vars)); 630 i = 0; 631 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { 632 for (vp = *vpp; vp; vp = vp->next) { 633 if (!(vp->flags & VUNSET)) 634 vars[i++] = vp->text; 635 } 636 } 637 638 qsort(vars, n, sizeof(*vars), var_compare); 639 for (i = 0; i < n; i++) { 640 s = strchr(vars[i], '='); 641 s++; 642 outbin(vars[i], s - vars[i], out1); 643 out1qstr(s); 644 out1c('\n'); 645 } 646 ckfree(vars); 647 INTOFF; 648 649 return 0; 650} 651 652 653 654/* 655 * The export and readonly commands. 656 */ 657 658int 659exportcmd(int argc, char **argv) 660{ 661 struct var **vpp; 662 struct var *vp; 663 char *name; 664 char *p; 665 char *cmdname; 666 int ch, values; 667 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 668 669 cmdname = argv[0]; 670 optreset = optind = 1; 671 opterr = 0; 672 values = 0; 673 while ((ch = getopt(argc, argv, "p")) != -1) { 674 switch (ch) { 675 case 'p': 676 values = 1; 677 break; 678 case '?': 679 default: 680 error("unknown option: -%c", optopt); 681 } 682 } 683 argc -= optind; 684 argv += optind; 685 686 if (values && argc != 0) 687 error("-p requires no arguments"); 688 if (argc != 0) { 689 while ((name = *argv++) != NULL) { 690 if ((p = strchr(name, '=')) != NULL) { 691 p++; 692 } else { 693 vpp = hashvar(name); 694 for (vp = *vpp ; vp ; vp = vp->next) { 695 if (varequal(vp->text, name)) { 696 697 vp->flags |= flag; 698 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 699 change_env(vp->text, 1); 700 (void) setlocale(LC_ALL, ""); 701 } 702 goto found; 703 } 704 } 705 } 706 setvar(name, p, flag); 707found:; 708 } 709 } else { 710 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 711 for (vp = *vpp ; vp ; vp = vp->next) { 712 if (vp->flags & flag) { 713 if (values) { 714 out1str(cmdname); 715 out1c(' '); 716 } 717 p = strchr(vp->text, '='); 718 if (values && !(vp->flags & VUNSET)) { 719 p++; 720 outbin(vp->text, p - vp->text, 721 out1); 722 out1qstr(p); 723 } else 724 outbin(vp->text, p - vp->text, 725 out1); 726 out1c('\n'); 727 } 728 } 729 } 730 } 731 return 0; 732} 733 734 735/* 736 * The "local" command. 737 */ 738 739int 740localcmd(int argc __unused, char **argv __unused) 741{ 742 char *name; 743 744 if (! in_function()) 745 error("Not in a function"); 746 while ((name = *argptr++) != NULL) { 747 mklocal(name); 748 } 749 return 0; 750} 751 752 753/* 754 * Make a variable a local variable. When a variable is made local, it's 755 * value and flags are saved in a localvar structure. The saved values 756 * will be restored when the shell function returns. We handle the name 757 * "-" as a special case. 758 */ 759 760void 761mklocal(char *name) 762{ 763 struct localvar *lvp; 764 struct var **vpp; 765 struct var *vp; 766 767 INTOFF; 768 lvp = ckmalloc(sizeof (struct localvar)); 769 if (name[0] == '-' && name[1] == '\0') { 770 lvp->text = ckmalloc(sizeof optlist); 771 memcpy(lvp->text, optlist, sizeof optlist); 772 vp = NULL; 773 } else { 774 vpp = hashvar(name); 775 for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); 776 if (vp == NULL) { 777 if (strchr(name, '=')) 778 setvareq(savestr(name), VSTRFIXED); 779 else 780 setvar(name, NULL, VSTRFIXED); 781 vp = *vpp; /* the new variable */ 782 lvp->text = NULL; 783 lvp->flags = VUNSET; 784 } else { 785 lvp->text = vp->text; 786 lvp->flags = vp->flags; 787 vp->flags |= VSTRFIXED|VTEXTFIXED; 788 if (strchr(name, '=')) 789 setvareq(savestr(name), 0); 790 } 791 } 792 lvp->vp = vp; 793 lvp->next = localvars; 794 localvars = lvp; 795 INTON; 796} 797 798 799/* 800 * Called after a function returns. 801 */ 802 803void 804poplocalvars(void) 805{ 806 struct localvar *lvp; 807 struct var *vp; 808 809 while ((lvp = localvars) != NULL) { 810 localvars = lvp->next; 811 vp = lvp->vp; 812 if (vp == NULL) { /* $- saved */ 813 memcpy(optlist, lvp->text, sizeof optlist); 814 ckfree(lvp->text); 815 optschanged(); 816 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 817 (void)unsetvar(vp->text); 818 } else { 819 if ((vp->flags & VTEXTFIXED) == 0) 820 ckfree(vp->text); 821 vp->flags = lvp->flags; 822 vp->text = lvp->text; 823 } 824 ckfree(lvp); 825 } 826} 827 828 829int 830setvarcmd(int argc, char **argv) 831{ 832 if (argc <= 2) 833 return unsetcmd(argc, argv); 834 else if (argc == 3) 835 setvar(argv[1], argv[2], 0); 836 else 837 error("too many arguments"); 838 return 0; 839} 840 841 842/* 843 * The unset builtin command. We unset the function before we unset the 844 * variable to allow a function to be unset when there is a readonly variable 845 * with the same name. 846 */ 847 848int 849unsetcmd(int argc __unused, char **argv __unused) 850{ 851 char **ap; 852 int i; 853 int flg_func = 0; 854 int flg_var = 0; 855 int ret = 0; 856 857 while ((i = nextopt("vf")) != '\0') { 858 if (i == 'f') 859 flg_func = 1; 860 else 861 flg_var = 1; 862 } 863 if (flg_func == 0 && flg_var == 0) 864 flg_var = 1; 865 866 for (ap = argptr; *ap ; ap++) { 867 if (flg_func) 868 ret |= unsetfunc(*ap); 869 if (flg_var) 870 ret |= unsetvar(*ap); 871 } 872 return ret; 873} 874 875 876/* 877 * Unset the specified variable. 878 */ 879 880int 881unsetvar(const char *s) 882{ 883 struct var **vpp; 884 struct var *vp; 885 886 vpp = hashvar(s); 887 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 888 if (varequal(vp->text, s)) { 889 if (vp->flags & VREADONLY) 890 return (1); 891 INTOFF; 892 if (*(strchr(vp->text, '=') + 1) != '\0') 893 setvar(s, nullstr, 0); 894 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 895 change_env(s, 0); 896 setlocale(LC_ALL, ""); 897 } 898 vp->flags &= ~VEXPORT; 899 vp->flags |= VUNSET; 900 if ((vp->flags & VSTRFIXED) == 0) { 901 if ((vp->flags & VTEXTFIXED) == 0) 902 ckfree(vp->text); 903 *vpp = vp->next; 904 ckfree(vp); 905 } 906 INTON; 907 return (0); 908 } 909 } 910 911 return (0); 912} 913 914 915 916/* 917 * Find the appropriate entry in the hash table from the name. 918 */ 919 920static struct var ** 921hashvar(const char *p) 922{ 923 unsigned int hashval; 924 925 hashval = ((unsigned char) *p) << 4; 926 while (*p && *p != '=') 927 hashval += (unsigned char) *p++; 928 return &vartab[hashval % VTABSIZE]; 929} 930 931 932 933/* 934 * Returns true if the two strings specify the same varable. The first 935 * variable name is terminated by '='; the second may be terminated by 936 * either '=' or '\0'. 937 */ 938 939static int 940varequal(const char *p, const char *q) 941{ 942 while (*p == *q++) { 943 if (*p++ == '=') 944 return 1; 945 } 946 if (*p == '=' && *(q - 1) == '\0') 947 return 1; 948 return 0; 949} 950