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