1 /* $NetBSD: var.c,v 1.91 2026/05/28 10:07:58 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.91 2026/05/28 10:07:58 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 #ifndef SMALL 55 #include <locale.h> 56 #endif 57 58 /* 59 * Shell variables. 60 */ 61 62 #include "shell.h" 63 #include "output.h" 64 #include "expand.h" 65 #include "nodes.h" /* for other headers */ 66 #include "eval.h" /* defines cmdenviron */ 67 #include "exec.h" 68 #include "syntax.h" 69 #include "options.h" 70 #include "builtins.h" 71 #include "mail.h" 72 #include "var.h" 73 #include "memalloc.h" 74 #include "error.h" 75 #include "mystring.h" 76 #include "parser.h" 77 #include "show.h" 78 #include "machdep.h" 79 #ifndef SMALL 80 #include "myhistedit.h" 81 #endif 82 83 #ifdef SMALL 84 #define VTABSIZE 39 85 #else 86 #define VTABSIZE 517 87 #endif 88 89 90 struct varinit { 91 struct var *var; 92 int flags; 93 const char *text; 94 union var_func_union v_u; 95 }; 96 #define func v_u.set_func 97 #define rfunc v_u.ref_func 98 99 char *get_lineno(struct var *); 100 101 #ifndef SMALL 102 char *get_tod(struct var *); 103 char *get_hostname(struct var *); 104 char *get_seconds(struct var *); 105 char *get_euser(struct var *); 106 char *get_random(struct var *); 107 108 STATIC void set_locale_var(const char *, int, struct var *); 109 void init_locale_vars(void); 110 #endif 111 112 struct localvar *localvars; 113 114 #ifndef SMALL 115 struct var vhistsize; 116 struct var vhistfile; 117 struct var vhistappend; 118 struct var vterm; 119 struct var editrc; 120 struct var ps_lit; 121 #endif 122 struct var vifs; 123 struct var vmail; 124 struct var vmpath; 125 struct var vpath; 126 struct var vps1; 127 struct var vps2; 128 struct var vps4; 129 struct var vvers; 130 struct var voptind; 131 struct var line_num; 132 #ifndef SMALL 133 struct var tod; 134 struct var host_name; 135 struct var seconds; 136 struct var euname; 137 struct var random_num; 138 139 intmax_t sh_start_time; 140 141 struct var lc_all; 142 struct var lc_collate; 143 struct var lc_ctype; 144 struct var lc_messages; 145 struct var lc_monetary; 146 struct var lc_numeric; 147 struct var lc_time; 148 struct var lc_lang; 149 #endif 150 151 struct var line_num; 152 int line_number; 153 int funclinebase = 0; 154 int funclineabs = 0; 155 156 char ifs_default[] = " \t\n"; 157 158 const struct varinit varinit[] = { 159 #ifndef SMALL 160 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 161 { .set_func= sethistsize } }, 162 { &vhistfile, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE=", 163 { .set_func= sethistfile } }, 164 { &vhistappend, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTAPPEND=", 165 { .set_func= sethistappend } }, 166 #endif 167 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 168 { NULL } }, 169 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", 170 { NULL } }, 171 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 172 { NULL } }, 173 { &vvers, VSTRFIXED|VTEXTFIXED|VNOEXPORT, "NETBSD_SHELL=", 174 { NULL } }, 175 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, 176 { .set_func= changepath } }, 177 /* 178 * vps1 depends on uid 179 */ 180 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", 181 { NULL } }, 182 { &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 183 { NULL } }, 184 #ifndef SMALL 185 { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 186 { .set_func= setterm } }, 187 { &editrc, VSTRFIXED|VTEXTFIXED|VUNSET, "EDITRC=", 188 { .set_func= set_editrc } }, 189 { &ps_lit, VSTRFIXED|VTEXTFIXED|VUNSET, "PSlit=", 190 { .set_func= set_prompt_lit } }, 191 { &lc_all, VSTRFIXED|VTEXTFIXED|VUNSET|VFUNCPOST, "LC_ALL=", 192 { .set_func= set_locale_var } }, 193 { &lc_collate, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_COLLATE=", 194 { .set_func= set_locale_var } }, 195 { &lc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=", 196 { .set_func= set_locale_var } }, 197 { &lc_messages, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_MESSAGES=", 198 { .set_func= set_locale_var } }, 199 { &lc_monetary, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_MONETARY=", 200 { .set_func= set_locale_var } }, 201 { &lc_numeric, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_NUMERIC=", 202 { .set_func= set_locale_var } }, 203 { &lc_time, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_TIME=", 204 { .set_func= set_locale_var } }, 205 { &lc_lang, VSTRFIXED|VTEXTFIXED|VUNSET|VFUNCPOST, "LANG=", 206 { .set_func= set_locale_var } }, 207 #endif 208 { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", 209 { .set_func= getoptsreset } }, 210 { &line_num, VSTRFIXED|VTEXTFIXED|VFUNCREF|VSPECIAL, "LINENO=1", 211 { .ref_func= get_lineno } }, 212 #ifndef SMALL 213 { &tod, VSTRFIXED|VTEXTFIXED|VFUNCREF, "ToD=", 214 { .ref_func= get_tod } }, 215 { &host_name, VSTRFIXED|VTEXTFIXED|VFUNCREF, "HOSTNAME=", 216 { .ref_func= get_hostname } }, 217 { &seconds, VSTRFIXED|VTEXTFIXED|VFUNCREF, "SECONDS=", 218 { .ref_func= get_seconds } }, 219 { &euname, VSTRFIXED|VTEXTFIXED|VFUNCREF, "EUSER=", 220 { .ref_func= get_euser } }, 221 { &random_num, VSTRFIXED|VTEXTFIXED|VFUNCREF|VSPECIAL, "RANDOM=", 222 { .ref_func= get_random } }, 223 #endif 224 { NULL, 0, NULL, 225 { NULL } } 226 }; 227 228 struct var *vartab[VTABSIZE]; 229 230 STATIC int strequal(const char *, const char *); 231 STATIC struct var *find_var(const char *, struct var ***, int *); 232 STATIC void showvar(struct var *, const char *, const char *, int); 233 static void export_usage(const char *) __dead; 234 STATIC int makespecial(const char *); 235 236 /* 237 * Initialize the variable symbol tables and import the environment 238 */ 239 240 #ifdef mkinit 241 INCLUDE <stdio.h> 242 INCLUDE <unistd.h> 243 INCLUDE <time.h> 244 INCLUDE "var.h" 245 INCLUDE "version.h" 246 MKINIT char **environ; 247 MKINIT void setvareqsafe(char *, int); 248 MKINIT void init_locale_vars(void); 249 INIT { 250 char **envp; 251 char buf[64]; 252 253 #ifndef SMALL 254 sh_start_time = (intmax_t)time((time_t *)0); 255 #endif 256 /* 257 * Set up our default variables and their values. 258 */ 259 initvar(); 260 261 /* 262 * Import variables from the environment, which will 263 * if permitted, override anything initialised just previously. 264 */ 265 for (envp = environ ; *envp ; envp++) { 266 if (strchr(*envp, '=')) { 267 setvareqsafe(*envp, VEXPORT|VTEXTFIXED|VUNSAFE); 268 } 269 } 270 271 /* 272 * Set variables which override anything read from environment. 273 * 274 * PPID is readonly 275 * Always default IFS 276 * POSIX: "Whenever the shell is invoked, OPTIND shall 277 * be initialized to 1." 278 * PSc indicates the root/non-root status of this shell. 279 * START_TIME belongs only to this shell. 280 * NETBSD_SHELL is a constant (readonly), and is never exported 281 * LINENO is simply magic... 282 */ 283 snprintf(buf, sizeof(buf), "%d", (int)getppid()); 284 setvar("PPID", buf, VREADONLY); 285 setvar("IFS", ifs_default, VTEXTFIXED); 286 setvar("OPTIND", "1", VTEXTFIXED); 287 setvar("PSc", (geteuid() == 0 ? "#" : "$"), VTEXTFIXED); 288 289 #ifndef SMALL 290 snprintf(buf, sizeof(buf), "%jd", sh_start_time); 291 setvar("START_TIME", buf, VTEXTFIXED); 292 293 init_locale_vars(); 294 #endif 295 296 setvar("NETBSD_SHELL", NETBSD_SHELL 297 #ifdef BUILD_DATE 298 " BUILD:" BUILD_DATE 299 #endif 300 #ifdef DEBUG 301 " DEBUG" 302 #endif 303 #if !defined(JOBS) || JOBS == 0 304 " -JOBS" 305 #endif 306 #ifndef DO_SHAREDVFORK 307 " -VFORK" 308 #endif 309 #ifdef SMALL 310 " SMALL" 311 #endif 312 #ifdef TINY 313 " TINY" 314 #endif 315 #ifdef OLD_TTY_DRIVER 316 " OLD_TTY" 317 #endif 318 #ifdef SYSV 319 " SYSV" 320 #endif 321 #ifndef BSD 322 " -BSD" 323 #endif 324 #ifdef BOGUS_NOT_COMMAND 325 " BOGUS_NOT" 326 #endif 327 #ifdef REJECT_NULS 328 " REJECT_NULS" 329 #endif 330 #ifdef RESCUEDIR 331 " RESCUE" 332 #endif 333 , VTEXTFIXED|VREADONLY|VNOEXPORT); 334 335 setvar("LINENO", "1", VTEXTFIXED); 336 } 337 #endif 338 339 340 /* 341 * This routine initializes the builtin variables. It is called when the 342 * shell is initialized and again when a shell procedure is spawned. 343 */ 344 345 void 346 initvar(void) 347 { 348 const struct varinit *ip; 349 struct var *vp; 350 struct var **vpp; 351 352 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 353 if (find_var(ip->text, &vpp, &vp->name_len) != NULL) 354 continue; 355 vp->next = *vpp; 356 *vpp = vp; 357 vp->text = strdup(ip->text); 358 vp->flags = (ip->flags & ~VTEXTFIXED) | VSTRFIXED; 359 vp->v_u = ip->v_u; 360 } 361 /* 362 * PS1 depends on uid 363 */ 364 if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { 365 vps1.next = *vpp; 366 *vpp = &vps1; 367 vps1.flags = VSTRFIXED; 368 vps1.text = NULL; 369 choose_ps1(); 370 } 371 } 372 373 void 374 choose_ps1(void) 375 { 376 uid_t u = geteuid(); 377 378 if ((vps1.flags & (VTEXTFIXED|VSTACK)) == 0) 379 free(vps1.text); 380 vps1.text = strdup(u != 0 ? "PS1=$ " : "PS1=# "); 381 vps1.flags &= ~(VTEXTFIXED|VSTACK); 382 383 /* 384 * Update PSc whenever we feel the need to update PS1 385 */ 386 setvarsafe("PSc", (u == 0 ? "#" : "$"), 0); 387 } 388 389 /* 390 * Validate a string as a valid variable name 391 * nb: not parameter - special params and such are "invalid" here. 392 * Name terminated by either \0 or the term param (usually '=' or '\0'). 393 * 394 * If not NULL, the length of the (intended) name is returned via len 395 */ 396 397 int 398 validname(const char *name, int term, int *len) 399 { 400 const char *p = name; 401 int ok = 1; 402 403 if (p == NULL || *p == '\0' || *p == term) { 404 if (len != NULL) 405 *len = 0; 406 return 0; 407 } 408 409 if (!is_name(*p)) 410 ok = 0; 411 p++; 412 for (;;) { 413 if (*p == '\0' || *p == term) 414 break; 415 if (!is_in_name(*p)) 416 ok = 0; 417 p++; 418 } 419 if (len != NULL) 420 *len = p - name; 421 422 return ok; 423 } 424 425 /* 426 * Safe version of setvar, returns 1 on success 0 on failure. 427 */ 428 429 int 430 setvarsafe(const char *name, const char *val, int flags) 431 { 432 struct jmploc jmploc; 433 struct jmploc * const savehandler = handler; 434 int volatile err = 0; 435 436 if (setjmp(jmploc.loc)) 437 err = 1; 438 else { 439 handler = &jmploc; 440 setvar(name, val, flags); 441 } 442 handler = savehandler; 443 return err; 444 } 445 446 void 447 setvareqsafe(char *s, int flags) 448 { 449 struct jmploc jmploc; 450 struct jmploc * const savehandler = handler; 451 volatile int e_s = errors_suppressed; 452 453 if (!setjmp(jmploc.loc)) { 454 handler = &jmploc; 455 errors_suppressed = 1; 456 setvareq(s, flags); 457 } 458 handler = savehandler; 459 errors_suppressed = e_s; 460 } 461 462 /* 463 * Set the value of a variable. The flags argument is ored with the 464 * flags of the variable. If val is NULL, the variable is unset. 465 * 466 * This always copies name and val when setting a variable, so 467 * the source strings can be from anywhere, and are no longer needed 468 * after this function returns. The VTEXTFIXED and VSTACK flags should 469 * not be used (but just in case they were, clear them.) 470 */ 471 472 void 473 setvar(const char *name, const char *val, int flags) 474 { 475 const char *p; 476 const char *q; 477 char *d; 478 int len; 479 int namelen; 480 char *nameeq; 481 482 p = name; 483 484 if (!validname(p, '=', &namelen)) 485 error("%.*s: bad variable name", namelen, name); 486 len = namelen + 2; /* 2 is space for '=' and '\0' */ 487 if (val == NULL) { 488 flags |= VUNSET; 489 } else { 490 len += strlen(val); 491 } 492 d = nameeq = ckmalloc(len); 493 q = name; 494 while (--namelen >= 0) 495 *d++ = *q++; 496 *d++ = '='; 497 *d = '\0'; 498 if (val) 499 scopy(val, d); 500 setvareq(nameeq, flags & ~(VTEXTFIXED | VSTACK)); 501 } 502 503 504 505 /* 506 * Same as setvar except that the variable and value are passed in 507 * the first argument as name=value. Since the first argument will 508 * be actually stored in the table, it should not be a string that 509 * will go away. The flags (VTEXTFIXED or VSTACK) can be used to 510 * indicate the source of the string (if neither is set, the string will 511 * eventually be free()d when a replacement value is assigned.) 512 */ 513 514 void 515 setvareq(char *s, int flags) 516 { 517 struct var *vp, **vpp; 518 int nlen; 519 520 VTRACE(DBG_VARS, ("setvareq([%s],%#x) aflag=%d ", s, flags, aflag)); 521 if (aflag && !(flags & VNOEXPORT)) 522 flags |= VEXPORT; 523 vp = find_var(s, &vpp, &nlen); 524 if (vp != NULL) { 525 VTRACE(DBG_VARS, ("was [%s] fl:%#x\n", vp->text, 526 vp->flags)); 527 if (vp->flags & VREADONLY) { 528 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 529 ckfree(s); 530 if (flags & VNOERROR) 531 return; 532 error("%.*s: is read only", vp->name_len, vp->text); 533 } 534 if (flags & VNOSET) { 535 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 536 ckfree(s); 537 return; 538 } 539 540 INTOFF; 541 542 if (vp->func && !(vp->flags & (VFUNCREF|VFUNCPOST)) && 543 !(flags & VNOFUNC)) 544 (*vp->func)(s + vp->name_len + 1, flags, vp); 545 546 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) 547 ckfree(vp->text); 548 549 /* 550 * if we set a magic var, the magic dissipates, 551 * unless it is very special indeed. 552 */ 553 if (vp->rfunc && (vp->flags & (VFUNCREF|VSPECIAL)) == VFUNCREF) 554 vp->rfunc = NULL; 555 556 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET|VUNSAFE); 557 if (flags & VNOEXPORT) 558 vp->flags &= ~VEXPORT; 559 if (flags & VDOEXPORT) 560 vp->flags &= ~VNOEXPORT; 561 if (vp->flags & VNOEXPORT) 562 flags &= ~VEXPORT; 563 vp->flags |= flags & ~(VNOFUNC | VDOEXPORT); 564 vp->text = s; 565 566 if (vp->func && 567 (vp->flags & (VFUNCREF|VFUNCPOST)) == VFUNCPOST && 568 !(flags & VNOFUNC)) 569 (*vp->func)(s + vp->name_len + 1, flags, vp); 570 571 /* 572 * We could roll this to a function, to handle it as 573 * a regular variable function callback, but why bother? 574 */ 575 if (vp == &vmpath || (vp == &vmail && ! mpathset())) 576 chkmail(1); 577 578 INTON; 579 return; 580 } 581 /* not found */ 582 if (flags & VNOSET) { 583 VTRACE(DBG_VARS, ("new noset\n")); 584 if ((flags & (VTEXTFIXED|VSTACK)) == 0) 585 ckfree(s); 586 return; 587 } 588 vp = ckmalloc(sizeof (*vp)); 589 vp->flags = flags & ~(VNOFUNC|VFUNCREF|VDOEXPORT); 590 vp->text = s; 591 vp->name_len = nlen; 592 vp->func = NULL; 593 vp->next = *vpp; 594 *vpp = vp; 595 596 VTRACE(DBG_VARS, ("new [%s] (%d) %#x\n", s, nlen, vp->flags)); 597 } 598 599 void 600 setvar_invocation(int argc, char **argv) 601 { 602 char value[32]; /* if we ever get 30, HELP */ 603 char *v; 604 605 /* 606 * Keep the following in ascii lexical order ( ie: Z before a ) 607 */ 608 609 v = value; 610 *v++ = '!'; /* never empty, and the '-' is not first */ 611 612 if (argc > 0 && argv[0] != NULL && argv[0][0] == '-') 613 *v++ = '-'; 614 if (shellparam.nparam == 0) 615 *v++ = '0'; 616 if (minusc) 617 *v++ = 'c'; 618 if (commandname) 619 *v++ = 'f'; 620 if (iflag) 621 *v++ = 'i'; 622 if (loginsh) 623 *v++ = 'l'; 624 if (privileged) 625 *v++ = 'p'; 626 if (sflag) 627 *v++ = 's'; 628 629 *v++ = '\0'; 630 631 /* 632 * this cannot fail, the var name is OK, 633 * there cannot be any (non special) read only 634 * variables at this point, ... 635 */ 636 setvar("NBSH_INVOCATION", value, VNOEXPORT); 637 } 638 639 /* 640 * Process a linked list of variable assignments. 641 */ 642 643 void 644 listsetvar(struct strlist *list, int flags) 645 { 646 struct strlist *lp; 647 648 INTOFF; 649 for (lp = list ; lp ; lp = lp->next) { 650 setvareq(savestr(lp->text), flags); 651 } 652 INTON; 653 } 654 655 void 656 listmklocal(struct strlist *list, int flags) 657 { 658 struct strlist *lp; 659 660 for (lp = list ; lp ; lp = lp->next) 661 mklocal(lp->text, flags); 662 } 663 664 665 /* 666 * Find the value of a variable. Returns NULL if not set. 667 */ 668 669 char * 670 lookupvar(const char *name) 671 { 672 struct var *v; 673 char *p; 674 675 v = find_var(name, NULL, NULL); 676 if (v == NULL || v->flags & VUNSET) 677 return NULL; 678 if (v->rfunc && (v->flags & VFUNCREF) != 0) { 679 p = (*v->rfunc)(v); 680 if (p == NULL) 681 return NULL; 682 } else 683 p = v->text; 684 685 return p + v->name_len + 1; 686 } 687 688 689 690 /* 691 * Search the environment of a builtin command. If the second argument 692 * is nonzero, return the value of a variable even if it hasn't been 693 * exported. 694 */ 695 696 char * 697 bltinlookup(const char *name, int doall) 698 { 699 struct strlist *sp; 700 struct var *v; 701 char *p; 702 703 for (sp = cmdenviron ; sp ; sp = sp->next) { 704 if (strequal(sp->text, name)) 705 return strchr(sp->text, '=') + 1; 706 } 707 708 v = find_var(name, NULL, NULL); 709 710 if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) 711 return NULL; 712 713 if (v->rfunc && (v->flags & VFUNCREF) != 0) { 714 p = (*v->rfunc)(v); 715 if (p == NULL) 716 return NULL; 717 } else 718 p = v->text; 719 720 return p + v->name_len + 1; 721 } 722 723 724 725 /* 726 * Generate a list of exported variables. This routine is used to construct 727 * the third argument to execve when executing a program. 728 */ 729 730 char ** 731 environment(void) 732 { 733 int nenv; 734 struct var **vpp; 735 struct var *vp; 736 char **env; 737 char **ep; 738 739 nenv = 0; 740 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 741 for (vp = *vpp ; vp ; vp = vp->next) 742 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) 743 nenv++; 744 } 745 CTRACE(DBG_VARS, ("environment: %d vars to export\n", nenv)); 746 ep = env = stalloc((nenv + 1) * sizeof *env); 747 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 748 for (vp = *vpp ; vp ; vp = vp->next) 749 if ((vp->flags & (VEXPORT|VUNSET)) == VEXPORT) { 750 if (vp->rfunc && (vp->flags & VFUNCREF)) { 751 *ep = (*vp->rfunc)(vp); 752 if (*ep != NULL) 753 ep++; 754 } else 755 *ep++ = vp->text; 756 VTRACE(DBG_VARS, ("environment: %s\n", ep[-1])); 757 } 758 } 759 *ep = NULL; 760 return env; 761 } 762 763 764 /* 765 * Called when a shell procedure is invoked to clear out nonexported 766 * variables. It is also necessary to reallocate variables of with 767 * VSTACK set since these are currently allocated on the stack. 768 */ 769 770 #ifdef mkinit 771 void shprocvar(void); 772 773 SHELLPROC { 774 shprocvar(); 775 } 776 #endif 777 778 void 779 shprocvar(void) 780 { 781 struct var **vpp; 782 struct var *vp, **prev; 783 784 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 785 for (prev = vpp ; (vp = *prev) != NULL ; ) { 786 if ((vp->flags & VEXPORT) == 0) { 787 *prev = vp->next; 788 if ((vp->flags & VTEXTFIXED) == 0) 789 ckfree(vp->text); 790 if ((vp->flags & VSTRFIXED) == 0) 791 ckfree(vp); 792 } else { 793 if (vp->flags & VSTACK) { 794 vp->text = savestr(vp->text); 795 vp->flags &=~ VSTACK; 796 } 797 prev = &vp->next; 798 } 799 } 800 } 801 initvar(); 802 } 803 804 805 806 /* 807 * Command to list all variables which are set. Currently this command 808 * is invoked from the set command when the set command is called without 809 * any variables. 810 */ 811 812 void 813 print_quoted(const char *p) 814 { 815 const char *q; 816 817 if (p[0] == '\0') { 818 out1fmt("''"); 819 return; 820 } 821 if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { 822 out1fmt("%s", p); 823 return; 824 } 825 while (*p) { 826 if (*p == '\'') { 827 out1fmt("\\'"); 828 p++; 829 continue; 830 } 831 q = strchr(p, '\''); 832 if (!q) { 833 out1fmt("'%s'", p ); 834 return; 835 } 836 out1fmt("'%.*s'", (int)(q - p), p ); 837 p = q; 838 } 839 } 840 841 static int 842 sort_var(const void *v_v1, const void *v_v2) 843 { 844 const struct var * const *v1 = v_v1; 845 const struct var * const *v2 = v_v2; 846 char *t1 = (*v1)->text, *t2 = (*v2)->text; 847 848 /* 849 * Note that we really just want return strcoll(t1, t2) here 850 * but we can't do that, as the strings are '=' terminated, 851 * not \0 terminated (there is a \0 later) - and we must not 852 * alter them. This causes problems if v1 is "x0" and v2 "x" 853 * as those are actually "x0=" and "x=", and since '0' < '=' 854 * that causes x0 to sort ahead of x which is backwards. 855 * 856 * So we need to fix that - but it only matters when the 857 * one string is a substring of the other (if they differ 858 * before either ends, that difference will correctly order 859 * the strings). To avoid too much extra work, we use the 860 * fact that we know the strings are variable names. This 861 * means that they must contain at least 1 character, and 862 * the names can only be equal if the var structs are the 863 * same thing. 864 */ 865 866 if (__predict_false(*v1 == *v2)) /* same pointers */ 867 return 0; /* must be the same name */ 868 869 /* 870 * But only 1 name char is guaranteed, so we see if the two 871 * names have the same first char, if not, then strcoll() 872 * will work, and we just use it (makes sure the locale collating 873 * sequence is used, rather than simply comparing the bytes.) 874 * (nb: that strcoll() doesn't actually use locales on NetBSD 875 * is irrelevant.) 876 * 877 * If the first char is the same, then we must make sure that the 878 * shorter name is \0 terminated, so if the names happen to be 879 * equal to that point (the shorter is a substring of the longer) 880 * then then shorter will always compare less. 881 * 882 * We do that by copying the shorter to the stack, null terminating 883 * it, and comparing that copy to the longer name 884 */ 885 886 if (__predict_false(*t1 == *t2)) { 887 char *p, *s; 888 889 STARTSTACKSTR(p); 890 891 /* 892 * note: if lengths are equal, strings must be different 893 * so we don't care which string we pick for the \0 in 894 * that case (the comparison won't reach that far). 895 */ 896 if ((*v1)->name_len <= (*v2)->name_len) { 897 CHECKSTRSPACE((*v1)->name_len + 1, p); 898 s = t1; 899 t1 = p; 900 } else { 901 CHECKSTRSPACE((*v2)->name_len + 1, p); 902 s = t2; 903 t2 = p; 904 } 905 906 /* 907 * MUST use CHECKSTRSPACE() (above) and USTPUTC() here 908 * as STPUTC() may reallocate the buffer (p) which we 909 * already saved in t1 (or t2) above - leading to the 910 * strcoll() below looking at garbage. USTPUTC() is safe. 911 */ 912 while (*s && *s != '=') { 913 USTPUTC(*s, p); 914 s++; 915 } 916 USTPUTC('\0', p); 917 } 918 919 return strcoll(t1, t2); 920 } 921 922 /* 923 * POSIX requires that 'set' (but not export or readonly) output the 924 * variables in lexicographic order - by the locale's collating order (sigh). 925 * Maybe we could keep them in an ordered balanced binary tree 926 * instead of hashed lists. 927 * For now just roll 'em through qsort for printing... 928 */ 929 930 STATIC void 931 showvar(struct var *vp, const char *cmd, const char *xtra, int show_value) 932 { 933 const char *p; 934 935 p = vp->text; 936 if (vp->rfunc && (vp->flags & VFUNCREF) != 0) { 937 p = (*vp->rfunc)(vp); 938 if (p == NULL) { 939 if (!(show_value & 2)) 940 return; 941 p = vp->text; 942 show_value = 0; 943 } 944 } 945 if (cmd) 946 out1fmt("%s ", cmd); 947 if (xtra) 948 out1fmt("%s ", xtra); 949 for ( ; *p != '=' ; p++) 950 out1c(*p); 951 if (!(vp->flags & VUNSET) && show_value) { 952 out1fmt("="); 953 print_quoted(++p); 954 } 955 out1c('\n'); 956 } 957 958 int 959 showvars(const char *cmd, int flag, int show_value, const char *xtra) 960 { 961 struct var **vpp; 962 struct var *vp; 963 964 static struct var **list; /* static in case we are interrupted */ 965 static int list_len; 966 int count = 0; 967 968 if (!list) { 969 list_len = 32; 970 list = ckmalloc(list_len * sizeof *list); 971 } 972 973 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { 974 for (vp = *vpp ; vp ; vp = vp->next) { 975 if (flag && !(vp->flags & flag)) 976 continue; 977 if (vp->flags & VUNSET && !(show_value & 2)) 978 continue; 979 if (count >= list_len) { 980 list = ckrealloc(list, 981 (list_len << 1) * sizeof *list); 982 list_len <<= 1; 983 } 984 list[count++] = vp; 985 } 986 } 987 988 qsort(list, count, sizeof *list, sort_var); 989 990 for (vpp = list; count--; vpp++) 991 showvar(*vpp, cmd, xtra, show_value); 992 993 /* no free(list), will be used again next time ... */ 994 995 return 0; 996 } 997 998 999 1000 /* 1001 * The export and readonly commands. 1002 */ 1003 1004 static void __dead 1005 export_usage(const char *cmd) 1006 { 1007 #ifdef SMALL 1008 if (*cmd == 'r') 1009 error("Usage: %s [ -p | var[=val]... ]", cmd); 1010 else 1011 error("Usage: %s [ -p | [-n] var[=val]... ]", cmd); 1012 #else 1013 if (*cmd == 'r') 1014 error("Usage: %s [-p [var...] | -q var... | var[=val]... ]", cmd); 1015 else 1016 error( 1017 "Usage: %s [ -px [var...] | -q[x] var... | [-n|x] var[=val]... ]", 1018 cmd); 1019 #endif 1020 } 1021 1022 int 1023 exportcmd(int argc, char **argv) 1024 { 1025 struct var *vp; 1026 char *name; 1027 const char *p = argv[0]; 1028 int flag = p[0] == 'r'? VREADONLY : VEXPORT; 1029 int pflg = 0; 1030 int nflg = 0; 1031 #ifndef SMALL 1032 int xflg = 0; 1033 int qflg = 0; 1034 #endif 1035 int res; 1036 int c; 1037 int f; 1038 1039 #ifdef SMALL 1040 #define EXPORT_OPTS "np" 1041 #else 1042 #define EXPORT_OPTS "npqx" 1043 #endif 1044 1045 while ((c = nextopt(EXPORT_OPTS)) != '\0') { 1046 1047 #undef EXPORT_OPTS 1048 1049 switch (c) { 1050 case 'n': 1051 if (pflg || flag == VREADONLY 1052 #ifndef SMALL 1053 || qflg || xflg 1054 #endif 1055 ) 1056 export_usage(p); 1057 nflg = 1; 1058 break; 1059 case 'p': 1060 if (nflg 1061 #ifndef SMALL 1062 || qflg 1063 #endif 1064 ) 1065 export_usage(p); 1066 pflg = 3; 1067 break; 1068 #ifndef SMALL 1069 case 'q': 1070 if (nflg || pflg) 1071 export_usage(p); 1072 qflg = 1; 1073 break; 1074 case 'x': 1075 if (nflg || flag == VREADONLY) 1076 export_usage(p); 1077 flag = VNOEXPORT; 1078 xflg = 1; 1079 break; 1080 #endif 1081 } 1082 } 1083 1084 if ((nflg 1085 #ifndef SMALL 1086 || qflg 1087 #endif 1088 ) && *argptr == NULL) 1089 export_usage(p); 1090 1091 #ifndef SMALL 1092 if (pflg && *argptr != NULL) { 1093 while ((name = *argptr++) != NULL) { 1094 int len; 1095 1096 vp = find_var(name, NULL, &len); 1097 if (name[len] == '=') 1098 export_usage(p); 1099 if (!goodname(name)) 1100 error("%s: bad variable name", name); 1101 1102 if (vp && vp->flags & flag) 1103 showvar(vp, p, xflg ? "-x" : NULL, 1); 1104 } 1105 return 0; 1106 } 1107 #endif 1108 1109 if (pflg || *argptr == NULL) 1110 return showvars( pflg ? p : 0, flag, pflg, 1111 #ifndef SMALL 1112 pflg && xflg ? "-x" : 1113 #endif 1114 NULL ); 1115 1116 res = 0; 1117 #ifndef SMALL 1118 if (qflg) { 1119 while ((name = *argptr++) != NULL) { 1120 int len; 1121 1122 vp = find_var(name, NULL, &len); 1123 if (name[len] == '=') 1124 export_usage(p); 1125 if (!goodname(name)) 1126 error("%s: bad variable name", name); 1127 1128 if (vp == NULL || !(vp->flags & flag)) 1129 res = 1; 1130 } 1131 return res; 1132 } 1133 #endif 1134 1135 while ((name = *argptr++) != NULL) { 1136 int len; 1137 1138 f = flag; 1139 1140 vp = find_var(name, NULL, &len); 1141 p = name + len; 1142 if (*p++ != '=') 1143 p = NULL; 1144 1145 if (vp != NULL) { 1146 if (nflg) 1147 vp->flags &= ~flag; 1148 else if (flag&VEXPORT && vp->flags&VNOEXPORT) { 1149 /* note we go ahead and do any assignment */ 1150 sh_warnx("%.*s: not available for export", 1151 len, name); 1152 res = 1; 1153 } else { 1154 if (flag == VNOEXPORT) 1155 vp->flags &= ~VEXPORT; 1156 1157 /* if not NULL will be done in setvar below */ 1158 if (p == NULL) 1159 vp->flags |= flag; 1160 } 1161 if (p == NULL) 1162 continue; 1163 } else if (nflg && p == NULL && !goodname(name)) 1164 error("%s: bad variable name", name); 1165 1166 if (!nflg || p != NULL) 1167 setvar(name, p, f); 1168 } 1169 return res; 1170 } 1171 1172 1173 /* 1174 * The "local" command. 1175 */ 1176 1177 int 1178 localcmd(int argc, char **argv) 1179 { 1180 char *name; 1181 int c; 1182 int flags = 0; /*XXX perhaps VUNSET from a -o option value */ 1183 1184 if (! in_function()) 1185 error("Not in a function"); 1186 1187 /* upper case options, as bash stole all the good ones ... */ 1188 while ((c = nextopt("INx")) != '\0') 1189 switch (c) { 1190 case 'I': flags &= ~VUNSET; break; 1191 case 'N': flags |= VUNSET; break; 1192 case 'x': flags |= VEXPORT; break; 1193 } 1194 1195 while ((name = *argptr++) != NULL) { 1196 mklocal(name, flags); 1197 } 1198 return 0; 1199 } 1200 1201 1202 /* 1203 * Make a variable a local variable. When a variable is made local, its 1204 * value and flags are saved in a localvar structure. The saved values 1205 * will be restored when the shell function returns. We handle the name 1206 * "-" as a special case. 1207 */ 1208 1209 void 1210 mklocal(const char *name, int flags) 1211 { 1212 struct localvar *lvp; 1213 struct var **vpp; 1214 struct var *vp; 1215 1216 INTOFF; 1217 lvp = ckmalloc(sizeof (struct localvar)); 1218 if (name[0] == '-' && name[1] == '\0') { 1219 char *p; 1220 p = ckmalloc(sizeof_optlist); 1221 lvp->text = memcpy(p, optlist, sizeof_optlist); 1222 lvp->rfunc = NULL; 1223 vp = NULL; 1224 xtrace_clone(0); 1225 } else { 1226 vp = find_var(name, &vpp, NULL); 1227 if (vp == NULL) { 1228 flags &= ~VNOEXPORT; 1229 if (strchr(name, '=')) 1230 setvareq(savestr(name), 1231 VSTRFIXED | (flags & ~VUNSET)); 1232 else 1233 setvar(name, NULL, VSTRFIXED|flags); 1234 vp = *vpp; /* the new variable */ 1235 lvp->text = NULL; 1236 lvp->flags = VUNSET; 1237 lvp->rfunc = NULL; 1238 } else { 1239 lvp->text = vp->text; 1240 lvp->flags = vp->flags; 1241 lvp->v_u = vp->v_u; 1242 vp->flags |= VSTRFIXED|VTEXTFIXED; 1243 if (flags & (VDOEXPORT | VUNSET)) 1244 vp->flags &= ~VNOEXPORT; 1245 if (vp->flags & VNOEXPORT && 1246 (flags & (VEXPORT|VDOEXPORT|VUNSET)) == VEXPORT) 1247 flags &= ~VEXPORT; 1248 if (flags & (VNOEXPORT | VUNSET)) 1249 vp->flags &= ~VEXPORT; 1250 flags &= ~VNOEXPORT; 1251 if (name[vp->name_len] == '=') 1252 setvareq(savestr(name), flags & ~VUNSET); 1253 else if (flags & VUNSET) 1254 unsetvar(name, 0); 1255 else 1256 vp->flags |= flags & (VUNSET|VEXPORT); 1257 1258 if (vp == &line_num) { 1259 if (name[vp->name_len] == '=') 1260 funclinebase = funclineabs -1; 1261 else 1262 funclinebase = 0; 1263 } 1264 } 1265 } 1266 lvp->vp = vp; 1267 lvp->next = localvars; 1268 localvars = lvp; 1269 INTON; 1270 } 1271 1272 1273 /* 1274 * Called after a function returns. 1275 */ 1276 1277 void 1278 poplocalvars(void) 1279 { 1280 struct localvar *lvp; 1281 struct var *vp; 1282 1283 while ((lvp = localvars) != NULL) { 1284 localvars = lvp->next; 1285 vp = lvp->vp; 1286 VTRACE(DBG_VARS, ("poplocalvar %s\n", vp ? vp->text : "-")); 1287 if (vp == NULL) { /* $- saved */ 1288 memcpy(optlist, lvp->text, sizeof_optlist); 1289 ckfree(lvp->text); 1290 xtrace_pop(); 1291 optschanged(); 1292 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 1293 (void)unsetvar(vp->text, 0); 1294 } else { 1295 if (lvp->func && (lvp->flags & (VNOFUNC|VFUNCREF)) == 0) 1296 (*lvp->func)(lvp->text + vp->name_len + 1, 1297 lvp->flags, lvp->vp); 1298 if ((vp->flags & VTEXTFIXED) == 0) 1299 ckfree(vp->text); 1300 vp->flags = lvp->flags; 1301 vp->text = lvp->text; 1302 vp->v_u = lvp->v_u; 1303 } 1304 ckfree(lvp); 1305 } 1306 } 1307 1308 1309 int 1310 setvarcmd(int argc, char **argv) 1311 { 1312 if (argc <= 2) 1313 return unsetcmd(argc, argv); 1314 else if (argc == 3) 1315 setvar(argv[1], argv[2], 0); 1316 else 1317 error("List assignment not implemented"); 1318 return 0; 1319 } 1320 1321 1322 /* 1323 * The unset builtin command. We unset the function before we unset the 1324 * variable to allow a function to be unset when there is a readonly variable 1325 * with the same name. 1326 */ 1327 1328 int 1329 unsetcmd(int argc, char **argv) 1330 { 1331 char **ap; 1332 int i; 1333 int flg_func = 0; 1334 int flg_var = 0; 1335 int flg_x = 0; 1336 int ret = 0; 1337 1338 while ((i = nextopt("efvx")) != '\0') { 1339 switch (i) { 1340 case 'f': 1341 flg_func = 1; 1342 break; 1343 case 'e': 1344 case 'x': 1345 flg_x = (2 >> (i == 'e')); 1346 /* FALLTHROUGH */ 1347 case 'v': 1348 flg_var = 1; 1349 break; 1350 } 1351 } 1352 1353 if (flg_func == 0 && flg_var == 0) 1354 flg_var = 1; 1355 1356 for (ap = argptr; *ap ; ap++) { 1357 if (flg_func) 1358 ret |= unsetfunc(*ap); 1359 if (flg_var) 1360 ret |= unsetvar(*ap, flg_x); 1361 } 1362 return ret; 1363 } 1364 1365 1366 /* 1367 * Unset the specified variable. 1368 */ 1369 1370 int 1371 unsetvar(const char *s, int unexport) 1372 { 1373 struct var **vpp; 1374 struct var *vp; 1375 1376 vp = find_var(s, &vpp, NULL); 1377 if (vp == NULL) 1378 return 0; 1379 1380 if (vp->flags & VREADONLY && !(unexport & 1)) 1381 return 1; 1382 1383 INTOFF; 1384 if (unexport & 1) { 1385 vp->flags &= ~VEXPORT; 1386 } else { 1387 if (vp->text[vp->name_len + 1] != '\0' || !(vp->flags & VUNSET)) 1388 setvar(s, nullstr, VUNSET); 1389 if (!(unexport & 2)) 1390 vp->flags &= ~VEXPORT; 1391 vp->flags |= VUNSET; 1392 if ((vp->flags&(VEXPORT|VSTRFIXED|VREADONLY|VNOEXPORT)) == 0) { 1393 if ((vp->flags & VTEXTFIXED) == 0) 1394 ckfree(vp->text); 1395 *vpp = vp->next; 1396 ckfree(vp); 1397 } 1398 } 1399 INTON; 1400 return 0; 1401 } 1402 1403 1404 /* 1405 * Returns true if the two strings specify the same variable. The first 1406 * variable name is terminated by '='; the second may be terminated by 1407 * either '=' or '\0'. 1408 */ 1409 1410 STATIC int 1411 strequal(const char *p, const char *q) 1412 { 1413 while (*p == *q++) { 1414 if (*p++ == '=') 1415 return 1; 1416 } 1417 if (*p == '=' && *(q - 1) == '\0') 1418 return 1; 1419 return 0; 1420 } 1421 1422 /* 1423 * Search for a variable. 1424 * 'name' may be terminated by '=' or a NUL. 1425 * vppp is set to the pointer to vp, or the list head if vp isn't found 1426 * lenp is set to the number of characters in 'name' 1427 */ 1428 1429 STATIC struct var * 1430 find_var(const char *name, struct var ***vppp, int *lenp) 1431 { 1432 unsigned int hashval; 1433 int len; 1434 struct var *vp, **vpp; 1435 const char *p = name; 1436 1437 hashval = 0; 1438 while (*p && *p != '=') 1439 hashval = 2 * hashval + (unsigned char)*p++; 1440 1441 len = p - name; 1442 if (lenp) 1443 *lenp = len; 1444 1445 if (len == 0) 1446 return NULL; 1447 1448 vpp = &vartab[hashval % VTABSIZE]; 1449 if (vppp) 1450 *vppp = vpp; 1451 1452 for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { 1453 if (vp->name_len != len) 1454 continue; 1455 if (memcmp(vp->text, name, len) != 0) 1456 continue; 1457 if (vppp) 1458 *vppp = vpp; 1459 return vp; 1460 } 1461 return NULL; 1462 } 1463 1464 /* 1465 * The following are the functions that create the values for 1466 * shell variables that are dynamically produced when needed. 1467 * 1468 * The output strings cannot be malloc'd as there is nothing to 1469 * free them - callers assume these are ordinary variables where 1470 * the value returned is vp->text 1471 * 1472 * Each function needs its own storage space, as the results are 1473 * used to create processes' environment, and (if exported) all 1474 * the values will (might) be needed simultaneously. 1475 * 1476 * It is not a problem if a var is updated while nominally in use 1477 * somewhere, all these are intended to be dynamic, the value they 1478 * return is not guaranteed, an updated value is just as good. 1479 * 1480 * So, malloc a single buffer for the result of each function, 1481 * grow, and even shrink, it as needed, but once we have one that 1482 * is a suitable size for the actual usage, simply hold it forever. 1483 * 1484 * For a SMALL shell we implement only LINENO, none of the others, 1485 * and give it just a fixed length static buffer for its result. 1486 */ 1487 1488 #ifndef SMALL 1489 1490 struct space_reserved { /* record of space allocated for results */ 1491 char *b; 1492 int len; 1493 }; 1494 1495 /* rough (over-)estimate of the number of bytes needed to hold a number */ 1496 static int 1497 digits_in(intmax_t number) 1498 { 1499 int res = 0; 1500 1501 if (number & ~((1LL << 62) - 1)) 1502 res = 64; /* enough for 2^200 and a bit more */ 1503 else if (number & ~((1LL << 32) - 1)) 1504 res = 20; /* enough for 2^64 */ 1505 else if (number & ~((1 << 23) - 1)) 1506 res = 10; /* enough for 2^32 */ 1507 else 1508 res = 8; /* enough for 2^23 or smaller */ 1509 1510 return res; 1511 } 1512 1513 static int 1514 make_space(struct space_reserved *m, int bytes) 1515 { 1516 void *p; 1517 1518 if (m->len >= bytes && m->len <= (bytes<<2)) 1519 return 1; 1520 1521 bytes = SHELL_ALIGN(bytes); 1522 INTOFF; 1523 /* not ckrealloc() - we want failure, not error() here */ 1524 p = realloc(m->b, bytes); 1525 if (p != NULL) { 1526 m->b = p; 1527 m->len = bytes; 1528 m->b[bytes - 1] = '\0'; 1529 } 1530 INTON; 1531 1532 return p != NULL; 1533 } 1534 #endif 1535 1536 char * 1537 get_lineno(struct var *vp) 1538 { 1539 #ifdef SMALL 1540 #define length (8 + 10) /* 10 digits is enough for a 32 bit line num */ 1541 static char result[length]; 1542 #else 1543 static struct space_reserved buf; 1544 #define result buf.b 1545 #define length buf.len 1546 #endif 1547 int ln = line_number; 1548 1549 if (vp->flags & VUNSET) 1550 return NULL; 1551 1552 ln -= funclinebase; 1553 1554 #ifndef SMALL 1555 if (!make_space(&buf, vp->name_len + 2 + digits_in(ln))) 1556 return vp->text; 1557 #endif 1558 1559 snprintf(result, length, "%.*s=%d", vp->name_len, vp->text, ln); 1560 return result; 1561 } 1562 #undef result 1563 #undef length 1564 1565 #ifndef SMALL 1566 1567 char * 1568 get_hostname(struct var *vp) 1569 { 1570 static struct space_reserved buf; 1571 1572 if (vp->flags & VUNSET) 1573 return NULL; 1574 1575 if (!make_space(&buf, vp->name_len + 2 + 256)) 1576 return vp->text; 1577 1578 memcpy(buf.b, vp->text, vp->name_len + 1); /* include '=' */ 1579 (void)gethostname(buf.b + vp->name_len + 1, 1580 buf.len - vp->name_len - 3); 1581 return buf.b; 1582 } 1583 1584 char * 1585 get_tod(struct var *vp) 1586 { 1587 static struct space_reserved buf; /* space for answers */ 1588 static struct space_reserved tzs; /* remember TZ last used */ 1589 static timezone_t last_zone; /* timezone data for tzs zone */ 1590 const char *fmt; 1591 char *tz; 1592 time_t now; 1593 struct tm tm_now, *tmp; 1594 timezone_t zone = NULL; 1595 static char t_err[] = "time error"; 1596 int len; 1597 1598 if (vp->flags & VUNSET) 1599 return NULL; 1600 1601 fmt = lookupvar("ToD_FORMAT"); 1602 if (fmt == NULL) 1603 fmt="%T"; 1604 tz = lookupvar("TZ"); 1605 (void)time(&now); 1606 1607 if (tz != NULL) { 1608 if (tzs.b == NULL || strcmp(tzs.b, tz) != 0) { 1609 INTOFF; 1610 if (make_space(&tzs, strlen(tz) + 1)) { 1611 strcpy(tzs.b, tz); 1612 if (last_zone) 1613 tzfree(last_zone); 1614 last_zone = zone = tzalloc(tz); 1615 INTON; 1616 } else 1617 zone = tzalloc(tz); 1618 } else 1619 zone = last_zone; 1620 1621 tmp = localtime_rz(zone, &now, &tm_now); 1622 } else 1623 tmp = localtime_r(&now, &tm_now); 1624 1625 len = (strlen(fmt) * 4) + vp->name_len + 2; 1626 while (make_space(&buf, len)) { 1627 memcpy(buf.b, vp->text, vp->name_len+1); 1628 if (tmp == NULL) { 1629 if (buf.len >= vp->name_len+2+(int)(sizeof t_err - 1)) { 1630 strcpy(buf.b + vp->name_len + 1, t_err); 1631 if (zone && zone != last_zone) { 1632 tzfree(zone); 1633 INTON; 1634 } 1635 return buf.b; 1636 } 1637 len = vp->name_len + 4 + sizeof t_err - 1; 1638 continue; 1639 } 1640 if (zone != NULL) { 1641 if (strftime_z(zone, buf.b + vp->name_len + 1, 1642 buf.len - vp->name_len - 2, fmt, tmp)) { 1643 if (zone != last_zone) { 1644 tzfree(zone); 1645 INTON; 1646 } 1647 return buf.b; 1648 } 1649 } else if (strftime(buf.b + vp->name_len + 1, 1650 buf.len - vp->name_len - 2, fmt, tmp)) 1651 return buf.b; 1652 1653 if (len >= 4096) /* Let's be reasonable */ 1654 break; 1655 len <<= 1; 1656 } 1657 if (zone && zone != last_zone) { 1658 tzfree(zone); 1659 INTON; 1660 } 1661 return vp->text; 1662 } 1663 1664 char * 1665 get_seconds(struct var *vp) 1666 { 1667 static struct space_reserved buf; 1668 intmax_t secs; 1669 1670 if (vp->flags & VUNSET) 1671 return NULL; 1672 1673 secs = (intmax_t)time((time_t *)0) - sh_start_time; 1674 if (!make_space(&buf, vp->name_len + 2 + digits_in(secs))) 1675 return vp->text; 1676 1677 snprintf(buf.b, buf.len, "%.*s=%jd", vp->name_len, vp->text, secs); 1678 return buf.b; 1679 } 1680 1681 char * 1682 get_euser(struct var *vp) 1683 { 1684 static struct space_reserved buf; 1685 static uid_t lastuid = 0; 1686 uid_t euid; 1687 struct passwd *pw; 1688 1689 if (vp->flags & VUNSET) 1690 return NULL; 1691 1692 euid = geteuid(); 1693 if (buf.b != NULL && lastuid == euid) 1694 return buf.b; 1695 1696 pw = getpwuid(euid); 1697 if (pw == NULL) 1698 return vp->text; 1699 1700 if (make_space(&buf, vp->name_len + 2 + strlen(pw->pw_name))) { 1701 INTOFF; 1702 lastuid = euid; 1703 snprintf(buf.b, buf.len, "%.*s=%s", vp->name_len, vp->text, 1704 pw->pw_name); 1705 INTON; 1706 return buf.b; 1707 } 1708 1709 return vp->text; 1710 } 1711 1712 char * 1713 get_random(struct var *vp) 1714 { 1715 static struct space_reserved buf; 1716 static intmax_t random_val = 0; 1717 1718 #ifdef USE_LRAND48 1719 #define random lrand48 1720 #define srandom srand48 1721 #endif 1722 1723 if (vp->flags & VUNSET) 1724 return NULL; 1725 1726 if (vp->text != buf.b) { 1727 /* 1728 * Either initialisation, or a new seed has been set 1729 */ 1730 if (vp->text[vp->name_len + 1] == '\0') { 1731 int fd; 1732 1733 /* 1734 * initialisation (without pre-seeding), 1735 * or explicitly requesting a truly random seed. 1736 */ 1737 INTOFF; 1738 fd = open("/dev/urandom", 0); 1739 if (fd == -1) { 1740 out2str("RANDOM initialisation failed\n"); 1741 random_val = (getpid()<<3) ^ time((time_t *)0); 1742 } else { 1743 int n; 1744 1745 do { 1746 n = read(fd,&random_val,sizeof random_val); 1747 } while (n != sizeof random_val); 1748 close(fd); 1749 } 1750 INTON; 1751 } else 1752 /* good enough for today */ 1753 random_val = strtoimax(vp->text+vp->name_len+1,NULL,0); 1754 1755 srandom((long)random_val); 1756 } 1757 1758 #if 0 1759 random_val = (random_val + 1) & 0x7FFF; /* 15 bit "random" numbers */ 1760 #else 1761 random_val = (random() >> 5) & 0x7FFF; 1762 #endif 1763 1764 if (!make_space(&buf, vp->name_len + 2 + digits_in(random_val))) 1765 return vp->text; 1766 1767 snprintf(buf.b, buf.len, "%.*s=%jd", vp->name_len, vp->text, 1768 random_val); 1769 1770 INTOFF; 1771 if (buf.b != vp->text && (vp->flags & (VTEXTFIXED|VSTACK)) == 0) 1772 free(vp->text); 1773 vp->flags |= VTEXTFIXED; 1774 vp->text = buf.b; 1775 INTON; 1776 1777 return vp->text; 1778 #undef random 1779 #undef srandom 1780 } 1781 1782 STATIC int 1783 makespecial(const char *name) 1784 { 1785 const struct varinit *ip; 1786 struct var *vp; 1787 1788 CTRACE(DBG_VARS, ("makespecial('%s') -> ", name)); 1789 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { 1790 if (strequal(ip->text, name)) { 1791 if (!(ip->flags & VFUNCREF)) { 1792 CTRACE(DBG_VARS, ("+1\n")); 1793 return 1; 1794 } 1795 INTOFF; 1796 vp->flags &= ~VUNSET; 1797 vp->v_u = ip->v_u; 1798 INTON; 1799 CTRACE(DBG_VARS, ("0\n")); 1800 return 0; 1801 } 1802 } 1803 CTRACE(DBG_VARS, ("1\n")); 1804 return 1; 1805 } 1806 1807 int 1808 specialvarcmd(int argc, char **argv) 1809 { 1810 int res = 0; 1811 char **ap; 1812 1813 (void) nextopt(""); 1814 1815 if (!*argptr) 1816 error("Usage: specialvar var..."); 1817 1818 for (ap = argptr; *ap ; ap++) 1819 res |= makespecial(*ap); 1820 1821 return res; 1822 } 1823 1824 struct lc_vars { 1825 const char *name; 1826 int category; 1827 struct var *vp; 1828 }; 1829 1830 const struct lc_vars lc_vars[] = { 1831 { .name= "LC_ALL", .category= LC_ALL, .vp= &lc_all }, 1832 1833 { .name= "LC_COLLATE", .category= LC_COLLATE, .vp= &lc_collate }, 1834 { .name= "LC_CTYPE", .category= LC_CTYPE, .vp= &lc_ctype }, 1835 { .name= "LC_MESSAGES", .category= LC_MESSAGES, .vp= &lc_messages }, 1836 { .name= "LC_MONETARY", .category= LC_MONETARY, .vp= &lc_monetary }, 1837 { .name= "LC_NUMERIC", .category= LC_NUMERIC, .vp= &lc_numeric }, 1838 { .name= "LC_TIME", .category= LC_TIME, .vp= &lc_time }, 1839 1840 { .name= "LANG", .category= LC_ALL, .vp= &lc_lang }, 1841 1842 { .name= NULL, .category= 0, .vp= NULL } 1843 }; 1844 1845 STATIC void 1846 set_locale_var(const char *val, int flags, struct var *vp) 1847 { 1848 const struct lc_vars *lv; 1849 1850 if (flags & VUNSAFE) /* parsing the environment */ 1851 return; /* do nothing until later */ 1852 1853 for (lv = lc_vars; lv->name != NULL; lv++) { 1854 /* Find the var being altered */ 1855 if (lv->vp != vp) 1856 continue; 1857 1858 if (flags & VUNSET) { 1859 /* 1860 * If we are unsetting one of these, then 1861 * we need to set the locale for the category 1862 * back to a default value 1863 */ 1864 1865 if (lv->category == LC_ALL) { 1866 /* 1867 * nb: the LC_ALL vars call this func 1868 * after their value has changed, ie: 1869 * since this is an unset, the var already 1870 * is unset. This simplifies things. 1871 */ 1872 1873 /* 1874 * LANG is just the default to use when 1875 * nothing more specific is set, if it is 1876 * unset, there is nothing to do. 1877 */ 1878 if (lv->vp == &lc_lang) 1879 return; 1880 1881 /* 1882 * Otherwise LC_ALL must be being unset, 1883 * in that case, simply set everything to 1884 * the values obtained from the other 1885 * LC_xxx vars (with LANG as default) 1886 */ 1887 init_locale_vars(); 1888 return; 1889 } 1890 1891 /* 1892 * For the category vars, this func is called before 1893 * the sh var is updated 1894 */ 1895 1896 /* If a category var previously was unset - easy case */ 1897 if (lv->vp->flags & VUNSET) 1898 return; 1899 1900 /* 1901 * One of the specific categories is being 1902 * unset, in that case we fall back upon 1903 * the value of LC_ALL if that is set, or 1904 * otherwise the value of LANG, if that is set, 1905 * or just set the "C" locale for this category 1906 */ 1907 vp = NULL; 1908 if (!(lc_all.flags & VUNSET)) 1909 vp = &lc_all; 1910 else if (!(lc_lang.flags & VUNSET)) 1911 vp = &lc_lang; 1912 1913 if (vp != NULL) 1914 val = vp->text + vp->name_len + 1; 1915 else 1916 val = "C"; 1917 1918 set_locale_var(val, 0, lv->vp); 1919 } else { 1920 char *old; 1921 1922 if (lv->category == LC_ALL) { 1923 /* 1924 * post call, so this var's value is 1925 * already established, just go use 1926 * it (and the others) to set all the 1927 * categories 1928 */ 1929 init_locale_vars(); 1930 return; 1931 } 1932 1933 /* 1934 * Potentially changing the value of a specific 1935 * category. 1936 * 1937 * If the value isn't actually changing, do nothing 1938 */ 1939 old = setlocale(lv->category, NULL); 1940 if (old != NULL && strcmp(old, val) != 0) { 1941 /* 1942 * Otherwise update the shell's locale 1943 * to match the new setting 1944 */ 1945 if (setlocale(lv->category, val) == NULL) { 1946 /*XXX NetBSD! */ if (lv->category != LC_COLLATE) 1947 outfmt(out2, 1948 "Setting %s to '%s' failed" 1949 " setlocale(3)\n", lv->name, val); 1950 } else if (lv->category == LC_CTYPE) { 1951 /* 1952 * and if that worked, and we're 1953 * changing the char encodings, 1954 * go re-init libedit (if in use) 1955 */ 1956 if (iflag && (Eflag || Vflag)) { 1957 int oE = Eflag, oV = Vflag; 1958 1959 /* 1960 * re-init editing if 1961 * LC_CTYPE changes 1962 * 1963 * easy way: disable, then 1964 * enable again 1965 */ 1966 Eflag = Vflag = 0; 1967 histedit(); 1968 Eflag = oE, Vflag=oV; 1969 histedit(); 1970 } 1971 } 1972 } 1973 1974 } 1975 return; 1976 } 1977 } 1978 1979 void 1980 init_locale_vars(void) 1981 { 1982 const struct lc_vars *lv; 1983 const char *defval; 1984 1985 if (!(lc_all.flags & VUNSET)) { 1986 /* 1987 * If LC_ALL is set, just use it, ignore others 1988 * Simply set all categories to the value of LC_ALL 1989 * 1990 * nb: strlen("LC_ALL") + 1 == 7 1991 */ 1992 for (lv = lc_vars; lv->name != NULL; lv++) { 1993 if (lv->category == LC_ALL) 1994 continue; 1995 set_locale_var(lc_all.text + 7, 0, lv->vp); 1996 } 1997 return; 1998 } 1999 2000 /* 2001 * Otherwise, for each specific category, set the value 2002 * of its variable for that category, if that variable is 2003 * set, otherwise we need a default for that category. 2004 * If LANG is set, that gives the default, otherwise it is "C" 2005 */ 2006 if (lc_lang.flags & VUNSET) 2007 defval = "C"; 2008 else 2009 defval = lc_lang.text + 5; /* strlen("LANG") + 1 == 5 */ 2010 2011 for (lv = lc_vars; lv->name != NULL; lv++) { 2012 /* ignore LC_ALL and LANG */ 2013 if (lv->category == LC_ALL) 2014 continue; 2015 /* otherwise set the category to the appropriate value */ 2016 set_locale_var( (lv->vp->flags & VUNSET ? defval : 2017 lv->vp->text + lv->vp->name_len + 1), 2018 0, lv->vp); 2019 } 2020 } 2021 2022 #endif /* SMALL */ 2023