10SN/A/*- 21472SN/A * Copyright (c) 1991, 1993 30SN/A * The Regents of the University of California. All rights reserved. 40SN/A * Copyright (c) 1997-2005 50SN/A * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. 60SN/A * 70SN/A * This code is derived from software contributed to Berkeley by 80SN/A * Kenneth Almquist. 90SN/A * 100SN/A * Redistribution and use in source and binary forms, with or without 110SN/A * modification, are permitted provided that the following conditions 120SN/A * are met: 130SN/A * 1. Redistributions of source code must retain the above copyright 140SN/A * notice, this list of conditions and the following disclaimer. 150SN/A * 2. Redistributions in binary form must reproduce the above copyright 160SN/A * notice, this list of conditions and the following disclaimer in the 170SN/A * documentation and/or other materials provided with the distribution. 180SN/A * 3. Neither the name of the University nor the names of its contributors 191472SN/A * may be used to endorse or promote products derived from this software 201472SN/A * without specific prior written permission. 211472SN/A * 220SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 230SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 240SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 250SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 260SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 270SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 280SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 290SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 300SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 310SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 320SN/A * SUCH DAMAGE. 330SN/A */ 340SN/A 350SN/A#include <zircon/paths.h> 360SN/A#include <unistd.h> 370SN/A#include <stdio.h> 380SN/A#include <stdlib.h> 390SN/A#ifdef HAVE_PATHS_H 400SN/A#include <paths.h> 410SN/A#endif 420SN/A 430SN/A/* 440SN/A * Shell variables. 450SN/A */ 460SN/A 470SN/A#include "shell.h" 480SN/A#include "output.h" 490SN/A#include "expand.h" 500SN/A#include "nodes.h" /* for other headers */ 510SN/A#include "exec.h" 520SN/A#include "syntax.h" 530SN/A#include "options.h" 540SN/A#include "var.h" 550SN/A#include "memalloc.h" 560SN/A#include "error.h" 570SN/A#include "mystring.h" 580SN/A#include "parser.h" 590SN/A#include "show.h" 600SN/A#include "system.h" 610SN/A 620SN/A 630SN/A#define VTABSIZE 39 640SN/A 65 66struct localvar_list { 67 struct localvar_list *next; 68 struct localvar *lv; 69}; 70 71MKINIT struct localvar_list *localvar_stack; 72 73const char defpathvar[] = ZX_SHELL_ENV_PATH; 74#ifdef IFS_BROKEN 75const char defifsvar[] = "IFS= \t\n"; 76#else 77const char defifs[] = " \t\n"; 78#endif 79MKINIT char defoptindvar[] = "OPTIND=1"; 80 81int lineno; 82char linenovar[sizeof("LINENO=")+sizeof(int)*CHAR_BIT/3+1] = "LINENO="; 83 84/* Some macros in var.h depend on the order, add new variables to the end. */ 85struct var varinit[] = { 86#if ATTY 87 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY\0", 0 }, 88#endif 89#ifdef IFS_BROKEN 90 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 }, 91#else 92 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 }, 93#endif 94 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, 95 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, 96 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, 97 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 }, 98 { 0, VSTRFIXED|VTEXTFIXED, defoptindvar, getoptsreset }, 99#ifdef WITH_LINENO 100 { 0, VSTRFIXED|VTEXTFIXED, linenovar, 0 }, 101#endif 102}; 103 104STATIC struct var *vartab[VTABSIZE]; 105 106STATIC struct var **hashvar(const char *); 107STATIC int vpcmp(const void *, const void *); 108STATIC struct var **findvar(struct var **, const char *); 109 110/* 111 * Initialize the varable symbol tables and import the environment 112 */ 113 114#ifdef mkinit 115INCLUDE <unistd.h> 116INCLUDE <sys/types.h> 117INCLUDE <sys/stat.h> 118INCLUDE "cd.h" 119INCLUDE "output.h" 120INCLUDE "var.h" 121MKINIT char **environ; 122INIT { 123 char **envp; 124 static char ppid[32] = "PPID="; 125 const char *p; 126 struct stat st1, st2; 127 128 initvar(); 129 for (envp = environ ; *envp ; envp++) { 130 p = endofname(*envp); 131 if (p != *envp && *p == '=') { 132 setvareq(*envp, VEXPORT|VTEXTFIXED); 133 } 134 } 135 136 setvareq(defoptindvar, VTEXTFIXED); 137 138 fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid()); 139 setvareq(ppid, VTEXTFIXED); 140 141 p = lookupvar("PWD"); 142 if (p) 143 if (*p != '/' || stat(p, &st1) || stat(".", &st2) || 144 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) 145 p = 0; 146 setpwd(p, 0); 147} 148 149RESET { 150 unwindlocalvars(0); 151} 152#endif 153 154 155/* 156 * This routine initializes the builtin variables. It is called when the 157 * shell is initialized. 158 */ 159 160void 161initvar(void) 162{ 163 struct var *vp; 164 struct var *end; 165 struct var **vpp; 166 167 vp = varinit; 168 end = vp + sizeof(varinit) / sizeof(varinit[0]); 169 do { 170 vpp = hashvar(vp->text); 171 vp->next = *vpp; 172 *vpp = vp; 173 } while (++vp < end); 174 /* 175 * PS1 depends on uid 176 */ 177 if (!geteuid()) 178 vps1.text = "PS1=# "; 179} 180 181/* 182 * Set the value of a variable. The flags argument is ored with the 183 * flags of the variable. If val is NULL, the variable is unset. 184 */ 185 186struct var *setvar(const char *name, const char *val, int flags) 187{ 188 char *p, *q; 189 size_t namelen; 190 char *nameeq; 191 size_t vallen; 192 struct var *vp; 193 194 q = endofname(name); 195 p = strchrnul(q, '='); 196 namelen = p - name; 197 if (!namelen || p != q) 198 sh_error("%.*s: bad variable name", namelen, name); 199 vallen = 0; 200 if (val == NULL) { 201 flags |= VUNSET; 202 } else { 203 vallen = strlen(val); 204 } 205 INTOFF; 206 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen); 207 if (val) { 208 *p++ = '='; 209 p = mempcpy(p, val, vallen); 210 } 211 *p = '\0'; 212 vp = setvareq(nameeq, flags | VNOSAVE); 213 INTON; 214 215 return vp; 216} 217 218/* 219 * Set the given integer as the value of a variable. The flags argument is 220 * ored with the flags of the variable. 221 */ 222 223intmax_t setvarint(const char *name, intmax_t val, int flags) 224{ 225 int len = max_int_length(sizeof(val)); 226 char buf[len]; 227 228 fmtstr(buf, len, "%" PRIdMAX, val); 229 setvar(name, buf, flags); 230 return val; 231} 232 233 234 235/* 236 * Same as setvar except that the variable and value are passed in 237 * the first argument as name=value. Since the first argument will 238 * be actually stored in the table, it should not be a string that 239 * will go away. 240 * Called with interrupts off. 241 */ 242 243struct var *setvareq(char *s, int flags) 244{ 245 struct var *vp, **vpp; 246 247 vpp = hashvar(s); 248 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); 249 vpp = findvar(vpp, s); 250 vp = *vpp; 251 if (vp) { 252 if (vp->flags & VREADONLY) { 253 const char *n; 254 255 if (flags & VNOSAVE) 256 free(s); 257 n = vp->text; 258 sh_error("%.*s: is read only", strchrnul(n, '=') - n, 259 n); 260 } 261 262 if (flags & VNOSET) 263 goto out; 264 265 if (vp->func && (flags & VNOFUNC) == 0) 266 (*vp->func)(strchrnul(s, '=') + 1); 267 268 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 269 ckfree(vp->text); 270 271 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | 272 (vp->flags & VSTRFIXED)) == VUNSET) { 273 *vpp = vp->next; 274 ckfree(vp); 275out_free: 276 if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE) 277 ckfree(s); 278 goto out; 279 } 280 281 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET); 282 } else { 283 if (flags & VNOSET) 284 goto out; 285 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET) 286 goto out_free; 287 /* not found */ 288 vp = ckmalloc(sizeof (*vp)); 289 vp->next = *vpp; 290 vp->func = NULL; 291 *vpp = vp; 292 } 293 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE))) 294 s = savestr(s); 295 vp->text = s; 296 vp->flags = flags; 297 298out: 299 return vp; 300} 301 302 303 304/* 305 * Process a linked list of variable assignments. 306 */ 307 308void 309listsetvar(struct strlist *list, int flags) 310{ 311 struct strlist *lp; 312 313 lp = list; 314 if (!lp) 315 return; 316 INTOFF; 317 do { 318 setvareq(lp->text, flags); 319 } while ((lp = lp->next)); 320 INTON; 321} 322 323 324/* 325 * Find the value of a variable. Returns NULL if not set. 326 */ 327 328char * 329lookupvar(const char *name) 330{ 331 struct var *v; 332 333 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) { 334#ifdef WITH_LINENO 335 if (v == &vlineno && v->text == linenovar) { 336 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); 337 } 338#endif 339 return strchrnul(v->text, '=') + 1; 340 } 341 return NULL; 342} 343 344intmax_t lookupvarint(const char *name) 345{ 346 return atomax(lookupvar(name) ?: nullstr, 0); 347} 348 349 350 351/* 352 * Generate a list of variables satisfying the given conditions. 353 */ 354 355char ** 356listvars(int on, int off, char ***end) 357{ 358 struct var **vpp; 359 struct var *vp; 360 char **ep; 361 int mask; 362 363 STARTSTACKSTR(ep); 364 vpp = vartab; 365 mask = on | off; 366 do { 367 for (vp = *vpp ; vp ; vp = vp->next) 368 if ((vp->flags & mask) == on) { 369 if (ep == stackstrend()) 370 ep = growstackstr(); 371 *ep++ = (char *) vp->text; 372 } 373 } while (++vpp < vartab + VTABSIZE); 374 if (ep == stackstrend()) 375 ep = growstackstr(); 376 if (end) 377 *end = ep; 378 *ep++ = NULL; 379 return grabstackstr(ep); 380} 381 382 383 384/* 385 * POSIX requires that 'set' (but not export or readonly) output the 386 * variables in lexicographic order - by the locale's collating order (sigh). 387 * Maybe we could keep them in an ordered balanced binary tree 388 * instead of hashed lists. 389 * For now just roll 'em through qsort for printing... 390 */ 391 392int 393showvars(const char *prefix, int on, int off) 394{ 395 const char *sep; 396 char **ep, **epend; 397 398 ep = listvars(on, off, &epend); 399 qsort(ep, epend - ep, sizeof(char *), vpcmp); 400 401 sep = *prefix ? spcstr : prefix; 402 403 for (; ep < epend; ep++) { 404 const char *p; 405 const char *q; 406 407 p = strchrnul(*ep, '='); 408 q = nullstr; 409 if (*p) 410 q = single_quote(++p); 411 412 out1fmt("%s%s%.*s%s\n", prefix, sep, (int)(p - *ep), *ep, q); 413 } 414 415 return 0; 416} 417 418 419 420/* 421 * The export and readonly commands. 422 */ 423 424int 425exportcmd(int argc, char **argv) 426{ 427 struct var *vp; 428 char *name; 429 const char *p; 430 char **aptr; 431 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 432 int notp; 433 434 notp = nextopt("p") - 'p'; 435 if (notp && ((name = *(aptr = argptr)))) { 436 do { 437 if ((p = strchr(name, '=')) != NULL) { 438 p++; 439 } else { 440 if ((vp = *findvar(hashvar(name), name))) { 441 vp->flags |= flag; 442 continue; 443 } 444 } 445 setvar(name, p, flag); 446 } while ((name = *++aptr) != NULL); 447 } else { 448 showvars(argv[0], flag, 0); 449 } 450 return 0; 451} 452 453 454/* 455 * The "local" command. 456 */ 457 458int 459localcmd(int argc, char **argv) 460{ 461 char *name; 462 463 if (!localvar_stack) 464 sh_error("not in a function"); 465 466 argv = argptr; 467 while ((name = *argv++) != NULL) { 468 mklocal(name); 469 } 470 return 0; 471} 472 473 474/* 475 * Make a variable a local variable. When a variable is made local, it's 476 * value and flags are saved in a localvar structure. The saved values 477 * will be restored when the shell function returns. We handle the name 478 * "-" as a special case. 479 */ 480 481void mklocal(char *name) 482{ 483 struct localvar *lvp; 484 struct var **vpp; 485 struct var *vp; 486 487 INTOFF; 488 lvp = ckmalloc(sizeof (struct localvar)); 489 if (name[0] == '-' && name[1] == '\0') { 490 char *p; 491 p = ckmalloc(sizeof(optlist)); 492 lvp->text = memcpy(p, optlist, sizeof(optlist)); 493 vp = NULL; 494 } else { 495 char *eq; 496 497 vpp = hashvar(name); 498 vp = *findvar(vpp, name); 499 eq = strchr(name, '='); 500 if (vp == NULL) { 501 if (eq) 502 vp = setvareq(name, VSTRFIXED); 503 else 504 vp = setvar(name, NULL, VSTRFIXED); 505 lvp->flags = VUNSET; 506 } else { 507 lvp->text = vp->text; 508 lvp->flags = vp->flags; 509 vp->flags |= VSTRFIXED|VTEXTFIXED; 510 if (eq) 511 setvareq(name, 0); 512 } 513 } 514 lvp->vp = vp; 515 lvp->next = localvar_stack->lv; 516 localvar_stack->lv = lvp; 517 INTON; 518} 519 520 521/* 522 * Called after a function returns. 523 * Interrupts must be off. 524 */ 525 526void 527poplocalvars(int keep) 528{ 529 struct localvar_list *ll; 530 struct localvar *lvp, *next; 531 struct var *vp; 532 533 INTOFF; 534 ll = localvar_stack; 535 localvar_stack = ll->next; 536 537 next = ll->lv; 538 ckfree(ll); 539 540 while ((lvp = next) != NULL) { 541 next = lvp->next; 542 vp = lvp->vp; 543 TRACE(("poplocalvar %s\n", vp ? vp->text : "-")); 544 if (keep) { 545 int bits = VSTRFIXED; 546 547 if (lvp->flags != VUNSET) { 548 if (vp->text == lvp->text) 549 bits |= VTEXTFIXED; 550 else if (!(lvp->flags & (VTEXTFIXED|VSTACK))) 551 ckfree(lvp->text); 552 } 553 554 vp->flags &= ~bits; 555 vp->flags |= (lvp->flags & bits); 556 557 if ((vp->flags & 558 (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET) 559 unsetvar(vp->text); 560 } else if (vp == NULL) { /* $- saved */ 561 memcpy(optlist, lvp->text, sizeof(optlist)); 562 ckfree(lvp->text); 563 optschanged(); 564 } else if (lvp->flags == VUNSET) { 565 vp->flags &= ~(VSTRFIXED|VREADONLY); 566 unsetvar(vp->text); 567 } else { 568 if (vp->func) 569 (*vp->func)(strchrnul(lvp->text, '=') + 1); 570 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 571 ckfree(vp->text); 572 vp->flags = lvp->flags; 573 vp->text = lvp->text; 574 } 575 ckfree(lvp); 576 } 577 INTON; 578} 579 580 581/* 582 * Create a new localvar environment. 583 */ 584struct localvar_list *pushlocalvars(void) 585{ 586 struct localvar_list *ll; 587 588 INTOFF; 589 ll = ckmalloc(sizeof(*ll)); 590 ll->lv = NULL; 591 ll->next = localvar_stack; 592 localvar_stack = ll; 593 INTON; 594 595 return ll->next; 596} 597 598 599void unwindlocalvars(struct localvar_list *stop) 600{ 601 while (localvar_stack != stop) 602 poplocalvars(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 612int 613unsetcmd(int argc, char **argv) 614{ 615 char **ap; 616 int i; 617 int flag = 0; 618 619 while ((i = nextopt("vf")) != '\0') { 620 flag = i; 621 } 622 623 for (ap = argptr; *ap ; ap++) { 624 if (flag != 'f') { 625 unsetvar(*ap); 626 continue; 627 } 628 if (flag != 'v') 629 unsetfunc(*ap); 630 } 631 return 0; 632} 633 634 635/* 636 * Unset the specified variable. 637 */ 638 639void unsetvar(const char *s) 640{ 641 setvar(s, 0, 0); 642} 643 644 645 646/* 647 * Find the appropriate entry in the hash table from the name. 648 */ 649 650STATIC struct var ** 651hashvar(const char *p) 652{ 653 unsigned int hashval; 654 655 hashval = ((unsigned char) *p) << 4; 656 while (*p && *p != '=') 657 hashval += (unsigned char) *p++; 658 return &vartab[hashval % VTABSIZE]; 659} 660 661 662 663/* 664 * Compares two strings up to the first = or '\0'. The first 665 * string must be terminated by '='; the second may be terminated by 666 * either '=' or '\0'. 667 */ 668 669int 670varcmp(const char *p, const char *q) 671{ 672 int c, d; 673 674 while ((c = *p) == (d = *q)) { 675 if (!c || c == '=') 676 goto out; 677 p++; 678 q++; 679 } 680 if (c == '=') 681 c = 0; 682 if (d == '=') 683 d = 0; 684out: 685 return c - d; 686} 687 688STATIC int 689vpcmp(const void *a, const void *b) 690{ 691 return varcmp(*(const char **)a, *(const char **)b); 692} 693 694STATIC struct var ** 695findvar(struct var **vpp, const char *name) 696{ 697 for (; *vpp; vpp = &(*vpp)->next) { 698 if (varequal((*vpp)->text, name)) { 699 break; 700 } 701 } 702 return vpp; 703} 704