1 /* $NetBSD: var.c,v 1.69 2017/11/19 03:23:01 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.69 2017/11/19 03:23:01 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 * Validate a string as a valid variable name 335 * nb: not parameter - special params and such are "invalid" here. 336 * Name terminated by either \0 or the term param (usually '=' or '\0'). 337 * 338 * If not NULL, the length of the (intended) name is returned via len 339 */ 340 341 int 342 validname(const char *name, int term, int *len) 343 { 344 const char *p = name; 345 int ok = 1; 346 347 if (p == NULL || *p == '\0' || *p == term) { 348 if (len != NULL) 349 *len = 0; 350 return 0; 351 } 352 353 if (!is_name(*p)) 354 ok = 0; 355 p++; 356 for (;;) { 357 if (*p == '\0' || *p == term) 358 break; 359 if (!is_in_name(*p)) 360 ok = 0; 361 p++; 362 } 363 if (len != NULL) 364 *len = p - name; 365 366 return ok; 367 } 368 369 /* 370 * Safe version of setvar, returns 1 on success 0 on failure. 371 */ 372 373 int 374 setvarsafe(const char *name, const char *val, int flags) 375 { 376 struct jmploc jmploc; 377 struct jmploc * const savehandler = handler; 378 int volatile err = 0; 379 380 if (setjmp(jmploc.loc)) 381 err = 1; 382 else { 383 handler = &jmploc; 384 setvar(name, val, flags); 385 } 386 handler = savehandler; 387 return err; 388 } 389 390 /* 391 * Set the value of a variable. The flags argument is ored with the 392 * flags of the variable. If val is NULL, the variable is unset. 393 * 394 * This always copies name and val when setting a variable, so 395 * the source strings can be from anywhere, and are no longer needed 396 * after this function returns. The VTEXTFIXED and VSTACK flags should 397 * not be used (but just in case they were, clear them.) 398 */ 399 400 void 401 setvar(const char *name, const char *val, int flags) 402 { 403 const char *p; 404 const char *q; 405 char *d; 406 int len; 407 int namelen; 408 char *nameeq; 409 410 p = name; 411 412 if (!validname(p, '=', &namelen)) 413 error("%.*s: bad variable name", namelen, name); 414 len = namelen + 2; /* 2 is space for '=' and '\0' */ 415 if (val == NULL) { 416 flags |= VUNSET; 417 } else { 418 len += strlen(val); 419 } 420 d = nameeq = ckmalloc(len); 421 q = name; 422 while (--namelen >= 0) 423 *d++ = *q++; 424 *d++ = '='; 425 *d = '\0'; 426 if (val) 427 scopy(val, d); 428 setvareq(nameeq, flags & ~(VTEXTFIXED | VSTACK)); 429 } 430 431 432 433 /* 434 * Same as setvar except that the variable and value are passed in 435 * the first argument as name=value. Since the first argument will 436 * be actually stored in the table, it should not be a string that 437 * will go away. The flags (VTEXTFIXED or VSTACK) can be used to 438 * indicate the source of the string (if neither is set, the string will 439 * eventually be free()d when a replacement value is assigned.) 440 */ 441 442 void 443 setvareq(char *s, int flags) 444 { 445 struct var *vp, **vpp; 446 int nlen; 447 448 VTRACE(DBG_VARS, ("setvareq([%s],%#x) aflag=%d ", s, flags, aflag)); 449 if (aflag && !(flags & VNOEXPORT)) 450 flags |= VEXPORT; 451 vp = find_var(s, &vpp, &nlen); 452 if (vp != NULL) { 453 VTRACE(DBG_VARS, ("was [%s] fl:%#x\n", vp->text, 454 vp->flags)); 455 if (vp->flags & VREADONLY) { 456 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 457 ckfree(s); 458 if (flags & VNOERROR) 459 return; 460 error("%.*s: is read only", vp->name_len, vp->text); 461 } 462 if (flags & VNOSET) { 463 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 464 ckfree(s); 465 return; 466 } 467 468 INTOFF; 469 470 if (vp->func && !(vp->flags & VFUNCREF) && !(flags & VNOFUNC)) 471 (*vp->func)(s + vp->name_len + 1); 472 473 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 474 ckfree(vp->text); 475 476 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); 477 if (flags & VNOEXPORT) 478 vp->flags &= ~VEXPORT; 479 if (vp->flags & VNOEXPORT) 480 flags &= ~VEXPORT; 481 vp->flags |= flags & ~VNOFUNC; 482 vp->text = s; 483 484 /* 485 * We could roll this to a function, to handle it as 486 * a regular variable function callback, but why bother? 487 */ 488 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 489 chkmail(1); 490 491 INTON; 492 return; 493 } 494 VTRACE(DBG_VARS, ("new\n")); 495 /* not found */ 496 if (flags & VNOSET) { 497 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 498 ckfree(s); 499 return; 500 } 501 vp = ckmalloc(sizeof (*vp)); 502 vp->flags = flags & ~(VNOFUNC|VFUNCREF); 503 vp->text = s; 504 vp->name_len = nlen; 505 vp->next = *vpp; 506 vp->func = NULL; 507 *vpp = vp; 508 } 509 510 511 512 /* 513 * Process a linked list of variable assignments. 514 */ 515 516 void 517 listsetvar(struct strlist *list, int flags) 518 { 519 struct strlist *lp; 520 521 INTOFF; 522 for (lp = list ; lp ; lp = lp->next) { 523 setvareq(savestr(lp->text), flags); 524 } 525 INTON; 526 } 527 528 void 529 listmklocal(struct strlist *list, int flags) 530 { 531 struct strlist *lp; 532 533 for (lp = list ; lp ; lp = lp->next) 534 mklocal(lp->text, flags); 535 } 536 537 538 /* 539 * Find the value of a variable. Returns NULL if not set. 540 */ 541 542 char * 543 lookupvar(const char *name) 544 { 545 struct var *v; 546 547 v = find_var(name, NULL, NULL); 548 if (v == NULL || v->flags & VUNSET) 549 return NULL; 550 if (v->rfunc && (v->flags & VFUNCREF) != 0) 551 return (*v->rfunc)(v) + v->name_len + 1; 552 return v->text + v->name_len + 1; 553 } 554 555 556 557 /* 558 * Search the environment of a builtin command. If the second argument 559 * is nonzero, return the value of a variable even if it hasn't been 560 * exported. 561 */ 562 563 char * 564 bltinlookup(const char *name, int doall) 565 { 566 struct strlist *sp; 567 struct var *v; 568 569 for (sp = cmdenviron ; sp ; sp = sp->next) { 570 if (strequal(sp->text, name)) 571 return strchr(sp->text, '=') + 1; 572 } 573 574 v = find_var(name, NULL, NULL); 575 576 if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) 577 return NULL; 578 if (v->rfunc && (v->flags & VFUNCREF) != 0) 579 return (*v->rfunc)(v) + v->name_len + 1; 580 return v->text + v->name_len + 1; 581 } 582 583 584 585 /* 586 * Generate a list of exported variables. This routine is used to construct 587 * the third argument to execve when executing a program. 588 */ 589 590 char ** 591 environment(void) 592 { 593 int nenv; 594 struct var **vpp; 595 struct var *vp; 596 char **env; 597 char **ep; 598 599 nenv = 0; 600 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 601 for (vp = *vpp ; vp ; vp = vp->next) 602 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) 603 nenv++; 604 } 605 CTRACE(DBG_VARS, ("environment: %d vars to export\n", nenv)); 606 ep = env = stalloc((nenv + 1) * sizeof *env); 607 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 608 for (vp = *vpp ; vp ; vp = vp->next) 609 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) { 610 if (vp->rfunc && (vp->flags & VFUNCREF)) 611 *ep++ = (*vp->rfunc)(vp); 612 else 613 *ep++ = vp->text; 614 VTRACE(DBG_VARS, ("environment: %s\n", ep[-1])); 615 } 616 } 617 *ep = NULL; 618 return env; 619 } 620 621 622 /* 623 * Called when a shell procedure is invoked to clear out nonexported 624 * variables. It is also necessary to reallocate variables of with 625 * VSTACK set since these are currently allocated on the stack. 626 */ 627 628 #ifdef mkinit 629 void shprocvar(void); 630 631 SHELLPROC { 632 shprocvar(); 633 } 634 #endif 635 636 void 637 shprocvar(void) 638 { 639 struct var **vpp; 640 struct var *vp, **prev; 641 642 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 643 for (prev = vpp ; (vp = *prev) != NULL ; ) { 644 if ((vp->flags & VEXPORT) == 0) { 645 *prev = vp->next; 646 if ((vp->flags & VTEXTFIXED) == 0) 647 ckfree(vp->text); 648 if ((vp->flags & VSTRFIXED) == 0) 649 ckfree(vp); 650 } else { 651 if (vp->flags & VSTACK) { 652 vp->text = savestr(vp->text); 653 vp->flags &=~ VSTACK; 654 } 655 prev = &vp->next; 656 } 657 } 658 } 659 initvar(); 660 } 661 662 663 664 /* 665 * Command to list all variables which are set. Currently this command 666 * is invoked from the set command when the set command is called without 667 * any variables. 668 */ 669 670 void 671 print_quoted(const char *p) 672 { 673 const char *q; 674 675 if (p[0] == '\0') { 676 out1fmt("''"); 677 return; 678 } 679 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 680 out1fmt("%s", p); 681 return; 682 } 683 while (*p) { 684 if (*p == '\'') { 685 out1fmt("\\'"); 686 p++; 687 continue; 688 } 689 q = strchr(p, '\''); 690 if (!q) { 691 out1fmt("'%s'", p ); 692 return; 693 } 694 out1fmt("'%.*s'", (int)(q - p), p ); 695 p = q; 696 } 697 } 698 699 static int 700 sort_var(const void *v_v1, const void *v_v2) 701 { 702 const struct var * const *v1 = v_v1; 703 const struct var * const *v2 = v_v2; 704 char *t1 = (*v1)->text, *t2 = (*v2)->text; 705 706 if (*t1 == *t2) { 707 char *p, *s; 708 709 STARTSTACKSTR(p); 710 711 /* 712 * note: if lengths are equal, strings must be different 713 * so we don't care which string we pick for the \0 in 714 * that case. 715 */ 716 if ((strchr(t1, '=') - t1) <= (strchr(t2, '=') - t2)) { 717 s = t1; 718 t1 = p; 719 } else { 720 s = t2; 721 t2 = p; 722 } 723 724 while (*s && *s != '=') { 725 STPUTC(*s, p); 726 s++; 727 } 728 STPUTC('\0', p); 729 } 730 731 return strcoll(t1, t2); 732 } 733 734 /* 735 * POSIX requires that 'set' (but not export or readonly) output the 736 * variables in lexicographic order - by the locale's collating order (sigh). 737 * Maybe we could keep them in an ordered balanced binary tree 738 * instead of hashed lists. 739 * For now just roll 'em through qsort for printing... 740 */ 741 742 int 743 showvars(const char *name, int flag, int show_value, const char *xtra) 744 { 745 struct var **vpp; 746 struct var *vp; 747 const char *p; 748 749 static struct var **list; /* static in case we are interrupted */ 750 static int list_len; 751 int count = 0; 752 753 if (!list) { 754 list_len = 32; 755 list = ckmalloc(list_len * sizeof *list); 756 } 757 758 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 759 for (vp = *vpp ; vp ; vp = vp->next) { 760 if (flag && !(vp->flags & flag)) 761 continue; 762 if (vp->flags & VUNSET && !(show_value & 2)) 763 continue; 764 if (count >= list_len) { 765 list = ckrealloc(list, 766 (list_len << 1) * sizeof *list); 767 list_len <<= 1; 768 } 769 list[count++] = vp; 770 } 771 } 772 773 qsort(list, count, sizeof *list, sort_var); 774 775 for (vpp = list; count--; vpp++) { 776 vp = *vpp; 777 if (name) 778 out1fmt("%s ", name); 779 if (xtra) 780 out1fmt("%s ", xtra); 781 p = vp->text; 782 if (vp->rfunc && (vp->flags & VFUNCREF) != 0) { 783 p = (*vp->rfunc)(vp); 784 if (p == NULL) 785 p = vp->text; 786 } 787 for ( ; *p != '=' ; p++) 788 out1c(*p); 789 if (!(vp->flags & VUNSET) && show_value) { 790 out1fmt("="); 791 print_quoted(++p); 792 } 793 out1c('\n'); 794 } 795 return 0; 796 } 797 798 799 800 /* 801 * The export and readonly commands. 802 */ 803 804 int 805 exportcmd(int argc, char **argv) 806 { 807 struct var *vp; 808 char *name; 809 const char *p; 810 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 811 int pflg = 0; 812 int nflg = 0; 813 int xflg = 0; 814 int res; 815 int c; 816 int f; 817 818 while ((c = nextopt("npx")) != '\0') { 819 switch (c) { 820 case 'p': 821 if (nflg) 822 return 1; 823 pflg = 3; 824 break; 825 case 'n': 826 if (pflg || xflg || flag == VREADONLY) 827 return 1; 828 nflg = 1; 829 break; 830 case 'x': 831 if (nflg || flag == VREADONLY) 832 return 1; 833 flag = VNOEXPORT; 834 xflg = 1; 835 break; 836 default: 837 return 1; 838 } 839 } 840 841 if (nflg && *argptr == NULL) 842 return 1; 843 844 if (pflg || *argptr == NULL) { 845 showvars( pflg ? argv[0] : 0, flag, pflg, 846 pflg && xflg ? "-x" : NULL ); 847 return 0; 848 } 849 850 res = 0; 851 while ((name = *argptr++) != NULL) { 852 f = flag; 853 if ((p = strchr(name, '=')) != NULL) { 854 p++; 855 } else { 856 vp = find_var(name, NULL, NULL); 857 if (vp != NULL) { 858 if (nflg) 859 vp->flags &= ~flag; 860 else if (flag&VEXPORT && vp->flags&VNOEXPORT) 861 res = 1; 862 else { 863 vp->flags |= flag; 864 if (flag == VNOEXPORT) 865 vp->flags &= ~VEXPORT; 866 } 867 continue; 868 } else 869 f |= VUNSET; 870 } 871 if (!nflg) 872 setvar(name, p, f); 873 } 874 return res; 875 } 876 877 878 /* 879 * The "local" command. 880 */ 881 882 int 883 localcmd(int argc, char **argv) 884 { 885 char *name; 886 int c; 887 int flags = 0; /*XXX perhaps VUNSET from a -o option value */ 888 889 if (! in_function()) 890 error("Not in a function"); 891 892 /* upper case options, as bash stole all the good ones ... */ 893 while ((c = nextopt("INx")) != '\0') 894 switch (c) { 895 case 'I': flags &= ~VUNSET; break; 896 case 'N': flags |= VUNSET; break; 897 case 'x': flags |= VEXPORT; break; 898 } 899 900 while ((name = *argptr++) != NULL) { 901 mklocal(name, flags); 902 } 903 return 0; 904 } 905 906 907 /* 908 * Make a variable a local variable. When a variable is made local, its 909 * value and flags are saved in a localvar structure. The saved values 910 * will be restored when the shell function returns. We handle the name 911 * "-" as a special case. 912 */ 913 914 void 915 mklocal(const char *name, int flags) 916 { 917 struct localvar *lvp; 918 struct var **vpp; 919 struct var *vp; 920 921 INTOFF; 922 lvp = ckmalloc(sizeof (struct localvar)); 923 if (name[0] == '-' && name[1] == '\0') { 924 char *p; 925 p = ckmalloc(sizeof_optlist); 926 lvp->text = memcpy(p, optlist, sizeof_optlist); 927 vp = NULL; 928 xtrace_clone(0); 929 } else { 930 vp = find_var(name, &vpp, NULL); 931 if (vp == NULL) { 932 flags &= ~VNOEXPORT; 933 if (strchr(name, '=')) 934 setvareq(savestr(name), 935 VSTRFIXED | (flags & ~VUNSET)); 936 else 937 setvar(name, NULL, VSTRFIXED|flags); 938 vp = *vpp; /* the new variable */ 939 lvp->text = NULL; 940 lvp->flags = VUNSET; 941 } else { 942 lvp->text = vp->text; 943 lvp->flags = vp->flags; 944 vp->flags |= VSTRFIXED|VTEXTFIXED; 945 if (vp->flags & VNOEXPORT) 946 flags &= ~VEXPORT; 947 if (flags & (VNOEXPORT | VUNSET)) 948 vp->flags &= ~VEXPORT; 949 flags &= ~VNOEXPORT; 950 if (name[vp->name_len] == '=') 951 setvareq(savestr(name), flags & ~VUNSET); 952 else if (flags & VUNSET) 953 unsetvar(name, 0); 954 else 955 vp->flags |= flags & (VUNSET|VEXPORT); 956 957 if (vp == &line_num) { 958 if (name[vp->name_len] == '=') 959 funclinebase = funclineabs -1; 960 else 961 funclinebase = 0; 962 } 963 } 964 } 965 lvp->vp = vp; 966 lvp->next = localvars; 967 localvars = lvp; 968 INTON; 969 } 970 971 972 /* 973 * Called after a function returns. 974 */ 975 976 void 977 poplocalvars(void) 978 { 979 struct localvar *lvp; 980 struct var *vp; 981 982 while ((lvp = localvars) != NULL) { 983 localvars = lvp->next; 984 vp = lvp->vp; 985 VTRACE(DBG_VARS, ("poplocalvar %s", vp ? vp->text : "-")); 986 if (vp == NULL) { /* $- saved */ 987 memcpy(optlist, lvp->text, sizeof_optlist); 988 ckfree(lvp->text); 989 xtrace_pop(); 990 optschanged(); 991 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 992 (void)unsetvar(vp->text, 0); 993 } else { 994 if (vp->func && (vp->flags & (VNOFUNC|VFUNCREF)) == 0) 995 (*vp->func)(lvp->text + vp->name_len + 1); 996 if ((vp->flags & VTEXTFIXED) == 0) 997 ckfree(vp->text); 998 vp->flags = lvp->flags; 999 vp->text = lvp->text; 1000 } 1001 ckfree(lvp); 1002 } 1003 } 1004 1005 1006 int 1007 setvarcmd(int argc, char **argv) 1008 { 1009 if (argc <= 2) 1010 return unsetcmd(argc, argv); 1011 else if (argc == 3) 1012 setvar(argv[1], argv[2], 0); 1013 else 1014 error("List assignment not implemented"); 1015 return 0; 1016 } 1017 1018 1019 /* 1020 * The unset builtin command. We unset the function before we unset the 1021 * variable to allow a function to be unset when there is a readonly variable 1022 * with the same name. 1023 */ 1024 1025 int 1026 unsetcmd(int argc, char **argv) 1027 { 1028 char **ap; 1029 int i; 1030 int flg_func = 0; 1031 int flg_var = 0; 1032 int flg_x = 0; 1033 int ret = 0; 1034 1035 while ((i = nextopt("efvx")) != '\0') { 1036 switch (i) { 1037 case 'f': 1038 flg_func = 1; 1039 break; 1040 case 'e': 1041 case 'x': 1042 flg_x = (2 >> (i == 'e')); 1043 /* FALLTHROUGH */ 1044 case 'v': 1045 flg_var = 1; 1046 break; 1047 } 1048 } 1049 1050 if (flg_func == 0 && flg_var == 0) 1051 flg_var = 1; 1052 1053 for (ap = argptr; *ap ; ap++) { 1054 if (flg_func) 1055 ret |= unsetfunc(*ap); 1056 if (flg_var) 1057 ret |= unsetvar(*ap, flg_x); 1058 } 1059 return ret; 1060 } 1061 1062 1063 /* 1064 * Unset the specified variable. 1065 */ 1066 1067 int 1068 unsetvar(const char *s, int unexport) 1069 { 1070 struct var **vpp; 1071 struct var *vp; 1072 1073 vp = find_var(s, &vpp, NULL); 1074 if (vp == NULL) 1075 return 0; 1076 1077 if (vp->flags & VREADONLY && !(unexport & 1)) 1078 return 1; 1079 1080 INTOFF; 1081 if (unexport & 1) { 1082 vp->flags &= ~VEXPORT; 1083 } else { 1084 if (vp->text[vp->name_len + 1] != '\0') 1085 setvar(s, nullstr, 0); 1086 if (!(unexport & 2)) 1087 vp->flags &= ~VEXPORT; 1088 vp->flags |= VUNSET; 1089 if ((vp->flags&(VEXPORT|VSTRFIXED|VREADONLY|VNOEXPORT)) == 0) { 1090 if ((vp->flags & VTEXTFIXED) == 0) 1091 ckfree(vp->text); 1092 *vpp = vp->next; 1093 ckfree(vp); 1094 } 1095 } 1096 INTON; 1097 return 0; 1098 } 1099 1100 1101 /* 1102 * Returns true if the two strings specify the same varable. The first 1103 * variable name is terminated by '='; the second may be terminated by 1104 * either '=' or '\0'. 1105 */ 1106 1107 STATIC int 1108 strequal(const char *p, const char *q) 1109 { 1110 while (*p == *q++) { 1111 if (*p++ == '=') 1112 return 1; 1113 } 1114 if (*p == '=' && *(q - 1) == '\0') 1115 return 1; 1116 return 0; 1117 } 1118 1119 /* 1120 * Search for a variable. 1121 * 'name' may be terminated by '=' or a NUL. 1122 * vppp is set to the pointer to vp, or the list head if vp isn't found 1123 * lenp is set to the number of charactets in 'name' 1124 */ 1125 1126 STATIC struct var * 1127 find_var(const char *name, struct var ***vppp, int *lenp) 1128 { 1129 unsigned int hashval; 1130 int len; 1131 struct var *vp, **vpp; 1132 const char *p = name; 1133 1134 hashval = 0; 1135 while (*p && *p != '=') 1136 hashval = 2 * hashval + (unsigned char)*p++; 1137 len = p - name; 1138 1139 if (lenp) 1140 *lenp = len; 1141 vpp = &vartab[hashval % VTABSIZE]; 1142 if (vppp) 1143 *vppp = vpp; 1144 1145 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 1146 if (vp->name_len != len) 1147 continue; 1148 if (memcmp(vp->text, name, len) != 0) 1149 continue; 1150 if (vppp) 1151 *vppp = vpp; 1152 return vp; 1153 } 1154 return NULL; 1155 } 1156 1157 /* 1158 * The following are the functions that create the values for 1159 * shell variables that are dynamically produced when needed. 1160 * 1161 * The output strings cannot be malloc'd as there is nothing to 1162 * free them - callers assume these are ordinary variables where 1163 * the value returned is vp->text 1164 * 1165 * Each function needs its own storage space, as the results are 1166 * used to create processes' environment, and (if exported) all 1167 * the values will (might) be needed simultaneously. 1168 * 1169 * It is not a problem if a var is updated while nominally in use 1170 * somewhere, all these are intended to be dynamic, the value they 1171 * return is not guaranteed, an updated vaue is just as good. 1172 * 1173 * So, malloc a single buffer for the result of each function, 1174 * grow, and even shrink, it as needed, but once we have one that 1175 * is a suitable size for the actual usage, simply hold it forever. 1176 * 1177 * For a SMALL shell we implement only LINENO, none of the others, 1178 * and give it just a fixed length static buffer for its result. 1179 */ 1180 1181 #ifndef SMALL 1182 1183 struct space_reserved { /* record of space allocated for results */ 1184 char *b; 1185 int len; 1186 }; 1187 1188 /* rough (over-)estimate of the number of bytes needed to hold a number */ 1189 static int 1190 digits_in(intmax_t number) 1191 { 1192 int res = 0; 1193 1194 if (number & ~((1LL << 62) - 1)) 1195 res = 64; /* enough for 2^200 and a bit more */ 1196 else if (number & ~((1LL << 32) - 1)) 1197 res = 20; /* enough for 2^64 */ 1198 else if (number & ~((1 << 23) - 1)) 1199 res = 10; /* enough for 2^32 */ 1200 else 1201 res = 8; /* enough for 2^23 or smaller */ 1202 1203 return res; 1204 } 1205 1206 static int 1207 make_space(struct space_reserved *m, int bytes) 1208 { 1209 void *p; 1210 1211 if (m->len >= bytes && m->len <= (bytes<<2)) 1212 return 1; 1213 1214 bytes = SHELL_ALIGN(bytes); 1215 /* not ckrealloc() - we want failure, not error() here */ 1216 p = realloc(m->b, bytes); 1217 if (p == NULL) /* what we had should still be there */ 1218 return 0; 1219 1220 m->b = p; 1221 m->len = bytes; 1222 m->b[bytes - 1] = '\0'; 1223 1224 return 1; 1225 } 1226 #endif 1227 1228 char * 1229 get_lineno(struct var *vp) 1230 { 1231 #ifdef SMALL 1232 #define length (8 + 10) /* 10 digits is enough for a 32 bit line num */ 1233 static char result[length]; 1234 #else 1235 static struct space_reserved buf; 1236 #define result buf.b 1237 #define length buf.len 1238 #endif 1239 int ln = line_number; 1240 1241 if (vp->flags & VUNSET) 1242 return NULL; 1243 1244 ln -= funclinebase; 1245 1246 #ifndef SMALL 1247 if (!make_space(&buf, vp->name_len + 2 + digits_in(ln))) 1248 return vp->text; 1249 #endif 1250 1251 snprintf(result, length - 1, "%.*s=%d", vp->name_len, vp->text, ln); 1252 return result; 1253 } 1254 #undef result 1255 #undef length 1256 1257 #ifndef SMALL 1258 1259 char * 1260 get_hostname(struct var *vp) 1261 { 1262 static struct space_reserved buf; 1263 1264 if (vp->flags & VUNSET) 1265 return NULL; 1266 1267 if (!make_space(&buf, vp->name_len + 2 + 256)) 1268 return vp->text; 1269 1270 memcpy(buf.b, vp->text, vp->name_len + 1); /* include '=' */ 1271 (void)gethostname(buf.b + vp->name_len + 1, 1272 buf.len - vp->name_len - 3); 1273 return buf.b; 1274 } 1275 1276 char * 1277 get_tod(struct var *vp) 1278 { 1279 static struct space_reserved buf; /* space for answers */ 1280 static struct space_reserved tzs; /* remember TZ last used */ 1281 static timezone_t last_zone; /* timezone data for tzs zone */ 1282 const char *fmt; 1283 char *tz; 1284 time_t now; 1285 struct tm tm_now, *tmp; 1286 timezone_t zone = NULL; 1287 static char t_err[] = "time error"; 1288 int len; 1289 1290 if (vp->flags & VUNSET) 1291 return NULL; 1292 1293 fmt = lookupvar("ToD_FORMAT"); 1294 if (fmt == NULL) 1295 fmt="%T"; 1296 tz = lookupvar("TZ"); 1297 (void)time(&now); 1298 1299 if (tz != NULL) { 1300 if (tzs.b == NULL || strcmp(tzs.b, tz) != 0) { 1301 if (make_space(&tzs, strlen(tz) + 1)) { 1302 INTOFF; 1303 strcpy(tzs.b, tz); 1304 if (last_zone) 1305 tzfree(last_zone); 1306 last_zone = zone = tzalloc(tz); 1307 INTON; 1308 } else 1309 zone = tzalloc(tz); 1310 } else 1311 zone = last_zone; 1312 1313 tmp = localtime_rz(zone, &now, &tm_now); 1314 } else 1315 tmp = localtime_r(&now, &tm_now); 1316 1317 len = (strlen(fmt) * 4) + vp->name_len + 2; 1318 while (make_space(&buf, len)) { 1319 memcpy(buf.b, vp->text, vp->name_len+1); 1320 if (tmp == NULL) { 1321 if (buf.len >= vp->name_len+2+(int)(sizeof t_err - 1)) { 1322 strcpy(buf.b + vp->name_len + 1, t_err); 1323 if (zone && zone != last_zone) 1324 tzfree(zone); 1325 return buf.b; 1326 } 1327 len = vp->name_len + 4 + sizeof t_err - 1; 1328 continue; 1329 } 1330 if (strftime_z(zone, buf.b + vp->name_len + 1, 1331 buf.len - vp->name_len - 2, fmt, tmp)) { 1332 if (zone && zone != last_zone) 1333 tzfree(zone); 1334 return buf.b; 1335 } 1336 if (len >= 4096) /* Let's be reasonable */ 1337 break; 1338 len <<= 1; 1339 } 1340 if (zone && zone != last_zone) 1341 tzfree(zone); 1342 return vp->text; 1343 } 1344 1345 char * 1346 get_seconds(struct var *vp) 1347 { 1348 static struct space_reserved buf; 1349 intmax_t secs; 1350 1351 if (vp->flags & VUNSET) 1352 return NULL; 1353 1354 secs = (intmax_t)time((time_t *)0) - sh_start_time; 1355 if (!make_space(&buf, vp->name_len + 2 + digits_in(secs))) 1356 return vp->text; 1357 1358 snprintf(buf.b, buf.len-1, "%.*s=%jd", vp->name_len, vp->text, secs); 1359 return buf.b; 1360 } 1361 1362 char * 1363 get_euser(struct var *vp) 1364 { 1365 static struct space_reserved buf; 1366 static uid_t lastuid = 0; 1367 uid_t euid; 1368 struct passwd *pw; 1369 1370 if (vp->flags & VUNSET) 1371 return NULL; 1372 1373 euid = geteuid(); 1374 if (buf.b != NULL && lastuid == euid) 1375 return buf.b; 1376 1377 pw = getpwuid(euid); 1378 if (pw == NULL) 1379 return vp->text; 1380 1381 if (make_space(&buf, vp->name_len + 2 + strlen(pw->pw_name))) { 1382 lastuid = euid; 1383 snprintf(buf.b, buf.len, "%.*s=%s", vp->name_len, vp->text, 1384 pw->pw_name); 1385 return buf.b; 1386 } 1387 1388 return vp->text; 1389 } 1390 1391 char * 1392 get_random(struct var *vp) 1393 { 1394 static struct space_reserved buf; 1395 static intmax_t random_val = 0; 1396 1397 #ifdef USE_LRAND48 1398 #define random lrand48 1399 #define srandom srand48 1400 #endif 1401 1402 if (vp->flags & VUNSET) 1403 return NULL; 1404 1405 if (vp->text != buf.b) { 1406 /* 1407 * Either initialisation, or a new seed has been set 1408 */ 1409 if (vp->text[vp->name_len + 1] == '\0') { 1410 int fd; 1411 1412 /* 1413 * initialisation (without pre-seeding), 1414 * or explictly requesting a truly random seed. 1415 */ 1416 fd = open("/dev/urandom", 0); 1417 if (fd == -1) { 1418 out2str("RANDOM initialisation failed\n"); 1419 random_val = (getpid()<<3) ^ time((time_t *)0); 1420 } else { 1421 int n; 1422 1423 do { 1424 n = read(fd,&random_val,sizeof random_val); 1425 } while (n != sizeof random_val); 1426 close(fd); 1427 } 1428 } else 1429 /* good enough for today */ 1430 random_val = atoi(vp->text + vp->name_len + 1); 1431 1432 srandom((long)random_val); 1433 } 1434 1435 #if 0 1436 random_val = (random_val + 1) & 0x7FFF; /* 15 bit "random" numbers */ 1437 #else 1438 random_val = (random() >> 5) & 0x7FFF; 1439 #endif 1440 1441 if (!make_space(&buf, vp->name_len + 2 + digits_in(random_val))) 1442 return vp->text; 1443 1444 snprintf(buf.b, buf.len-1, "%.*s=%jd", vp->name_len, vp->text, 1445 random_val); 1446 1447 if (buf.b != vp->text && (vp->flags & (VTEXTFIXED|VSTACK)) == 0) 1448 free(vp->text); 1449 vp->flags |= VTEXTFIXED; 1450 vp->text = buf.b; 1451 1452 return vp->text; 1453 #undef random 1454 #undef srandom 1455 } 1456 1457 #endif /* SMALL */ 1458