1 /* $NetBSD: var.c,v 1.66 2017/07/24 13:36:15 kre 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 38 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 39 #else 40 __RCSID("$NetBSD: var.c,v 1.66 2017/07/24 13:36:15 kre Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <stdio.h> 45 #include <unistd.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <paths.h> 49 #include <limits.h> 50 #include <time.h> 51 #include <pwd.h> 52 #include <fcntl.h> 53 54 /* 55 * Shell variables. 56 */ 57 58 #include "shell.h" 59 #include "output.h" 60 #include "expand.h" 61 #include "nodes.h" /* for other headers */ 62 #include "eval.h" /* defines cmdenviron */ 63 #include "exec.h" 64 #include "syntax.h" 65 #include "options.h" 66 #include "builtins.h" 67 #include "mail.h" 68 #include "var.h" 69 #include "memalloc.h" 70 #include "error.h" 71 #include "mystring.h" 72 #include "parser.h" 73 #include "show.h" 74 #include "machdep.h" 75 #ifndef SMALL 76 #include "myhistedit.h" 77 #endif 78 79 #ifdef SMALL 80 #define VTABSIZE 39 81 #else 82 #define VTABSIZE 517 83 #endif 84 85 86 struct varinit { 87 struct var *var; 88 int flags; 89 const char *text; 90 union var_func_union v_u; 91 }; 92 #define func v_u.set_func 93 #define rfunc v_u.ref_func 94 95 char *get_lineno(struct var *); 96 97 #ifndef SMALL 98 char *get_tod(struct var *); 99 char *get_hostname(struct var *); 100 char *get_seconds(struct var *); 101 char *get_euser(struct var *); 102 char *get_random(struct var *); 103 #endif 104 105 struct localvar *localvars; 106 107 #ifndef SMALL 108 struct var vhistsize; 109 struct var vterm; 110 struct var editrc; 111 struct var ps_lit; 112 #endif 113 struct var vifs; 114 struct var vmail; 115 struct var vmpath; 116 struct var vpath; 117 struct var vps1; 118 struct var vps2; 119 struct var vps4; 120 struct var vvers; 121 struct var voptind; 122 struct var line_num; 123 #ifndef SMALL 124 struct var tod; 125 struct var host_name; 126 struct var seconds; 127 struct var euname; 128 struct var random_num; 129 130 intmax_t sh_start_time; 131 #endif 132 133 struct var line_num; 134 int line_number; 135 int funclinebase = 0; 136 int funclineabs = 0; 137 138 char ifs_default[] = " \t\n"; 139 140 const struct varinit varinit[] = { 141 #ifndef SMALL 142 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 143 { .set_func= sethistsize } }, 144 #endif 145 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 146 { NULL } }, 147 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", 148 { NULL } }, 149 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 150 { NULL } }, 151 { &vvers, VSTRFIXED|VTEXTFIXED|VNOEXPORT, "NETBSD_SHELL=", 152 { NULL } }, 153 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, 154 { .set_func= changepath } }, 155 /* 156 * vps1 depends on uid 157 */ 158 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 159 { NULL } }, 160 { &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 161 { NULL } }, 162 #ifndef SMALL 163 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 164 { .set_func= setterm } }, 165 { &editrc, VSTRFIXED|VTEXTFIXED|VUNSET, "EDITRC=", 166 { .set_func= set_editrc } }, 167 { &ps_lit, VSTRFIXED|VTEXTFIXED|VUNSET, "PSlit=", 168 { .set_func= set_prompt_lit } }, 169 #endif 170 { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", 171 { .set_func= getoptsreset } }, 172 { &line_num, VSTRFIXED|VTEXTFIXED|VFUNCREF, "LINENO=1", 173 { .ref_func= get_lineno } }, 174 #ifndef SMALL 175 { &tod, VSTRFIXED|VTEXTFIXED|VFUNCREF, "ToD=", 176 { .ref_func= get_tod } }, 177 { &host_name, VSTRFIXED|VTEXTFIXED|VFUNCREF, "HOSTNAME=", 178 { .ref_func= get_hostname } }, 179 { &seconds, VSTRFIXED|VTEXTFIXED|VFUNCREF, "SECONDS=", 180 { .ref_func= get_seconds } }, 181 { &euname, VSTRFIXED|VTEXTFIXED|VFUNCREF, "EUSER=", 182 { .ref_func= get_euser } }, 183 { &random_num, VSTRFIXED|VTEXTFIXED|VFUNCREF, "RANDOM=", 184 { .ref_func= get_random } }, 185 #endif 186 { NULL, 0, NULL, 187 { NULL } } 188 }; 189 190 struct var *vartab[VTABSIZE]; 191 192 STATIC int strequal(const char *, const char *); 193 STATIC struct var *find_var(const char *, struct var ***, int *); 194 195 /* 196 * Initialize the varable symbol tables and import the environment 197 */ 198 199 #ifdef mkinit 200 INCLUDE <stdio.h> 201 INCLUDE <unistd.h> 202 INCLUDE <time.h> 203 INCLUDE "var.h" 204 INCLUDE "version.h" 205 MKINIT char **environ; 206 INIT { 207 char **envp; 208 char buf[64]; 209 210 #ifndef SMALL 211 sh_start_time = (intmax_t)time((time_t *)0); 212 #endif 213 /* 214 * Set up our default variables and their values. 215 */ 216 initvar(); 217 218 /* 219 * Import variables from the environment, which will 220 * override anything initialised just previously. 221 */ 222 for (envp = environ ; *envp ; envp++) { 223 if (strchr(*envp, '=')) { 224 setvareq(*envp, VEXPORT|VTEXTFIXED); 225 } 226 } 227 228 /* 229 * Set variables which override anything read from environment. 230 * 231 * PPID is readonly 232 * Always default IFS 233 * PSc indicates the root/non-root status of this shell. 234 * NETBSD_SHELL is a constant (readonly), and is never exported 235 * START_TIME belongs only to this shell. 236 * LINENO is simply magic... 237 */ 238 snprintf(buf, sizeof(buf), "%d", (int)getppid()); 239 setvar("PPID", buf, VREADONLY); 240 setvar("IFS", ifs_default, VTEXTFIXED); 241 setvar("PSc", (geteuid() == 0 ? "#" : "$"), VTEXTFIXED); 242 243 #ifndef SMALL 244 snprintf(buf, sizeof(buf), "%jd", sh_start_time); 245 setvar("START_TIME", buf, VTEXTFIXED); 246 #endif 247 248 setvar("NETBSD_SHELL", NETBSD_SHELL 249 #ifdef BUILD_DATE 250 " BUILD:" BUILD_DATE 251 #endif 252 #ifdef DEBUG 253 " DEBUG" 254 #endif 255 #if !defined(JOBS) || JOBS == 0 256 " -JOBS" 257 #endif 258 #ifndef DO_SHAREDVFORK 259 " -VFORK" 260 #endif 261 #ifdef SMALL 262 " SMALL" 263 #endif 264 #ifdef TINY 265 " TINY" 266 #endif 267 #ifdef OLD_TTY_DRIVER 268 " OLD_TTY" 269 #endif 270 #ifdef SYSV 271 " SYSV" 272 #endif 273 #ifndef BSD 274 " -BSD" 275 #endif 276 #ifdef BOGUS_NOT_COMMAND 277 " BOGUS_NOT" 278 #endif 279 , VTEXTFIXED|VREADONLY|VNOEXPORT); 280 281 setvar("LINENO", "1", VTEXTFIXED); 282 } 283 #endif 284 285 286 /* 287 * This routine initializes the builtin variables. It is called when the 288 * shell is initialized and again when a shell procedure is spawned. 289 */ 290 291 void 292 initvar(void) 293 { 294 const struct varinit *ip; 295 struct var *vp; 296 struct var **vpp; 297 298 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 299 if (find_var(ip->text, &vpp, &vp->name_len) != NULL) 300 continue; 301 vp->next = *vpp; 302 *vpp = vp; 303 vp->text = strdup(ip->text); 304 vp->flags = (ip->flags & ~VTEXTFIXED) | VSTRFIXED; 305 vp->v_u = ip->v_u; 306 } 307 /* 308 * PS1 depends on uid 309 */ 310 if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { 311 vps1.next = *vpp; 312 *vpp = &vps1; 313 vps1.flags = VSTRFIXED; 314 vps1.text = NULL; 315 choose_ps1(); 316 } 317 } 318 319 void 320 choose_ps1(void) 321 { 322 if ((vps1.flags & (VTEXTFIXED|VSTACK)) == 0) 323 free(vps1.text); 324 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); 325 vps1.flags &= ~(VTEXTFIXED|VSTACK); 326 327 /* 328 * Update PSc whenever we feel the need to update PS1 329 */ 330 setvarsafe("PSc", (geteuid() == 0 ? "#" : "$"), 0); 331 } 332 333 /* 334 * Safe version of setvar, returns 1 on success 0 on failure. 335 */ 336 337 int 338 setvarsafe(const char *name, const char *val, int flags) 339 { 340 struct jmploc jmploc; 341 struct jmploc * const savehandler = handler; 342 int volatile err = 0; 343 344 if (setjmp(jmploc.loc)) 345 err = 1; 346 else { 347 handler = &jmploc; 348 setvar(name, val, flags); 349 } 350 handler = savehandler; 351 return err; 352 } 353 354 /* 355 * Set the value of a variable. The flags argument is ored with the 356 * flags of the variable. If val is NULL, the variable is unset. 357 * 358 * This always copies name and val when setting a variable, so 359 * the source strings can be from anywhere, and are no longer needed 360 * after this function returns. The VTEXTFIXED and VSTACK flags should 361 * not be used (but just in case they were, clear them.) 362 */ 363 364 void 365 setvar(const char *name, const char *val, int flags) 366 { 367 const char *p; 368 const char *q; 369 char *d; 370 int len; 371 int namelen; 372 char *nameeq; 373 int isbad; 374 375 isbad = 0; 376 p = name; 377 if (! is_name(*p)) 378 isbad = 1; 379 p++; 380 for (;;) { 381 if (! is_in_name(*p)) { 382 if (*p == '\0' || *p == '=') 383 break; 384 isbad = 1; 385 } 386 p++; 387 } 388 namelen = p - name; 389 if (isbad) 390 error("%.*s: bad variable name", namelen, name); 391 len = namelen + 2; /* 2 is space for '=' and '\0' */ 392 if (val == NULL) { 393 flags |= VUNSET; 394 } else { 395 len += strlen(val); 396 } 397 d = nameeq = ckmalloc(len); 398 q = name; 399 while (--namelen >= 0) 400 *d++ = *q++; 401 *d++ = '='; 402 *d = '\0'; 403 if (val) 404 scopy(val, d); 405 setvareq(nameeq, flags & ~(VTEXTFIXED | VSTACK)); 406 } 407 408 409 410 /* 411 * Same as setvar except that the variable and value are passed in 412 * the first argument as name=value. Since the first argument will 413 * be actually stored in the table, it should not be a string that 414 * will go away. The flags (VTEXTFIXED or VSTACK) can be used to 415 * indicate the source of the string (if neither is set, the string will 416 * eventually be free()d when a replacement value is assigned.) 417 */ 418 419 void 420 setvareq(char *s, int flags) 421 { 422 struct var *vp, **vpp; 423 int nlen; 424 425 VTRACE(DBG_VARS, ("setvareq([%s],%#x) aflag=%d ", s, flags, aflag)); 426 if (aflag && !(flags & VNOEXPORT)) 427 flags |= VEXPORT; 428 vp = find_var(s, &vpp, &nlen); 429 if (vp != NULL) { 430 VTRACE(DBG_VARS, ("was [%s] fl:%#x\n", vp->text, 431 vp->flags)); 432 if (vp->flags & VREADONLY) { 433 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 434 ckfree(s); 435 if (flags & VNOERROR) 436 return; 437 error("%.*s: is read only", vp->name_len, vp->text); 438 } 439 if (flags & VNOSET) { 440 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 441 ckfree(s); 442 return; 443 } 444 445 INTOFF; 446 447 if (vp->func && !(vp->flags & VFUNCREF) && !(flags & VNOFUNC)) 448 (*vp->func)(s + vp->name_len + 1); 449 450 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 451 ckfree(vp->text); 452 453 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 454 if (flags & VNOEXPORT) 455 vp->flags &= ~VEXPORT; 456 if (vp->flags & VNOEXPORT) 457 flags &= ~VEXPORT; 458 vp->flags |= flags & ~VNOFUNC; 459 vp->text = s; 460 461 /* 462 * We could roll this to a function, to handle it as 463 * a regular variable function callback, but why bother? 464 */ 465 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 466 chkmail(1); 467 468 INTON; 469 return; 470 } 471 VTRACE(DBG_VARS, ("new\n")); 472 /* not found */ 473 if (flags & VNOSET) { 474 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 475 ckfree(s); 476 return; 477 } 478 vp = ckmalloc(sizeof (*vp)); 479 vp->flags = flags & ~(VNOFUNC|VFUNCREF|VSTRFIXED); 480 vp->text = s; 481 vp->name_len = nlen; 482 vp->next = *vpp; 483 vp->func = NULL; 484 *vpp = vp; 485 } 486 487 488 489 /* 490 * Process a linked list of variable assignments. 491 */ 492 493 void 494 listsetvar(struct strlist *list, int flags) 495 { 496 struct strlist *lp; 497 498 INTOFF; 499 for (lp = list ; lp ; lp = lp->next) { 500 setvareq(savestr(lp->text), flags); 501 } 502 INTON; 503 } 504 505 void 506 listmklocal(struct strlist *list, int flags) 507 { 508 struct strlist *lp; 509 510 for (lp = list ; lp ; lp = lp->next) 511 mklocal(lp->text, flags); 512 } 513 514 515 /* 516 * Find the value of a variable. Returns NULL if not set. 517 */ 518 519 char * 520 lookupvar(const char *name) 521 { 522 struct var *v; 523 524 v = find_var(name, NULL, NULL); 525 if (v == NULL || v->flags & VUNSET) 526 return NULL; 527 if (v->rfunc && (v->flags & VFUNCREF) != 0) 528 return (*v->rfunc)(v) + v->name_len + 1; 529 return v->text + v->name_len + 1; 530 } 531 532 533 534 /* 535 * Search the environment of a builtin command. If the second argument 536 * is nonzero, return the value of a variable even if it hasn't been 537 * exported. 538 */ 539 540 char * 541 bltinlookup(const char *name, int doall) 542 { 543 struct strlist *sp; 544 struct var *v; 545 546 for (sp = cmdenviron ; sp ; sp = sp->next) { 547 if (strequal(sp->text, name)) 548 return strchr(sp->text, '=') + 1; 549 } 550 551 v = find_var(name, NULL, NULL); 552 553 if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) 554 return NULL; 555 if (v->rfunc && (v->flags & VFUNCREF) != 0) 556 return (*v->rfunc)(v) + v->name_len + 1; 557 return v->text + v->name_len + 1; 558 } 559 560 561 562 /* 563 * Generate a list of exported variables. This routine is used to construct 564 * the third argument to execve when executing a program. 565 */ 566 567 char ** 568 environment(void) 569 { 570 int nenv; 571 struct var **vpp; 572 struct var *vp; 573 char **env; 574 char **ep; 575 576 nenv = 0; 577 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 578 for (vp = *vpp ; vp ; vp = vp->next) 579 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) 580 nenv++; 581 } 582 CTRACE(DBG_VARS, ("environment: %d vars to export\n", nenv)); 583 ep = env = stalloc((nenv + 1) * sizeof *env); 584 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 585 for (vp = *vpp ; vp ; vp = vp->next) 586 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) { 587 if (vp->rfunc && (vp->flags & VFUNCREF)) 588 *ep++ = (*vp->rfunc)(vp); 589 else 590 *ep++ = vp->text; 591 VTRACE(DBG_VARS, ("environment: %s\n", ep[-1])); 592 } 593 } 594 *ep = NULL; 595 return env; 596 } 597 598 599 /* 600 * Called when a shell procedure is invoked to clear out nonexported 601 * variables. It is also necessary to reallocate variables of with 602 * VSTACK set since these are currently allocated on the stack. 603 */ 604 605 #ifdef mkinit 606 void shprocvar(void); 607 608 SHELLPROC { 609 shprocvar(); 610 } 611 #endif 612 613 void 614 shprocvar(void) 615 { 616 struct var **vpp; 617 struct var *vp, **prev; 618 619 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 620 for (prev = vpp ; (vp = *prev) != NULL ; ) { 621 if ((vp->flags & VEXPORT) == 0) { 622 *prev = vp->next; 623 if ((vp->flags & VTEXTFIXED) == 0) 624 ckfree(vp->text); 625 if ((vp->flags & VSTRFIXED) == 0) 626 ckfree(vp); 627 } else { 628 if (vp->flags & VSTACK) { 629 vp->text = savestr(vp->text); 630 vp->flags &=~ VSTACK; 631 } 632 prev = &vp->next; 633 } 634 } 635 } 636 initvar(); 637 } 638 639 640 641 /* 642 * Command to list all variables which are set. Currently this command 643 * is invoked from the set command when the set command is called without 644 * any variables. 645 */ 646 647 void 648 print_quoted(const char *p) 649 { 650 const char *q; 651 652 if (p[0] == '\0') { 653 out1fmt("''"); 654 return; 655 } 656 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 657 out1fmt("%s", p); 658 return; 659 } 660 while (*p) { 661 if (*p == '\'') { 662 out1fmt("\\'"); 663 p++; 664 continue; 665 } 666 q = strchr(p, '\''); 667 if (!q) { 668 out1fmt("'%s'", p ); 669 return; 670 } 671 out1fmt("'%.*s'", (int)(q - p), p ); 672 p = q; 673 } 674 } 675 676 static int 677 sort_var(const void *v_v1, const void *v_v2) 678 { 679 const struct var * const *v1 = v_v1; 680 const struct var * const *v2 = v_v2; 681 char *t1 = (*v1)->text, *t2 = (*v2)->text; 682 683 if (*t1 == *t2) { 684 char *p, *s; 685 686 STARTSTACKSTR(p); 687 688 /* 689 * note: if lengths are equal, strings must be different 690 * so we don't care which string we pick for the \0 in 691 * that case. 692 */ 693 if ((strchr(t1, '=') - t1) <= (strchr(t2, '=') - t2)) { 694 s = t1; 695 t1 = p; 696 } else { 697 s = t2; 698 t2 = p; 699 } 700 701 while (*s && *s != '=') { 702 STPUTC(*s, p); 703 s++; 704 } 705 STPUTC('\0', p); 706 } 707 708 return strcoll(t1, t2); 709 } 710 711 /* 712 * POSIX requires that 'set' (but not export or readonly) output the 713 * variables in lexicographic order - by the locale's collating order (sigh). 714 * Maybe we could keep them in an ordered balanced binary tree 715 * instead of hashed lists. 716 * For now just roll 'em through qsort for printing... 717 */ 718 719 int 720 showvars(const char *name, int flag, int show_value, const char *xtra) 721 { 722 struct var **vpp; 723 struct var *vp; 724 const char *p; 725 726 static struct var **list; /* static in case we are interrupted */ 727 static int list_len; 728 int count = 0; 729 730 if (!list) { 731 list_len = 32; 732 list = ckmalloc(list_len * sizeof *list); 733 } 734 735 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 736 for (vp = *vpp ; vp ; vp = vp->next) { 737 if (flag && !(vp->flags & flag)) 738 continue; 739 if (vp->flags & VUNSET && !(show_value & 2)) 740 continue; 741 if (count >= list_len) { 742 list = ckrealloc(list, 743 (list_len << 1) * sizeof *list); 744 list_len <<= 1; 745 } 746 list[count++] = vp; 747 } 748 } 749 750 qsort(list, count, sizeof *list, sort_var); 751 752 for (vpp = list; count--; vpp++) { 753 vp = *vpp; 754 if (name) 755 out1fmt("%s ", name); 756 if (xtra) 757 out1fmt("%s ", xtra); 758 p = vp->text; 759 if (vp->rfunc && (vp->flags & VFUNCREF) != 0) { 760 p = (*vp->rfunc)(vp); 761 if (p == NULL) 762 p = vp->text; 763 } 764 for ( ; *p != '=' ; p++) 765 out1c(*p); 766 if (!(vp->flags & VUNSET) && show_value) { 767 out1fmt("="); 768 print_quoted(++p); 769 } 770 out1c('\n'); 771 } 772 return 0; 773 } 774 775 776 777 /* 778 * The export and readonly commands. 779 */ 780 781 int 782 exportcmd(int argc, char **argv) 783 { 784 struct var *vp; 785 char *name; 786 const char *p; 787 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 788 int pflg = 0; 789 int nflg = 0; 790 int xflg = 0; 791 int res; 792 int c; 793 int f; 794 795 while ((c = nextopt("npx")) != '\0') { 796 switch (c) { 797 case 'p': 798 if (nflg) 799 return 1; 800 pflg = 3; 801 break; 802 case 'n': 803 if (pflg || xflg || flag == VREADONLY) 804 return 1; 805 nflg = 1; 806 break; 807 case 'x': 808 if (nflg || flag == VREADONLY) 809 return 1; 810 flag = VNOEXPORT; 811 xflg = 1; 812 break; 813 default: 814 return 1; 815 } 816 } 817 818 if (nflg && *argptr == NULL) 819 return 1; 820 821 if (pflg || *argptr == NULL) { 822 showvars( pflg ? argv[0] : 0, flag, pflg, 823 pflg && xflg ? "-x" : NULL ); 824 return 0; 825 } 826 827 res = 0; 828 while ((name = *argptr++) != NULL) { 829 f = flag; 830 if ((p = strchr(name, '=')) != NULL) { 831 p++; 832 } else { 833 vp = find_var(name, NULL, NULL); 834 if (vp != NULL) { 835 if (nflg) 836 vp->flags &= ~flag; 837 else if (flag&VEXPORT && vp->flags&VNOEXPORT) 838 res = 1; 839 else { 840 vp->flags |= flag; 841 if (flag == VNOEXPORT) 842 vp->flags &= ~VEXPORT; 843 } 844 continue; 845 } else 846 f |= VUNSET; 847 } 848 if (!nflg) 849 setvar(name, p, f); 850 } 851 return res; 852 } 853 854 855 /* 856 * The "local" command. 857 */ 858 859 int 860 localcmd(int argc, char **argv) 861 { 862 char *name; 863 int c; 864 int flags = 0; /*XXX perhaps VUNSET from a -o option value */ 865 866 if (! in_function()) 867 error("Not in a function"); 868 869 /* upper case options, as bash stole all the good ones ... */ 870 while ((c = nextopt("INx")) != '\0') 871 switch (c) { 872 case 'I': flags &= ~VUNSET; break; 873 case 'N': flags |= VUNSET; break; 874 case 'x': flags |= VEXPORT; break; 875 } 876 877 while ((name = *argptr++) != NULL) { 878 mklocal(name, flags); 879 } 880 return 0; 881 } 882 883 884 /* 885 * Make a variable a local variable. When a variable is made local, its 886 * value and flags are saved in a localvar structure. The saved values 887 * will be restored when the shell function returns. We handle the name 888 * "-" as a special case. 889 */ 890 891 void 892 mklocal(const char *name, int flags) 893 { 894 struct localvar *lvp; 895 struct var **vpp; 896 struct var *vp; 897 898 INTOFF; 899 lvp = ckmalloc(sizeof (struct localvar)); 900 if (name[0] == '-' && name[1] == '\0') { 901 char *p; 902 p = ckmalloc(sizeof_optlist); 903 lvp->text = memcpy(p, optlist, sizeof_optlist); 904 vp = NULL; 905 } else { 906 vp = find_var(name, &vpp, NULL); 907 if (vp == NULL) { 908 flags &= ~VNOEXPORT; 909 if (strchr(name, '=')) 910 setvareq(savestr(name), 911 VSTRFIXED | (flags & ~VUNSET)); 912 else 913 setvar(name, NULL, VSTRFIXED|flags); 914 vp = *vpp; /* the new variable */ 915 lvp->text = NULL; 916 lvp->flags = VUNSET; 917 } else { 918 lvp->text = vp->text; 919 lvp->flags = vp->flags; 920 vp->flags |= VSTRFIXED|VTEXTFIXED; 921 if (vp->flags & VNOEXPORT) 922 flags &= ~VEXPORT; 923 if (flags & (VNOEXPORT | VUNSET)) 924 vp->flags &= ~VEXPORT; 925 flags &= ~VNOEXPORT; 926 if (name[vp->name_len] == '=') 927 setvareq(savestr(name), flags & ~VUNSET); 928 else if (flags & VUNSET) 929 unsetvar(name, 0); 930 else 931 vp->flags |= flags & (VUNSET|VEXPORT); 932 933 if (vp == &line_num) { 934 if (name[vp->name_len] == '=') 935 funclinebase = funclineabs -1; 936 else 937 funclinebase = 0; 938 } 939 } 940 } 941 lvp->vp = vp; 942 lvp->next = localvars; 943 localvars = lvp; 944 INTON; 945 } 946 947 948 /* 949 * Called after a function returns. 950 */ 951 952 void 953 poplocalvars(void) 954 { 955 struct localvar *lvp; 956 struct var *vp; 957 958 while ((lvp = localvars) != NULL) { 959 localvars = lvp->next; 960 vp = lvp->vp; 961 VTRACE(DBG_VARS, ("poplocalvar %s", vp ? vp->text : "-")); 962 if (vp == NULL) { /* $- saved */ 963 memcpy(optlist, lvp->text, sizeof_optlist); 964 ckfree(lvp->text); 965 optschanged(); 966 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 967 (void)unsetvar(vp->text, 0); 968 } else { 969 if (vp->func && (vp->flags & (VNOFUNC|VFUNCREF)) == 0) 970 (*vp->func)(lvp->text + vp->name_len + 1); 971 if ((vp->flags & VTEXTFIXED) == 0) 972 ckfree(vp->text); 973 vp->flags = lvp->flags; 974 vp->text = lvp->text; 975 } 976 ckfree(lvp); 977 } 978 } 979 980 981 int 982 setvarcmd(int argc, char **argv) 983 { 984 if (argc <= 2) 985 return unsetcmd(argc, argv); 986 else if (argc == 3) 987 setvar(argv[1], argv[2], 0); 988 else 989 error("List assignment not implemented"); 990 return 0; 991 } 992 993 994 /* 995 * The unset builtin command. We unset the function before we unset the 996 * variable to allow a function to be unset when there is a readonly variable 997 * with the same name. 998 */ 999 1000 int 1001 unsetcmd(int argc, char **argv) 1002 { 1003 char **ap; 1004 int i; 1005 int flg_func = 0; 1006 int flg_var = 0; 1007 int flg_x = 0; 1008 int ret = 0; 1009 1010 while ((i = nextopt("efvx")) != '\0') { 1011 switch (i) { 1012 case 'f': 1013 flg_func = 1; 1014 break; 1015 case 'e': 1016 case 'x': 1017 flg_x = (2 >> (i == 'e')); 1018 /* FALLTHROUGH */ 1019 case 'v': 1020 flg_var = 1; 1021 break; 1022 } 1023 } 1024 1025 if (flg_func == 0 && flg_var == 0) 1026 flg_var = 1; 1027 1028 for (ap = argptr; *ap ; ap++) { 1029 if (flg_func) 1030 ret |= unsetfunc(*ap); 1031 if (flg_var) 1032 ret |= unsetvar(*ap, flg_x); 1033 } 1034 return ret; 1035 } 1036 1037 1038 /* 1039 * Unset the specified variable. 1040 */ 1041 1042 int 1043 unsetvar(const char *s, int unexport) 1044 { 1045 struct var **vpp; 1046 struct var *vp; 1047 1048 vp = find_var(s, &vpp, NULL); 1049 if (vp == NULL) 1050 return 0; 1051 1052 if (vp->flags & VREADONLY && !(unexport & 1)) 1053 return 1; 1054 1055 INTOFF; 1056 if (unexport & 1) { 1057 vp->flags &= ~VEXPORT; 1058 } else { 1059 if (vp->text[vp->name_len + 1] != '\0') 1060 setvar(s, nullstr, 0); 1061 if (!(unexport & 2)) 1062 vp->flags &= ~VEXPORT; 1063 vp->flags |= VUNSET; 1064 if ((vp->flags&(VEXPORT|VSTRFIXED|VREADONLY|VNOEXPORT)) == 0) { 1065 if ((vp->flags & VTEXTFIXED) == 0) 1066 ckfree(vp->text); 1067 *vpp = vp->next; 1068 ckfree(vp); 1069 } 1070 } 1071 INTON; 1072 return 0; 1073 } 1074 1075 1076 /* 1077 * Returns true if the two strings specify the same varable. The first 1078 * variable name is terminated by '='; the second may be terminated by 1079 * either '=' or '\0'. 1080 */ 1081 1082 STATIC int 1083 strequal(const char *p, const char *q) 1084 { 1085 while (*p == *q++) { 1086 if (*p++ == '=') 1087 return 1; 1088 } 1089 if (*p == '=' && *(q - 1) == '\0') 1090 return 1; 1091 return 0; 1092 } 1093 1094 /* 1095 * Search for a variable. 1096 * 'name' may be terminated by '=' or a NUL. 1097 * vppp is set to the pointer to vp, or the list head if vp isn't found 1098 * lenp is set to the number of charactets in 'name' 1099 */ 1100 1101 STATIC struct var * 1102 find_var(const char *name, struct var ***vppp, int *lenp) 1103 { 1104 unsigned int hashval; 1105 int len; 1106 struct var *vp, **vpp; 1107 const char *p = name; 1108 1109 hashval = 0; 1110 while (*p && *p != '=') 1111 hashval = 2 * hashval + (unsigned char)*p++; 1112 len = p - name; 1113 1114 if (lenp) 1115 *lenp = len; 1116 vpp = &vartab[hashval % VTABSIZE]; 1117 if (vppp) 1118 *vppp = vpp; 1119 1120 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 1121 if (vp->name_len != len) 1122 continue; 1123 if (memcmp(vp->text, name, len) != 0) 1124 continue; 1125 if (vppp) 1126 *vppp = vpp; 1127 return vp; 1128 } 1129 return NULL; 1130 } 1131 1132 /* 1133 * The following are the functions that create the values for 1134 * shell variables that are dynamically produced when needed. 1135 * 1136 * The output strings cannot be malloc'd as there is nothing to 1137 * free them - callers assume these are ordinary variables where 1138 * the value returned is vp->text 1139 * 1140 * Each function needs its own storage space, as the results are 1141 * used to create processes' environment, and (if exported) all 1142 * the values will (might) be needed simultaneously. 1143 * 1144 * It is not a problem if a var is updated while nominally in use 1145 * somewhere, all these are intended to be dynamic, the value they 1146 * return is not guaranteed, an updated vaue is just as good. 1147 * 1148 * So, malloc a single buffer for the result of each function, 1149 * grow, and even shrink, it as needed, but once we have one that 1150 * is a suitable size for the actual usage, simply hold it forever. 1151 * 1152 * For a SMALL shell we implement only LINENO, none of the others, 1153 * and give it just a fixed length static buffer for its result. 1154 */ 1155 1156 #ifndef SMALL 1157 1158 struct space_reserved { /* record of space allocated for results */ 1159 char *b; 1160 int len; 1161 }; 1162 1163 /* rough (over-)estimate of the number of bytes needed to hold a number */ 1164 static int 1165 digits_in(intmax_t number) 1166 { 1167 int res = 0; 1168 1169 if (number & ~((1LL << 62) - 1)) 1170 res = 64; /* enough for 2^200 and a bit more */ 1171 else if (number & ~((1LL << 32) - 1)) 1172 res = 20; /* enough for 2^64 */ 1173 else if (number & ~((1 << 23) - 1)) 1174 res = 10; /* enough for 2^32 */ 1175 else 1176 res = 8; /* enough for 2^23 or smaller */ 1177 1178 return res; 1179 } 1180 1181 static int 1182 make_space(struct space_reserved *m, int bytes) 1183 { 1184 void *p; 1185 1186 if (m->len >= bytes && m->len <= (bytes<<2)) 1187 return 1; 1188 1189 bytes = SHELL_ALIGN(bytes); 1190 /* not ckrealloc() - we want failure, not error() here */ 1191 p = realloc(m->b, bytes); 1192 if (p == NULL) /* what we had should still be there */ 1193 return 0; 1194 1195 m->b = p; 1196 m->len = bytes; 1197 m->b[bytes - 1] = '\0'; 1198 1199 return 1; 1200 } 1201 #endif 1202 1203 char * 1204 get_lineno(struct var *vp) 1205 { 1206 #ifdef SMALL 1207 #define length (8 + 10) /* 10 digits is enough for a 32 bit line num */ 1208 static char result[length]; 1209 #else 1210 static struct space_reserved buf; 1211 #define result buf.b 1212 #define length buf.len 1213 #endif 1214 int ln = line_number; 1215 1216 if (vp->flags & VUNSET) 1217 return NULL; 1218 1219 ln -= funclinebase; 1220 1221 #ifndef SMALL 1222 if (!make_space(&buf, vp->name_len + 2 + digits_in(ln))) 1223 return vp->text; 1224 #endif 1225 1226 snprintf(result, length - 1, "%.*s=%d", vp->name_len, vp->text, ln); 1227 return result; 1228 } 1229 #undef result 1230 #undef length 1231 1232 #ifndef SMALL 1233 1234 char * 1235 get_hostname(struct var *vp) 1236 { 1237 static struct space_reserved buf; 1238 1239 if (vp->flags & VUNSET) 1240 return NULL; 1241 1242 if (!make_space(&buf, vp->name_len + 2 + 256)) 1243 return vp->text; 1244 1245 memcpy(buf.b, vp->text, vp->name_len + 1); /* include '=' */ 1246 (void)gethostname(buf.b + vp->name_len + 1, 1247 buf.len - vp->name_len - 3); 1248 return buf.b; 1249 } 1250 1251 char * 1252 get_tod(struct var *vp) 1253 { 1254 static struct space_reserved buf; /* space for answers */ 1255 static struct space_reserved tzs; /* remember TZ last used */ 1256 static timezone_t last_zone; /* timezone data for tzs zone */ 1257 const char *fmt; 1258 char *tz; 1259 time_t now; 1260 struct tm tm_now, *tmp; 1261 timezone_t zone = NULL; 1262 static char t_err[] = "time error"; 1263 int len; 1264 1265 if (vp->flags & VUNSET) 1266 return NULL; 1267 1268 fmt = lookupvar("ToD_FORMAT"); 1269 if (fmt == NULL) 1270 fmt="%T"; 1271 tz = lookupvar("TZ"); 1272 (void)time(&now); 1273 1274 if (tz != NULL) { 1275 if (tzs.b == NULL || strcmp(tzs.b, tz) != 0) { 1276 if (make_space(&tzs, strlen(tz) + 1)) { 1277 INTOFF; 1278 strcpy(tzs.b, tz); 1279 if (last_zone) 1280 tzfree(last_zone); 1281 last_zone = zone = tzalloc(tz); 1282 INTON; 1283 } else 1284 zone = tzalloc(tz); 1285 } else 1286 zone = last_zone; 1287 1288 tmp = localtime_rz(zone, &now, &tm_now); 1289 } else 1290 tmp = localtime_r(&now, &tm_now); 1291 1292 len = (strlen(fmt) * 4) + vp->name_len + 2; 1293 while (make_space(&buf, len)) { 1294 memcpy(buf.b, vp->text, vp->name_len+1); 1295 if (tmp == NULL) { 1296 if (buf.len >= vp->name_len+2+(int)(sizeof t_err - 1)) { 1297 strcpy(buf.b + vp->name_len + 1, t_err); 1298 if (zone && zone != last_zone) 1299 tzfree(zone); 1300 return buf.b; 1301 } 1302 len = vp->name_len + 4 + sizeof t_err - 1; 1303 continue; 1304 } 1305 if (strftime_z(zone, buf.b + vp->name_len + 1, 1306 buf.len - vp->name_len - 2, fmt, tmp)) { 1307 if (zone && zone != last_zone) 1308 tzfree(zone); 1309 return buf.b; 1310 } 1311 if (len >= 4096) /* Let's be reasonable */ 1312 break; 1313 len <<= 1; 1314 } 1315 if (zone && zone != last_zone) 1316 tzfree(zone); 1317 return vp->text; 1318 } 1319 1320 char * 1321 get_seconds(struct var *vp) 1322 { 1323 static struct space_reserved buf; 1324 intmax_t secs; 1325 1326 if (vp->flags & VUNSET) 1327 return NULL; 1328 1329 secs = (intmax_t)time((time_t *)0) - sh_start_time; 1330 if (!make_space(&buf, vp->name_len + 2 + digits_in(secs))) 1331 return vp->text; 1332 1333 snprintf(buf.b, buf.len-1, "%.*s=%jd", vp->name_len, vp->text, secs); 1334 return buf.b; 1335 } 1336 1337 char * 1338 get_euser(struct var *vp) 1339 { 1340 static struct space_reserved buf; 1341 static uid_t lastuid = 0; 1342 uid_t euid; 1343 struct passwd *pw; 1344 1345 if (vp->flags & VUNSET) 1346 return NULL; 1347 1348 euid = geteuid(); 1349 if (buf.b != NULL && lastuid == euid) 1350 return buf.b; 1351 1352 pw = getpwuid(euid); 1353 if (pw == NULL) 1354 return vp->text; 1355 1356 if (make_space(&buf, vp->name_len + 2 + strlen(pw->pw_name))) { 1357 lastuid = euid; 1358 snprintf(buf.b, buf.len, "%.*s=%s", vp->name_len, vp->text, 1359 pw->pw_name); 1360 return buf.b; 1361 } 1362 1363 return vp->text; 1364 } 1365 1366 char * 1367 get_random(struct var *vp) 1368 { 1369 static struct space_reserved buf; 1370 static intmax_t random_val = 0; 1371 1372 #ifdef USE_LRAND48 1373 #define random lrand48 1374 #define srandom srand48 1375 #endif 1376 1377 if (vp->flags & VUNSET) 1378 return NULL; 1379 1380 if (vp->text != buf.b) { 1381 /* 1382 * Either initialisation, or a new seed has been set 1383 */ 1384 if (vp->text[vp->name_len + 1] == '\0') { 1385 int fd; 1386 1387 /* 1388 * initialisation (without pre-seeding), 1389 * or explictly requesting a truly random seed. 1390 */ 1391 fd = open("/dev/urandom", 0); 1392 if (fd == -1) { 1393 out2str("RANDOM initialisation failed\n"); 1394 random_val = (getpid()<<3) ^ time((time_t *)0); 1395 } else { 1396 int n; 1397 1398 do { 1399 n = read(fd,&random_val,sizeof random_val); 1400 } while (n != sizeof random_val); 1401 close(fd); 1402 } 1403 } else 1404 /* good enough for today */ 1405 random_val = atoi(vp->text + vp->name_len + 1); 1406 1407 srandom((long)random_val); 1408 } 1409 1410 #if 0 1411 random_val = (random_val + 1) & 0x7FFF; /* 15 bit "random" numbers */ 1412 #else 1413 random_val = (random() >> 5) & 0x7FFF; 1414 #endif 1415 1416 if (!make_space(&buf, vp->name_len + 2 + digits_in(random_val))) 1417 return vp->text; 1418 1419 snprintf(buf.b, buf.len-1, "%.*s=%jd", vp->name_len, vp->text, 1420 random_val); 1421 1422 if (buf.b != vp->text && (vp->flags & (VTEXTFIXED|VSTACK)) == 0) 1423 free(vp->text); 1424 vp->flags |= VTEXTFIXED; 1425 vp->text = buf.b; 1426 1427 return vp->text; 1428 #undef random 1429 #undef srandom 1430 } 1431 1432 #endif /* SMALL */ 1433