var.c revision 231001
12490Sjkh/*- 22490Sjkh * Copyright (c) 1991, 1993 32490Sjkh * The Regents of the University of California. All rights reserved. 42490Sjkh * 52490Sjkh * This code is derived from software contributed to Berkeley by 62490Sjkh * Kenneth Almquist. 72490Sjkh * 82490Sjkh * Redistribution and use in source and binary forms, with or without 92490Sjkh * modification, are permitted provided that the following conditions 102490Sjkh * are met: 112490Sjkh * 1. Redistributions of source code must retain the above copyright 122490Sjkh * notice, this list of conditions and the following disclaimer. 132490Sjkh * 2. Redistributions in binary form must reproduce the above copyright 142490Sjkh * notice, this list of conditions and the following disclaimer in the 152490Sjkh * documentation and/or other materials provided with the distribution. 162490Sjkh * 4. Neither the name of the University nor the names of its contributors 172490Sjkh * may be used to endorse or promote products derived from this software 182490Sjkh * without specific prior written permission. 192490Sjkh * 202490Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 212490Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 222490Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 232490Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 242490Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 252490Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 262490Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 272490Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 282490Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 292490Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 302490Sjkh * SUCH DAMAGE. 312490Sjkh */ 322490Sjkh 332490Sjkh#ifndef lint 3410352Sjoerg#if 0 3510352Sjoergstatic char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 3610352Sjoerg#endif 3710352Sjoerg#endif /* not lint */ 3810352Sjoerg#include <sys/cdefs.h> 392490Sjkh__FBSDID("$FreeBSD: head/bin/sh/var.c 231001 2012-02-04 23:29:07Z jilles $"); 4053920Sbillf 412490Sjkh#include <unistd.h> 422490Sjkh#include <stdlib.h> 432490Sjkh#include <paths.h> 442490Sjkh 452490Sjkh/* 4653920Sbillf * Shell variables. 472490Sjkh */ 4853920Sbillf 4953920Sbillf#include <locale.h> 5053920Sbillf#include <langinfo.h> 512490Sjkh 522490Sjkh#include "shell.h" 532490Sjkh#include "output.h" 542490Sjkh#include "expand.h" 5510352Sjoerg#include "nodes.h" /* for other headers */ 5610352Sjoerg#include "eval.h" /* defines cmdenviron */ 5735857Sjb#include "exec.h" 582490Sjkh#include "syntax.h" 5910352Sjoerg#include "options.h" 6010352Sjoerg#include "mail.h" 6110352Sjoerg#include "var.h" 6210352Sjoerg#include "memalloc.h" 6310352Sjoerg#include "error.h" 6410352Sjoerg#include "mystring.h" 6510352Sjoerg#include "parser.h" 6610352Sjoerg#include "builtins.h" 672490Sjkh#ifndef NO_HISTORY 682490Sjkh#include "myhistedit.h" 6910352Sjoerg#endif 702490Sjkh 7110352Sjoerg 7210352Sjoerg#define VTABSIZE 39 7310352Sjoerg 7410352Sjoerg 7510352Sjoergstruct varinit { 7610352Sjoerg struct var *var; 7710352Sjoerg int flags; 7810352Sjoerg const char *text; 7910352Sjoerg void (*func)(const char *); 8010352Sjoerg}; 8110352Sjoerg 8210352Sjoerg 8310352Sjoerg#ifndef NO_HISTORY 8410352Sjoergstruct var vhistsize; 8510352Sjoergstruct var vterm; 8610352Sjoerg#endif 8710352Sjoergstruct var vifs; 8810352Sjoergstruct var vmail; 8910352Sjoergstruct var vmpath; 9010352Sjoergstruct var vpath; 9110352Sjoergstruct var vppid; 9210352Sjoergstruct var vps1; 9310352Sjoergstruct var vps2; 9410352Sjoergstruct var vps4; 9510352Sjoergstruct var vvers; 9610352Sjoergstatic struct var voptind; 9710352Sjoergstruct var vdisvfork; 9810352Sjoerg 9910352Sjoergint forcelocal; 10010352Sjoerg 10110352Sjoergstatic const struct varinit varinit[] = { 10210352Sjoerg#ifndef NO_HISTORY 10310352Sjoerg { &vhistsize, VUNSET, "HISTSIZE=", 10410352Sjoerg sethistsize }, 10510352Sjoerg#endif 10610352Sjoerg { &vifs, 0, "IFS= \t\n", 10710352Sjoerg NULL }, 10810352Sjoerg { &vmail, VUNSET, "MAIL=", 10910352Sjoerg NULL }, 11010352Sjoerg { &vmpath, VUNSET, "MAILPATH=", 11110352Sjoerg NULL }, 11210352Sjoerg { &vpath, 0, "PATH=" _PATH_DEFPATH, 11310352Sjoerg changepath }, 11410352Sjoerg { &vppid, VUNSET, "PPID=", 11510352Sjoerg NULL }, 11610352Sjoerg /* 11710352Sjoerg * vps1 depends on uid 11810352Sjoerg */ 11910352Sjoerg { &vps2, 0, "PS2=> ", 12010352Sjoerg NULL }, 12110352Sjoerg { &vps4, 0, "PS4=+ ", 12210352Sjoerg NULL }, 12310352Sjoerg#ifndef NO_HISTORY 12410352Sjoerg { &vterm, VUNSET, "TERM=", 12510352Sjoerg setterm }, 12610352Sjoerg#endif 12710352Sjoerg { &voptind, 0, "OPTIND=1", 12810352Sjoerg getoptsreset }, 12910352Sjoerg { &vdisvfork, VUNSET, "SH_DISABLE_VFORK=", 13010352Sjoerg NULL }, 13110352Sjoerg { NULL, 0, NULL, 13210352Sjoerg NULL } 13310352Sjoerg}; 13410352Sjoerg 13510352Sjoergstatic struct var *vartab[VTABSIZE]; 13610352Sjoerg 13710352Sjoergstatic const char *const locale_names[7] = { 13810352Sjoerg "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", 13910352Sjoerg "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL 14010352Sjoerg}; 14110352Sjoergstatic const int locale_categories[7] = { 14210352Sjoerg LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0 14310352Sjoerg}; 14410352Sjoerg 14510352Sjoergstatic int varequal(const char *, const char *); 14610352Sjoergstatic struct var *find_var(const char *, struct var ***, int *); 14710352Sjoergstatic int localevar(const char *); 14810352Sjoerg 14910352Sjoerg/* 15010352Sjoerg * Initialize the variable symbol tables and import the environment. 15110352Sjoerg */ 15210352Sjoerg 15310352Sjoerg#ifdef mkinit 15410352SjoergINCLUDE "var.h" 15510352SjoergMKINIT char **environ; 15610352SjoergINIT { 15710352Sjoerg char **envp; 15810352Sjoerg 15910352Sjoerg initvar(); 16010352Sjoerg for (envp = environ ; *envp ; envp++) { 16110352Sjoerg if (strchr(*envp, '=')) { 16210352Sjoerg setvareq(*envp, VEXPORT|VTEXTFIXED); 16310352Sjoerg } 16410352Sjoerg } 16529018Sache} 16610352Sjoerg#endif 16710352Sjoerg 16810352Sjoerg 16910352Sjoerg/* 17010352Sjoerg * This routine initializes the builtin variables. It is called when the 17110352Sjoerg * shell is initialized. 17210352Sjoerg */ 17310352Sjoerg 17410352Sjoergvoid 17510352Sjoerginitvar(void) 17610352Sjoerg{ 17710352Sjoerg char ppid[20]; 17810352Sjoerg const struct varinit *ip; 17910352Sjoerg struct var *vp; 18010352Sjoerg struct var **vpp; 18110352Sjoerg 18210352Sjoerg for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 18310352Sjoerg if (find_var(ip->text, &vpp, &vp->name_len) != NULL) 18410352Sjoerg continue; 18510352Sjoerg vp->next = *vpp; 18610352Sjoerg *vpp = vp; 18710352Sjoerg vp->text = __DECONST(char *, ip->text); 18810352Sjoerg vp->flags = ip->flags | VSTRFIXED | VTEXTFIXED; 18910352Sjoerg vp->func = ip->func; 19010352Sjoerg } 19110352Sjoerg /* 19210352Sjoerg * PS1 depends on uid 19310352Sjoerg */ 19410352Sjoerg if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { 19510352Sjoerg vps1.next = *vpp; 19610352Sjoerg *vpp = &vps1; 19710352Sjoerg vps1.text = __DECONST(char *, geteuid() ? "PS1=$ " : "PS1=# "); 19810352Sjoerg vps1.flags = VSTRFIXED|VTEXTFIXED; 19910352Sjoerg } 20010352Sjoerg if ((vppid.flags & VEXPORT) == 0) { 20110352Sjoerg fmtstr(ppid, sizeof(ppid), "%d", (int)getppid()); 20210352Sjoerg setvarsafe("PPID", ppid, 0); 20310352Sjoerg } 20410352Sjoerg} 20510352Sjoerg 20610352Sjoerg/* 20710352Sjoerg * Safe version of setvar, returns 1 on success 0 on failure. 20810352Sjoerg */ 20910352Sjoerg 21010352Sjoergint 21110352Sjoergsetvarsafe(const char *name, const char *val, int flags) 21210352Sjoerg{ 21310352Sjoerg struct jmploc jmploc; 21410352Sjoerg struct jmploc *const savehandler = handler; 2152490Sjkh int err = 0; 21610352Sjoerg int inton; 21710352Sjoerg 21853210Sbillf inton = is_int_on(); 21953210Sbillf if (setjmp(jmploc.loc)) 2202490Sjkh err = 1; 22133937Sjkh else { 22210352Sjoerg handler = &jmploc; 22310352Sjoerg setvar(name, val, flags); 22410352Sjoerg } 22510352Sjoerg handler = savehandler; 22610352Sjoerg SETINTON(inton); 22710352Sjoerg return err; 22810352Sjoerg} 2292490Sjkh 2302490Sjkh/* 2312490Sjkh * Set the value of a variable. The flags argument is stored with the 23210352Sjoerg * flags of the variable. If val is NULL, the variable is unset. 23310352Sjoerg */ 23410352Sjoerg 2352490Sjkhvoid 2362490Sjkhsetvar(const char *name, const char *val, int flags) 23710352Sjoerg{ 2382490Sjkh const char *p; 2392490Sjkh int len; 24010352Sjoerg int namelen; 24110352Sjoerg char *nameeq; 24210352Sjoerg int isbad; 24310352Sjoerg 24410352Sjoerg isbad = 0; 24510352Sjoerg p = name; 24610352Sjoerg if (! is_name(*p)) 24710352Sjoerg isbad = 1; 24810352Sjoerg p++; 24910352Sjoerg for (;;) { 25010352Sjoerg if (! is_in_name(*p)) { 25110352Sjoerg if (*p == '\0' || *p == '=') 25210352Sjoerg break; 25310352Sjoerg isbad = 1; 25410352Sjoerg } 25510352Sjoerg p++; 25610352Sjoerg } 25710352Sjoerg namelen = p - name; 25810352Sjoerg if (isbad) 25910352Sjoerg error("%.*s: bad variable name", namelen, name); 26010352Sjoerg len = namelen + 2; /* 2 is space for '=' and '\0' */ 26110352Sjoerg if (val == NULL) { 26210352Sjoerg flags |= VUNSET; 26310352Sjoerg } else { 2642490Sjkh len += strlen(val); 2652490Sjkh } 2662490Sjkh nameeq = ckmalloc(len); 26729018Sache memcpy(nameeq, name, namelen); 26829018Sache nameeq[namelen] = '='; 26929018Sache if (val) 27029018Sache scopy(val, nameeq + namelen + 1); 27129018Sache else 27210352Sjoerg nameeq[namelen + 1] = '\0'; 27310352Sjoerg setvareq(nameeq, flags); 27429018Sache} 27510352Sjoerg 27610352Sjoergstatic int 2772490Sjkhlocalevar(const char *s) 27810352Sjoerg{ 27929018Sache const char *const *ss; 28010352Sjoerg 28129018Sache if (*s != 'L') 2822490Sjkh return 0; 28310352Sjoerg if (varequal(s + 1, "ANG")) 28410352Sjoerg return 1; 28510352Sjoerg if (strncmp(s + 1, "C_", 2) != 0) 28610352Sjoerg return 0; 28710352Sjoerg if (varequal(s + 3, "ALL")) 2882490Sjkh return 1; 2892490Sjkh for (ss = locale_names; *ss ; ss++) 29010352Sjoerg if (varequal(s + 3, *ss + 3)) 29110352Sjoerg return 1; 2922490Sjkh return 0; 29310352Sjoerg} 29410352Sjoerg 29529018Sache 29629018Sache/* 29710352Sjoerg * Sets/unsets an environment variable from a pointer that may actually be a 29810352Sjoerg * pointer into environ where the string should not be manipulated. 29910352Sjoerg */ 30010352Sjoergstatic void 30110352Sjoergchange_env(const char *s, int set) 30210352Sjoerg{ 30310352Sjoerg char *eqp; 30410352Sjoerg char *ss; 30510352Sjoerg 30610352Sjoerg ss = savestr(s); 30710352Sjoerg if ((eqp = strchr(ss, '=')) != NULL) 30810352Sjoerg *eqp = '\0'; 30910352Sjoerg if (set && eqp != NULL) 31010352Sjoerg (void) setenv(ss, eqp + 1, 1); 31110352Sjoerg else 31210352Sjoerg (void) unsetenv(ss); 31310352Sjoerg ckfree(ss); 31410352Sjoerg 31510352Sjoerg return; 31610352Sjoerg} 31710352Sjoerg 3182490Sjkh 3192490Sjkh/* 32010352Sjoerg * Same as setvar except that the variable and value are passed in 32110352Sjoerg * the first argument as name=value. Since the first argument will 3222490Sjkh * be actually stored in the table, it should not be a string that 3232490Sjkh * will go away. 3242490Sjkh */ 32510352Sjoerg 32610352Sjoergvoid 32710352Sjoergsetvareq(char *s, int flags) 32810352Sjoerg{ 3292490Sjkh struct var *vp, **vpp; 33010352Sjoerg int nlen; 33110352Sjoerg 33210352Sjoerg if (aflag) 33310352Sjoerg flags |= VEXPORT; 33410352Sjoerg if (forcelocal && !(flags & (VNOSET | VNOLOCAL))) 33510352Sjoerg mklocal(s); 33610352Sjoerg vp = find_var(s, &vpp, &nlen); 33710352Sjoerg if (vp != NULL) { 33829018Sache if (vp->flags & VREADONLY) 33910352Sjoerg error("%.*s: is read only", vp->name_len, s); 34010352Sjoerg if (flags & VNOSET) 34110352Sjoerg return; 34210352Sjoerg INTOFF; 34310352Sjoerg 34410352Sjoerg if (vp->func && (flags & VNOFUNC) == 0) 34510352Sjoerg (*vp->func)(s + vp->name_len + 1); 34610352Sjoerg 34710352Sjoerg if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 34810352Sjoerg ckfree(vp->text); 34910352Sjoerg 35010352Sjoerg vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 35110352Sjoerg vp->flags |= flags; 35210352Sjoerg vp->text = s; 35310352Sjoerg 35410352Sjoerg /* 35510352Sjoerg * We could roll this to a function, to handle it as 35610352Sjoerg * a regular variable function callback, but why bother? 35710352Sjoerg * 35810352Sjoerg * Note: this assumes iflag is not set to 1 initially. 35910352Sjoerg * As part of init(), this is called before arguments 36010352Sjoerg * are looked at. 36110352Sjoerg */ 36210352Sjoerg if ((vp == &vmpath || (vp == &vmail && ! mpathset())) && 36310352Sjoerg iflag == 1) 36410352Sjoerg chkmail(1); 36510352Sjoerg if ((vp->flags & VEXPORT) && localevar(s)) { 36610352Sjoerg change_env(s, 1); 36710352Sjoerg (void) setlocale(LC_ALL, ""); 36810352Sjoerg updatecharset(); 36910352Sjoerg } 37010352Sjoerg INTON; 37110352Sjoerg return; 372 } 373 /* not found */ 374 if (flags & VNOSET) 375 return; 376 vp = ckmalloc(sizeof (*vp)); 377 vp->flags = flags; 378 vp->text = s; 379 vp->name_len = nlen; 380 vp->next = *vpp; 381 vp->func = NULL; 382 INTOFF; 383 *vpp = vp; 384 if ((vp->flags & VEXPORT) && localevar(s)) { 385 change_env(s, 1); 386 (void) setlocale(LC_ALL, ""); 387 updatecharset(); 388 } 389 INTON; 390} 391 392 393 394/* 395 * Process a linked list of variable assignments. 396 */ 397 398void 399listsetvar(struct strlist *list, int flags) 400{ 401 struct strlist *lp; 402 403 INTOFF; 404 for (lp = list ; lp ; lp = lp->next) { 405 setvareq(savestr(lp->text), flags); 406 } 407 INTON; 408} 409 410 411 412/* 413 * Find the value of a variable. Returns NULL if not set. 414 */ 415 416char * 417lookupvar(const char *name) 418{ 419 struct var *v; 420 421 v = find_var(name, NULL, NULL); 422 if (v == NULL || v->flags & VUNSET) 423 return NULL; 424 return v->text + v->name_len + 1; 425} 426 427 428 429/* 430 * Search the environment of a builtin command. If the second argument 431 * is nonzero, return the value of a variable even if it hasn't been 432 * exported. 433 */ 434 435char * 436bltinlookup(const char *name, int doall) 437{ 438 struct strlist *sp; 439 struct var *v; 440 char *result; 441 442 result = NULL; 443 for (sp = cmdenviron ; sp ; sp = sp->next) { 444 if (varequal(sp->text, name)) 445 result = strchr(sp->text, '=') + 1; 446 } 447 if (result != NULL) 448 return result; 449 450 v = find_var(name, NULL, NULL); 451 if (v == NULL || v->flags & VUNSET || 452 (!doall && (v->flags & VEXPORT) == 0)) 453 return NULL; 454 return v->text + v->name_len + 1; 455} 456 457 458/* 459 * Set up locale for a builtin (LANG/LC_* assignments). 460 */ 461void 462bltinsetlocale(void) 463{ 464 struct strlist *lp; 465 int act = 0; 466 char *loc, *locdef; 467 int i; 468 469 for (lp = cmdenviron ; lp ; lp = lp->next) { 470 if (localevar(lp->text)) { 471 act = 1; 472 break; 473 } 474 } 475 if (!act) 476 return; 477 loc = bltinlookup("LC_ALL", 0); 478 INTOFF; 479 if (loc != NULL) { 480 setlocale(LC_ALL, loc); 481 INTON; 482 updatecharset(); 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 updatecharset(); 495} 496 497/* 498 * Undo the effect of bltinlocaleset(). 499 */ 500void 501bltinunsetlocale(void) 502{ 503 struct strlist *lp; 504 505 INTOFF; 506 for (lp = cmdenviron ; lp ; lp = lp->next) { 507 if (localevar(lp->text)) { 508 setlocale(LC_ALL, ""); 509 updatecharset(); 510 return; 511 } 512 } 513 INTON; 514} 515 516/* 517 * Update the localeisutf8 flag. 518 */ 519void 520updatecharset(void) 521{ 522 char *charset; 523 524 charset = nl_langinfo(CODESET); 525 localeisutf8 = !strcmp(charset, "UTF-8"); 526} 527 528void 529initcharset(void) 530{ 531 updatecharset(); 532 initial_localeisutf8 = localeisutf8; 533} 534 535/* 536 * Generate a list of exported variables. This routine is used to construct 537 * the third argument to execve when executing a program. 538 */ 539 540char ** 541environment(void) 542{ 543 int nenv; 544 struct var **vpp; 545 struct var *vp; 546 char **env, **ep; 547 548 nenv = 0; 549 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 550 for (vp = *vpp ; vp ; vp = vp->next) 551 if (vp->flags & VEXPORT) 552 nenv++; 553 } 554 ep = env = stalloc((nenv + 1) * sizeof *env); 555 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 556 for (vp = *vpp ; vp ; vp = vp->next) 557 if (vp->flags & VEXPORT) 558 *ep++ = vp->text; 559 } 560 *ep = NULL; 561 return env; 562} 563 564 565static int 566var_compare(const void *a, const void *b) 567{ 568 const char *const *sa, *const *sb; 569 570 sa = a; 571 sb = b; 572 /* 573 * This compares two var=value strings which creates a different 574 * order from what you would probably expect. POSIX is somewhat 575 * ambiguous on what should be sorted exactly. 576 */ 577 return strcoll(*sa, *sb); 578} 579 580 581/* 582 * Command to list all variables which are set. This is invoked from the 583 * set command when it is called without any options or operands. 584 */ 585 586int 587showvarscmd(int argc __unused, char **argv __unused) 588{ 589 struct var **vpp; 590 struct var *vp; 591 const char *s; 592 const char **vars; 593 int i, n; 594 595 /* 596 * POSIX requires us to sort the variables. 597 */ 598 n = 0; 599 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { 600 for (vp = *vpp; vp; vp = vp->next) { 601 if (!(vp->flags & VUNSET)) 602 n++; 603 } 604 } 605 606 INTOFF; 607 vars = ckmalloc(n * sizeof(*vars)); 608 i = 0; 609 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { 610 for (vp = *vpp; vp; vp = vp->next) { 611 if (!(vp->flags & VUNSET)) 612 vars[i++] = vp->text; 613 } 614 } 615 616 qsort(vars, n, sizeof(*vars), var_compare); 617 for (i = 0; i < n; i++) { 618 /* 619 * Skip improper variable names so the output remains usable as 620 * shell input. 621 */ 622 if (!isassignment(vars[i])) 623 continue; 624 s = strchr(vars[i], '='); 625 s++; 626 outbin(vars[i], s - vars[i], out1); 627 out1qstr(s); 628 out1c('\n'); 629 } 630 ckfree(vars); 631 INTON; 632 633 return 0; 634} 635 636 637 638/* 639 * The export and readonly commands. 640 */ 641 642int 643exportcmd(int argc, char **argv) 644{ 645 struct var **vpp; 646 struct var *vp; 647 char *name; 648 char *p; 649 char *cmdname; 650 int ch, values; 651 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 652 653 cmdname = argv[0]; 654 optreset = optind = 1; 655 opterr = 0; 656 values = 0; 657 while ((ch = getopt(argc, argv, "p")) != -1) { 658 switch (ch) { 659 case 'p': 660 values = 1; 661 break; 662 case '?': 663 default: 664 error("unknown option: -%c", optopt); 665 } 666 } 667 argc -= optind; 668 argv += optind; 669 670 if (values && argc != 0) 671 error("-p requires no arguments"); 672 if (argc != 0) { 673 while ((name = *argv++) != NULL) { 674 if ((p = strchr(name, '=')) != NULL) { 675 p++; 676 } else { 677 vp = find_var(name, NULL, NULL); 678 if (vp != NULL) { 679 vp->flags |= flag; 680 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 681 change_env(vp->text, 1); 682 (void) setlocale(LC_ALL, ""); 683 updatecharset(); 684 } 685 continue; 686 } 687 } 688 setvar(name, p, flag); 689 } 690 } else { 691 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 692 for (vp = *vpp ; vp ; vp = vp->next) { 693 if (vp->flags & flag) { 694 if (values) { 695 /* 696 * Skip improper variable names 697 * so the output remains usable 698 * as shell input. 699 */ 700 if (!isassignment(vp->text)) 701 continue; 702 out1str(cmdname); 703 out1c(' '); 704 } 705 if (values && !(vp->flags & VUNSET)) { 706 outbin(vp->text, 707 vp->name_len + 1, out1); 708 out1qstr(vp->text + 709 vp->name_len + 1); 710 } else 711 outbin(vp->text, vp->name_len, 712 out1); 713 out1c('\n'); 714 } 715 } 716 } 717 } 718 return 0; 719} 720 721 722/* 723 * The "local" command. 724 */ 725 726int 727localcmd(int argc __unused, char **argv __unused) 728{ 729 char *name; 730 731 if (! in_function()) 732 error("Not in a function"); 733 while ((name = *argptr++) != NULL) { 734 mklocal(name); 735 } 736 return 0; 737} 738 739 740/* 741 * Make a variable a local variable. When a variable is made local, it's 742 * value and flags are saved in a localvar structure. The saved values 743 * will be restored when the shell function returns. We handle the name 744 * "-" as a special case. 745 */ 746 747void 748mklocal(char *name) 749{ 750 struct localvar *lvp; 751 struct var **vpp; 752 struct var *vp; 753 754 INTOFF; 755 lvp = ckmalloc(sizeof (struct localvar)); 756 if (name[0] == '-' && name[1] == '\0') { 757 lvp->text = ckmalloc(sizeof optlist); 758 memcpy(lvp->text, optlist, sizeof optlist); 759 vp = NULL; 760 } else { 761 vp = find_var(name, &vpp, NULL); 762 if (vp == NULL) { 763 if (strchr(name, '=')) 764 setvareq(savestr(name), VSTRFIXED | VNOLOCAL); 765 else 766 setvar(name, NULL, VSTRFIXED | VNOLOCAL); 767 vp = *vpp; /* the new variable */ 768 lvp->text = NULL; 769 lvp->flags = VUNSET; 770 } else { 771 lvp->text = vp->text; 772 lvp->flags = vp->flags; 773 vp->flags |= VSTRFIXED|VTEXTFIXED; 774 if (name[vp->name_len] == '=') 775 setvareq(savestr(name), VNOLOCAL); 776 } 777 } 778 lvp->vp = vp; 779 lvp->next = localvars; 780 localvars = lvp; 781 INTON; 782} 783 784 785/* 786 * Called after a function returns. 787 */ 788 789void 790poplocalvars(void) 791{ 792 struct localvar *lvp; 793 struct var *vp; 794 795 while ((lvp = localvars) != NULL) { 796 localvars = lvp->next; 797 vp = lvp->vp; 798 if (vp == NULL) { /* $- saved */ 799 memcpy(optlist, lvp->text, sizeof optlist); 800 ckfree(lvp->text); 801 optschanged(); 802 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 803 (void)unsetvar(vp->text); 804 } else { 805 if ((vp->flags & VTEXTFIXED) == 0) 806 ckfree(vp->text); 807 vp->flags = lvp->flags; 808 vp->text = lvp->text; 809 } 810 ckfree(lvp); 811 } 812} 813 814 815int 816setvarcmd(int argc, char **argv) 817{ 818 if (argc <= 2) 819 return unsetcmd(argc, argv); 820 else if (argc == 3) 821 setvar(argv[1], argv[2], 0); 822 else 823 error("too many arguments"); 824 return 0; 825} 826 827 828/* 829 * The unset builtin command. 830 */ 831 832int 833unsetcmd(int argc __unused, char **argv __unused) 834{ 835 char **ap; 836 int i; 837 int flg_func = 0; 838 int flg_var = 0; 839 int ret = 0; 840 841 while ((i = nextopt("vf")) != '\0') { 842 if (i == 'f') 843 flg_func = 1; 844 else 845 flg_var = 1; 846 } 847 if (flg_func == 0 && flg_var == 0) 848 flg_var = 1; 849 850 for (ap = argptr; *ap ; ap++) { 851 if (flg_func) 852 ret |= unsetfunc(*ap); 853 if (flg_var) 854 ret |= unsetvar(*ap); 855 } 856 return ret; 857} 858 859 860/* 861 * Unset the specified variable. 862 */ 863 864int 865unsetvar(const char *s) 866{ 867 struct var **vpp; 868 struct var *vp; 869 870 vp = find_var(s, &vpp, NULL); 871 if (vp == NULL) 872 return (0); 873 if (vp->flags & VREADONLY) 874 return (1); 875 INTOFF; 876 if (vp->text[vp->name_len + 1] != '\0') 877 setvar(s, nullstr, 0); 878 if ((vp->flags & VEXPORT) && localevar(vp->text)) { 879 change_env(s, 0); 880 setlocale(LC_ALL, ""); 881 updatecharset(); 882 } 883 vp->flags &= ~VEXPORT; 884 vp->flags |= VUNSET; 885 if ((vp->flags & VSTRFIXED) == 0) { 886 if ((vp->flags & VTEXTFIXED) == 0) 887 ckfree(vp->text); 888 *vpp = vp->next; 889 ckfree(vp); 890 } 891 INTON; 892 return (0); 893} 894 895 896 897/* 898 * Returns true if the two strings specify the same varable. The first 899 * variable name is terminated by '='; the second may be terminated by 900 * either '=' or '\0'. 901 */ 902 903static int 904varequal(const char *p, const char *q) 905{ 906 while (*p == *q++) { 907 if (*p++ == '=') 908 return 1; 909 } 910 if (*p == '=' && *(q - 1) == '\0') 911 return 1; 912 return 0; 913} 914 915/* 916 * Search for a variable. 917 * 'name' may be terminated by '=' or a NUL. 918 * vppp is set to the pointer to vp, or the list head if vp isn't found 919 * lenp is set to the number of charactets in 'name' 920 */ 921 922static struct var * 923find_var(const char *name, struct var ***vppp, int *lenp) 924{ 925 unsigned int hashval; 926 int len; 927 struct var *vp, **vpp; 928 const char *p = name; 929 930 hashval = 0; 931 while (*p && *p != '=') 932 hashval = 2 * hashval + (unsigned char)*p++; 933 len = p - name; 934 935 if (lenp) 936 *lenp = len; 937 vpp = &vartab[hashval % VTABSIZE]; 938 if (vppp) 939 *vppp = vpp; 940 941 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 942 if (vp->name_len != len) 943 continue; 944 if (memcmp(vp->text, name, len) != 0) 945 continue; 946 if (vppp) 947 *vppp = vpp; 948 return vp; 949 } 950 return NULL; 951} 952