1 /* $OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 5 * Thorsten Glaser <tg (at) mirbsd.org> 6 * 7 * Provided that these terms and disclaimer and all copyright notices 8 * are retained or reproduced in an accompanying document, permission 9 * is granted to deal in this work without restriction, including un- 10 * limited rights to use, publicly perform, distribute, sell, modify, 11 * merge, give away, or sublicence. 12 * 13 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 14 * the utmost extent permitted by applicable law, neither express nor 15 * implied; without malicious intent or gross negligence. In no event 16 * may a licensor, author or contributor be held liable for indirect, 17 * direct, other damage, loss, or other issues arising in any way out 18 * of dealing in the work, even if advised of the possibility of such 19 * damage or existence of a defect, except proven that it results out 20 * of said person's immediate fault when using the work as intended. 21 */ 22 23 #include "sh.h" 24 25 #if defined(__OpenBSD__) 26 #include <sys/sysctl.h> 27 #endif 28 29 __RCSID("$MirOS: src/bin/mksh/var.c,v 1.110 2010/07/25 11:35:43 tg Exp $"); 30 31 /* 32 * Variables 33 * 34 * WARNING: unreadable code, needs a rewrite 35 * 36 * if (flag&INTEGER), val.i contains integer value, and type contains base. 37 * otherwise, (val.s + type) contains string value. 38 * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting. 39 */ 40 static struct tbl vtemp; 41 static struct table specials; 42 static char *formatstr(struct tbl *, const char *); 43 static void exportprep(struct tbl *, const char *); 44 static int special(const char *); 45 static void unspecial(const char *); 46 static void getspec(struct tbl *); 47 static void setspec(struct tbl *); 48 static void unsetspec(struct tbl *); 49 static int getint(struct tbl *, mksh_ari_t *, bool); 50 static mksh_ari_t intval(struct tbl *); 51 static struct tbl *arraysearch(struct tbl *, uint32_t); 52 static const char *array_index_calc(const char *, bool *, uint32_t *); 53 static uint32_t oaathash_update(register uint32_t, register const uint8_t *, 54 register size_t); 55 static uint32_t oaathash_finalise(register uint32_t); 56 57 uint8_t set_refflag = 0; 58 59 /* 60 * create a new block for function calls and simple commands 61 * assume caller has allocated and set up e->loc 62 */ 63 void 64 newblock(void) 65 { 66 struct block *l; 67 static const char *empty[] = { null }; 68 69 l = alloc(sizeof(struct block), ATEMP); 70 l->flags = 0; 71 ainit(&l->area); /* todo: could use e->area (l->area => l->areap) */ 72 if (!e->loc) { 73 l->argc = 0; 74 l->argv = empty; 75 } else { 76 l->argc = e->loc->argc; 77 l->argv = e->loc->argv; 78 } 79 l->exit = l->error = NULL; 80 ktinit(&l->vars, &l->area, 0); 81 ktinit(&l->funs, &l->area, 0); 82 l->next = e->loc; 83 e->loc = l; 84 } 85 86 /* 87 * pop a block handling special variables 88 */ 89 void 90 popblock(void) 91 { 92 struct block *l = e->loc; 93 struct tbl *vp, **vpp = l->vars.tbls, *vq; 94 int i; 95 96 e->loc = l->next; /* pop block */ 97 for (i = l->vars.size; --i >= 0; ) 98 if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) { 99 if ((vq = global(vp->name))->flag & ISSET) 100 setspec(vq); 101 else 102 unsetspec(vq); 103 } 104 if (l->flags & BF_DOGETOPTS) 105 user_opt = l->getopts_state; 106 afreeall(&l->area); 107 afree(l, ATEMP); 108 } 109 110 /* called by main() to initialise variable data structures */ 111 #define VARSPEC_DEFNS 112 #include "var_spec.h" 113 114 enum var_specs { 115 #define VARSPEC_ENUMS 116 #include "var_spec.h" 117 V_MAX 118 }; 119 120 static const char * const initvar_names[] = { 121 #define VARSPEC_ITEMS 122 #include "var_spec.h" 123 }; 124 125 void 126 initvar(void) 127 { 128 int i = 0; 129 struct tbl *tp; 130 131 ktinit(&specials, APERM, 132 /* must be 80% of 2^n (currently 12 specials) */ 16); 133 while (i < V_MAX - 1) { 134 tp = ktenter(&specials, initvar_names[i], 135 hash(initvar_names[i])); 136 tp->flag = DEFINED|ISSET; 137 tp->type = ++i; 138 } 139 } 140 141 /* Used to calculate an array index for global()/local(). Sets *arrayp to 142 * true if this is an array, sets *valp to the array index, returns 143 * the basename of the array. 144 */ 145 static const char * 146 array_index_calc(const char *n, bool *arrayp, uint32_t *valp) 147 { 148 const char *p; 149 int len; 150 char *ap = NULL; 151 152 *arrayp = false; 153 redo_from_ref: 154 p = skip_varname(n, false); 155 if (!set_refflag && (p != n) && ksh_isalphx(n[0])) { 156 struct block *l = e->loc; 157 struct tbl *vp; 158 char *vn; 159 uint32_t h; 160 161 strndupx(vn, n, p - n, ATEMP); 162 h = hash(vn); 163 /* check if this is a reference */ 164 do { 165 vp = ktsearch(&l->vars, vn, h); 166 } while (!vp && (l = l->next)); 167 afree(vn, ATEMP); 168 if (vp && (vp->flag & (DEFINED|ASSOC|ARRAY)) == 169 (DEFINED|ASSOC)) { 170 char *cp; 171 172 /* gotcha! */ 173 cp = shf_smprintf("%s%s", str_val(vp), p); 174 afree(ap, ATEMP); 175 n = ap = cp; 176 goto redo_from_ref; 177 } 178 } 179 180 if (p != n && *p == '[' && (len = array_ref_len(p))) { 181 char *sub, *tmp; 182 mksh_ari_t rval; 183 184 /* Calculate the value of the subscript */ 185 *arrayp = true; 186 strndupx(tmp, p + 1, len - 2, ATEMP); 187 sub = substitute(tmp, 0); 188 afree(tmp, ATEMP); 189 strndupx(n, n, p - n, ATEMP); 190 evaluate(sub, &rval, KSH_UNWIND_ERROR, true); 191 *valp = (uint32_t)rval; 192 afree(sub, ATEMP); 193 } 194 return (n); 195 } 196 197 /* 198 * Search for variable, if not found create globally. 199 */ 200 struct tbl * 201 global(const char *n) 202 { 203 struct block *l = e->loc; 204 struct tbl *vp; 205 int c; 206 bool array; 207 uint32_t h, val; 208 209 /* Check to see if this is an array */ 210 n = array_index_calc(n, &array, &val); 211 h = hash(n); 212 c = n[0]; 213 if (!ksh_isalphx(c)) { 214 if (array) 215 errorf("bad substitution"); 216 vp = &vtemp; 217 vp->flag = DEFINED; 218 vp->type = 0; 219 vp->areap = ATEMP; 220 *vp->name = c; 221 if (ksh_isdigit(c)) { 222 for (c = 0; ksh_isdigit(*n); n++) 223 c = c*10 + *n-'0'; 224 if (c <= l->argc) 225 /* setstr can't fail here */ 226 setstr(vp, l->argv[c], KSH_RETURN_ERROR); 227 vp->flag |= RDONLY; 228 return (vp); 229 } 230 vp->flag |= RDONLY; 231 if (n[1] != '\0') 232 return (vp); 233 vp->flag |= ISSET|INTEGER; 234 switch (c) { 235 case '$': 236 vp->val.i = kshpid; 237 break; 238 case '!': 239 /* If no job, expand to nothing */ 240 if ((vp->val.i = j_async()) == 0) 241 vp->flag &= ~(ISSET|INTEGER); 242 break; 243 case '?': 244 vp->val.i = exstat; 245 break; 246 case '#': 247 vp->val.i = l->argc; 248 break; 249 case '-': 250 vp->flag &= ~INTEGER; 251 vp->val.s = getoptions(); 252 break; 253 default: 254 vp->flag &= ~(ISSET|INTEGER); 255 } 256 return (vp); 257 } 258 for (l = e->loc; ; l = l->next) { 259 vp = ktsearch(&l->vars, n, h); 260 if (vp != NULL) { 261 if (array) 262 return (arraysearch(vp, val)); 263 else 264 return (vp); 265 } 266 if (l->next == NULL) 267 break; 268 } 269 vp = ktenter(&l->vars, n, h); 270 if (array) 271 vp = arraysearch(vp, val); 272 vp->flag |= DEFINED; 273 if (special(n)) 274 vp->flag |= SPECIAL; 275 return (vp); 276 } 277 278 /* 279 * Search for local variable, if not found create locally. 280 */ 281 struct tbl * 282 local(const char *n, bool copy) 283 { 284 struct block *l = e->loc; 285 struct tbl *vp; 286 bool array; 287 uint32_t h, val; 288 289 /* Check to see if this is an array */ 290 n = array_index_calc(n, &array, &val); 291 h = hash(n); 292 if (!ksh_isalphx(*n)) { 293 vp = &vtemp; 294 vp->flag = DEFINED|RDONLY; 295 vp->type = 0; 296 vp->areap = ATEMP; 297 return (vp); 298 } 299 vp = ktenter(&l->vars, n, h); 300 if (copy && !(vp->flag & DEFINED)) { 301 struct block *ll = l; 302 struct tbl *vq = NULL; 303 304 while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h))) 305 ; 306 if (vq) { 307 vp->flag |= vq->flag & 308 (EXPORT | INTEGER | RDONLY | LJUST | RJUST | 309 ZEROFIL | LCASEV | UCASEV_AL | INT_U | INT_L); 310 if (vq->flag & INTEGER) 311 vp->type = vq->type; 312 vp->u2.field = vq->u2.field; 313 } 314 } 315 if (array) 316 vp = arraysearch(vp, val); 317 vp->flag |= DEFINED; 318 if (special(n)) 319 vp->flag |= SPECIAL; 320 return (vp); 321 } 322 323 /* get variable string value */ 324 char * 325 str_val(struct tbl *vp) 326 { 327 char *s; 328 329 if ((vp->flag&SPECIAL)) 330 getspec(vp); 331 if (!(vp->flag&ISSET)) 332 s = null; /* special to dollar() */ 333 else if (!(vp->flag&INTEGER)) /* string source */ 334 s = vp->val.s + vp->type; 335 else { /* integer source */ 336 /* worst case number length is when base=2 */ 337 /* 1 (minus) + 2 (base, up to 36) + 1 ('#') + number of bits 338 * in the mksh_uari_t + 1 (NUL) */ 339 char strbuf[1 + 2 + 1 + 8 * sizeof(mksh_uari_t) + 1]; 340 const char *digits = (vp->flag & UCASEV_AL) ? 341 digits_uc : digits_lc; 342 mksh_uari_t n; 343 int base; 344 345 s = strbuf + sizeof(strbuf); 346 if (vp->flag & INT_U) 347 n = vp->val.u; 348 else 349 n = (vp->val.i < 0) ? -vp->val.i : vp->val.i; 350 base = (vp->type == 0) ? 10 : vp->type; 351 352 if (base == 1) { 353 size_t sz = 1; 354 355 *(s = strbuf) = '1'; 356 s[1] = '#'; 357 if (!UTFMODE || ((n & 0xFF80) == 0xEF80)) 358 /* OPTU-16 -> raw octet */ 359 s[2] = n & 0xFF; 360 else 361 sz = utf_wctomb(s + 2, n); 362 s[2 + sz] = '\0'; 363 } else { 364 *--s = '\0'; 365 do { 366 *--s = digits[n % base]; 367 n /= base; 368 } while (n != 0); 369 if (base != 10) { 370 *--s = '#'; 371 *--s = digits[base % 10]; 372 if (base >= 10) 373 *--s = digits[base / 10]; 374 } 375 if (!(vp->flag & INT_U) && vp->val.i < 0) 376 *--s = '-'; 377 } 378 if (vp->flag & (RJUST|LJUST)) /* case already dealt with */ 379 s = formatstr(vp, s); 380 else 381 strdupx(s, s, ATEMP); 382 } 383 return (s); 384 } 385 386 /* get variable integer value, with error checking */ 387 static mksh_ari_t 388 intval(struct tbl *vp) 389 { 390 mksh_ari_t num; 391 int base; 392 393 base = getint(vp, &num, false); 394 if (base == -1) 395 /* XXX check calls - is error here ok by POSIX? */ 396 errorf("%s: bad number", str_val(vp)); 397 return (num); 398 } 399 400 /* set variable to string value */ 401 int 402 setstr(struct tbl *vq, const char *s, int error_ok) 403 { 404 char *salloc = NULL; 405 int no_ro_check = error_ok & 0x4; 406 407 error_ok &= ~0x4; 408 if ((vq->flag & RDONLY) && !no_ro_check) { 409 warningf(true, "%s: is read only", vq->name); 410 if (!error_ok) 411 errorfz(); 412 return (0); 413 } 414 if (!(vq->flag&INTEGER)) { /* string dest */ 415 if ((vq->flag&ALLOC)) { 416 /* debugging */ 417 if (s >= vq->val.s && 418 s <= vq->val.s + strlen(vq->val.s)) 419 internal_errorf( 420 "setstr: %s=%s: assigning to self", 421 vq->name, s); 422 afree(vq->val.s, vq->areap); 423 } 424 vq->flag &= ~(ISSET|ALLOC); 425 vq->type = 0; 426 if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST))) 427 s = salloc = formatstr(vq, s); 428 if ((vq->flag&EXPORT)) 429 exportprep(vq, s); 430 else { 431 strdupx(vq->val.s, s, vq->areap); 432 vq->flag |= ALLOC; 433 } 434 } else { /* integer dest */ 435 if (!v_evaluate(vq, s, error_ok, true)) 436 return (0); 437 } 438 vq->flag |= ISSET; 439 if ((vq->flag&SPECIAL)) 440 setspec(vq); 441 afree(salloc, ATEMP); 442 return (1); 443 } 444 445 /* set variable to integer */ 446 void 447 setint(struct tbl *vq, mksh_ari_t n) 448 { 449 if (!(vq->flag&INTEGER)) { 450 struct tbl *vp = &vtemp; 451 vp->flag = (ISSET|INTEGER); 452 vp->type = 0; 453 vp->areap = ATEMP; 454 vp->val.i = n; 455 /* setstr can't fail here */ 456 setstr(vq, str_val(vp), KSH_RETURN_ERROR); 457 } else 458 vq->val.i = n; 459 vq->flag |= ISSET; 460 if ((vq->flag&SPECIAL)) 461 setspec(vq); 462 } 463 464 static int 465 getint(struct tbl *vp, mksh_ari_t *nump, bool arith) 466 { 467 char *s; 468 int c, base, neg; 469 bool have_base = false; 470 mksh_ari_t num; 471 472 if (vp->flag&SPECIAL) 473 getspec(vp); 474 /* XXX is it possible for ISSET to be set and val.s to be 0? */ 475 if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL)) 476 return (-1); 477 if (vp->flag&INTEGER) { 478 *nump = vp->val.i; 479 return (vp->type); 480 } 481 s = vp->val.s + vp->type; 482 if (s == NULL) /* redundant given initial test */ 483 s = null; 484 base = 10; 485 num = 0; 486 neg = 0; 487 if (arith && *s == '0' && *(s+1)) { 488 s++; 489 if (*s == 'x' || *s == 'X') { 490 s++; 491 base = 16; 492 } else if (vp->flag & ZEROFIL) { 493 while (*s == '0') 494 s++; 495 } else 496 base = 8; 497 have_base = true; 498 } 499 for (c = *s++; c ; c = *s++) { 500 if (c == '-') { 501 neg++; 502 continue; 503 } else if (c == '#') { 504 base = (int)num; 505 if (have_base || base < 1 || base > 36) 506 return (-1); 507 if (base == 1) { 508 unsigned int wc; 509 510 if (!UTFMODE) 511 wc = *(unsigned char *)s; 512 else if (utf_mbtowc(&wc, s) == (size_t)-1) 513 /* OPTU-8 -> OPTU-16 */ 514 /* 515 * (with a twist: 1#\uEF80 converts 516 * the same as 1#\x80 does, thus is 517 * not round-tripping correctly XXX) 518 */ 519 wc = 0xEF00 + *(unsigned char *)s; 520 *nump = (mksh_ari_t)wc; 521 return (1); 522 } 523 num = 0; 524 have_base = true; 525 continue; 526 } else if (ksh_isdigit(c)) 527 c -= '0'; 528 else if (ksh_islower(c)) 529 c -= 'a' - 10; 530 else if (ksh_isupper(c)) 531 c -= 'A' - 10; 532 else 533 return (-1); 534 if (c < 0 || c >= base) 535 return (-1); 536 num = num * base + c; 537 } 538 if (neg) 539 num = -num; 540 *nump = num; 541 return (base); 542 } 543 544 /* convert variable vq to integer variable, setting its value from vp 545 * (vq and vp may be the same) 546 */ 547 struct tbl * 548 setint_v(struct tbl *vq, struct tbl *vp, bool arith) 549 { 550 int base; 551 mksh_ari_t num; 552 553 if ((base = getint(vp, &num, arith)) == -1) 554 return (NULL); 555 if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) { 556 vq->flag &= ~ALLOC; 557 afree(vq->val.s, vq->areap); 558 } 559 vq->val.i = num; 560 if (vq->type == 0) /* default base */ 561 vq->type = base; 562 vq->flag |= ISSET|INTEGER; 563 if (vq->flag&SPECIAL) 564 setspec(vq); 565 return (vq); 566 } 567 568 static char * 569 formatstr(struct tbl *vp, const char *s) 570 { 571 int olen, nlen; 572 char *p, *q; 573 size_t psiz; 574 575 olen = utf_mbswidth(s); 576 577 if (vp->flag & (RJUST|LJUST)) { 578 if (!vp->u2.field) /* default field width */ 579 vp->u2.field = olen; 580 nlen = vp->u2.field; 581 } else 582 nlen = olen; 583 584 p = alloc((psiz = nlen * /* MB_LEN_MAX */ 3 + 1), ATEMP); 585 if (vp->flag & (RJUST|LJUST)) { 586 int slen = olen, i = 0; 587 588 if (vp->flag & RJUST) { 589 const char *qq = s; 590 int n = 0; 591 592 while (i < slen) 593 i += utf_widthadj(qq, &qq); 594 /* strip trailing spaces (AT&T uses qq[-1] == ' ') */ 595 while (qq > s && ksh_isspace(qq[-1])) { 596 --qq; 597 --slen; 598 } 599 if (vp->flag & ZEROFIL && vp->flag & INTEGER) { 600 if (s[1] == '#') 601 n = 2; 602 else if (s[2] == '#') 603 n = 3; 604 if (vp->u2.field <= n) 605 n = 0; 606 } 607 if (n) { 608 memcpy(p, s, n); 609 s += n; 610 } 611 while (slen > vp->u2.field) 612 slen -= utf_widthadj(s, &s); 613 if (vp->u2.field - slen) 614 memset(p + n, (vp->flag & ZEROFIL) ? '0' : ' ', 615 vp->u2.field - slen); 616 slen -= n; 617 shf_snprintf(p + vp->u2.field - slen, 618 psiz - (vp->u2.field - slen), 619 "%.*s", slen, s); 620 } else { 621 /* strip leading spaces/zeros */ 622 while (ksh_isspace(*s)) 623 s++; 624 if (vp->flag & ZEROFIL) 625 while (*s == '0') 626 s++; 627 shf_snprintf(p, nlen + 1, "%-*.*s", 628 vp->u2.field, vp->u2.field, s); 629 } 630 } else 631 memcpy(p, s, strlen(s) + 1); 632 633 if (vp->flag & UCASEV_AL) { 634 for (q = p; *q; q++) 635 *q = ksh_toupper(*q); 636 } else if (vp->flag & LCASEV) { 637 for (q = p; *q; q++) 638 *q = ksh_tolower(*q); 639 } 640 641 return (p); 642 } 643 644 /* 645 * make vp->val.s be "name=value" for quick exporting. 646 */ 647 static void 648 exportprep(struct tbl *vp, const char *val) 649 { 650 char *xp; 651 char *op = (vp->flag&ALLOC) ? vp->val.s : NULL; 652 int namelen = strlen(vp->name); 653 int vallen = strlen(val) + 1; 654 655 vp->flag |= ALLOC; 656 xp = alloc(namelen + 1 + vallen, vp->areap); 657 memcpy(vp->val.s = xp, vp->name, namelen); 658 xp += namelen; 659 *xp++ = '='; 660 vp->type = xp - vp->val.s; /* offset to value */ 661 memcpy(xp, val, vallen); 662 if (op != NULL) 663 afree(op, vp->areap); 664 } 665 666 /* 667 * lookup variable (according to (set&LOCAL)), 668 * set its attributes (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL, 669 * LCASEV, UCASEV_AL), and optionally set its value if an assignment. 670 */ 671 struct tbl * 672 typeset(const char *var, Tflag set, Tflag clr, int field, int base) 673 { 674 struct tbl *vp; 675 struct tbl *vpbase, *t; 676 char *tvar; 677 const char *val; 678 int len; 679 680 /* check for valid variable name, search for value */ 681 val = skip_varname(var, false); 682 if (val == var) 683 return (NULL); 684 mkssert(var != NULL); 685 mkssert(*var != 0); 686 if (*val == '[') { 687 if (set_refflag) 688 errorf("%s: reference variable cannot be an array", 689 var); 690 len = array_ref_len(val); 691 if (len == 0) 692 return (NULL); 693 /* IMPORT is only used when the shell starts up and is 694 * setting up its environment. Allow only simple array 695 * references at this time since parameter/command substitution 696 * is preformed on the [expression] which would be a major 697 * security hole. 698 */ 699 if (set & IMPORT) { 700 int i; 701 for (i = 1; i < len - 1; i++) 702 if (!ksh_isdigit(val[i])) 703 return (NULL); 704 } 705 val += len; 706 } 707 if (*val == '=') 708 strndupx(tvar, var, val++ - var, ATEMP); 709 else { 710 /* Importing from original environment: must have an = */ 711 if (set & IMPORT) 712 return (NULL); 713 strdupx(tvar, var, ATEMP); 714 val = NULL; 715 /* handle foo[*] foo (whole array) mapping for R39b */ 716 len = strlen(tvar); 717 if (len > 3 && tvar[len-3] == '[' && tvar[len-2] == '*' && 718 tvar[len-1] == ']') 719 tvar[len-3] = '\0'; 720 } 721 722 /* Prevent typeset from creating a local PATH/ENV/SHELL */ 723 if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0 || 724 strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0)) 725 errorf("%s: restricted", tvar); 726 727 vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) : 728 global(tvar); 729 if (set_refflag == 2 && (vp->flag & (ARRAY|ASSOC)) == ASSOC) 730 vp->flag &= ~ASSOC; 731 else if (set_refflag == 1) { 732 if (vp->flag & ARRAY) { 733 struct tbl *a, *tmp; 734 735 /* Free up entire array */ 736 for (a = vp->u.array; a; ) { 737 tmp = a; 738 a = a->u.array; 739 if (tmp->flag & ALLOC) 740 afree(tmp->val.s, tmp->areap); 741 afree(tmp, tmp->areap); 742 } 743 vp->u.array = NULL; 744 vp->flag &= ~ARRAY; 745 } 746 vp->flag |= ASSOC; 747 } 748 749 set &= ~(LOCAL|LOCAL_COPY); 750 751 vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp; 752 753 /* only allow export flag to be set. AT&T ksh allows any attribute to 754 * be changed which means it can be truncated or modified (-L/-R/-Z/-i) 755 */ 756 if ((vpbase->flag&RDONLY) && 757 (val || clr || (set & ~EXPORT))) 758 /* XXX check calls - is error here ok by POSIX? */ 759 errorf("%s: is read only", tvar); 760 afree(tvar, ATEMP); 761 762 /* most calls are with set/clr == 0 */ 763 if (set | clr) { 764 bool ok = true; 765 766 /* XXX if x[0] isn't set, there will be problems: need to have 767 * one copy of attributes for arrays... 768 */ 769 for (t = vpbase; t; t = t->u.array) { 770 bool fake_assign; 771 char *s = NULL; 772 char *free_me = NULL; 773 774 fake_assign = (t->flag & ISSET) && (!val || t != vp) && 775 ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL)) || 776 ((t->flag & INTEGER) && (clr & INTEGER)) || 777 (!(t->flag & INTEGER) && (set & INTEGER))); 778 if (fake_assign) { 779 if (t->flag & INTEGER) { 780 s = str_val(t); 781 free_me = NULL; 782 } else { 783 s = t->val.s + t->type; 784 free_me = (t->flag & ALLOC) ? t->val.s : 785 NULL; 786 } 787 t->flag &= ~ALLOC; 788 } 789 if (!(t->flag & INTEGER) && (set & INTEGER)) { 790 t->type = 0; 791 t->flag &= ~ALLOC; 792 } 793 t->flag = (t->flag | set) & ~clr; 794 /* Don't change base if assignment is to be done, 795 * in case assignment fails. 796 */ 797 if ((set & INTEGER) && base > 0 && (!val || t != vp)) 798 t->type = base; 799 if (set & (LJUST|RJUST|ZEROFIL)) 800 t->u2.field = field; 801 if (fake_assign) { 802 if (!setstr(t, s, KSH_RETURN_ERROR)) { 803 /* Somewhat arbitrary action here: 804 * zap contents of variable, but keep 805 * the flag settings. 806 */ 807 ok = false; 808 if (t->flag & INTEGER) 809 t->flag &= ~ISSET; 810 else { 811 if (t->flag & ALLOC) 812 afree(t->val.s, t->areap); 813 t->flag &= ~(ISSET|ALLOC); 814 t->type = 0; 815 } 816 } 817 if (free_me) 818 afree(free_me, t->areap); 819 } 820 } 821 if (!ok) 822 errorfz(); 823 } 824 825 if (val != NULL) { 826 if (vp->flag&INTEGER) { 827 /* do not zero base before assignment */ 828 setstr(vp, val, KSH_UNWIND_ERROR | 0x4); 829 /* Done after assignment to override default */ 830 if (base > 0) 831 vp->type = base; 832 } else 833 /* setstr can't fail (readonly check already done) */ 834 setstr(vp, val, KSH_RETURN_ERROR | 0x4); 835 } 836 837 /* only x[0] is ever exported, so use vpbase */ 838 if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) && 839 vpbase->type == 0) 840 exportprep(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null); 841 842 return (vp); 843 } 844 845 /** 846 * Unset a variable. The flags can be: 847 * |1 = tear down entire array 848 * |2 = keep attributes, only unset content 849 */ 850 void 851 unset(struct tbl *vp, int flags) 852 { 853 if (vp->flag & ALLOC) 854 afree(vp->val.s, vp->areap); 855 if ((vp->flag & ARRAY) && (flags & 1)) { 856 struct tbl *a, *tmp; 857 858 /* Free up entire array */ 859 for (a = vp->u.array; a; ) { 860 tmp = a; 861 a = a->u.array; 862 if (tmp->flag & ALLOC) 863 afree(tmp->val.s, tmp->areap); 864 afree(tmp, tmp->areap); 865 } 866 vp->u.array = NULL; 867 } 868 if (flags & 2) { 869 vp->flag &= ~(ALLOC|ISSET); 870 return; 871 } 872 /* If foo[0] is being unset, the remainder of the array is kept... */ 873 vp->flag &= SPECIAL | ((flags & 1) ? 0 : ARRAY|DEFINED); 874 if (vp->flag & SPECIAL) 875 unsetspec(vp); /* responsible for 'unspecial'ing var */ 876 } 877 878 /* return a pointer to the first char past a legal variable name (returns the 879 * argument if there is no legal name, returns a pointer to the terminating 880 * NUL if whole string is legal). 881 */ 882 const char * 883 skip_varname(const char *s, int aok) 884 { 885 int alen; 886 887 if (s && ksh_isalphx(*s)) { 888 while (*++s && ksh_isalnux(*s)) 889 ; 890 if (aok && *s == '[' && (alen = array_ref_len(s))) 891 s += alen; 892 } 893 return (s); 894 } 895 896 /* Return a pointer to the first character past any legal variable name */ 897 const char * 898 skip_wdvarname(const char *s, 899 int aok) /* skip array de-reference? */ 900 { 901 if (s[0] == CHAR && ksh_isalphx(s[1])) { 902 do { 903 s += 2; 904 } while (s[0] == CHAR && ksh_isalnux(s[1])); 905 if (aok && s[0] == CHAR && s[1] == '[') { 906 /* skip possible array de-reference */ 907 const char *p = s; 908 char c; 909 int depth = 0; 910 911 while (1) { 912 if (p[0] != CHAR) 913 break; 914 c = p[1]; 915 p += 2; 916 if (c == '[') 917 depth++; 918 else if (c == ']' && --depth == 0) { 919 s = p; 920 break; 921 } 922 } 923 } 924 } 925 return (s); 926 } 927 928 /* Check if coded string s is a variable name */ 929 int 930 is_wdvarname(const char *s, int aok) 931 { 932 const char *p = skip_wdvarname(s, aok); 933 934 return (p != s && p[0] == EOS); 935 } 936 937 /* Check if coded string s is a variable assignment */ 938 int 939 is_wdvarassign(const char *s) 940 { 941 const char *p = skip_wdvarname(s, true); 942 943 return (p != s && p[0] == CHAR && p[1] == '='); 944 } 945 946 /* 947 * Make the exported environment from the exported names in the dictionary. 948 */ 949 char ** 950 makenv(void) 951 { 952 struct block *l; 953 XPtrV denv; 954 struct tbl *vp, **vpp; 955 int i; 956 957 XPinit(denv, 64); 958 for (l = e->loc; l != NULL; l = l->next) 959 for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; ) 960 if ((vp = *vpp++) != NULL && 961 (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) { 962 struct block *l2; 963 struct tbl *vp2; 964 uint32_t h = hash(vp->name); 965 966 /* unexport any redefined instances */ 967 for (l2 = l->next; l2 != NULL; l2 = l2->next) { 968 vp2 = ktsearch(&l2->vars, vp->name, h); 969 if (vp2 != NULL) 970 vp2->flag &= ~EXPORT; 971 } 972 if ((vp->flag&INTEGER)) { 973 /* integer to string */ 974 char *val; 975 val = str_val(vp); 976 vp->flag &= ~(INTEGER|RDONLY|SPECIAL); 977 /* setstr can't fail here */ 978 setstr(vp, val, KSH_RETURN_ERROR); 979 } 980 XPput(denv, vp->val.s); 981 } 982 XPput(denv, NULL); 983 return ((char **)XPclose(denv)); 984 } 985 986 /* Bob Jenkins' one-at-a-time hash */ 987 static uint32_t 988 oaathash_update(register uint32_t h, register const uint8_t *cp, 989 register size_t n) 990 { 991 while (n--) { 992 h += *cp++; 993 h += h << 10; 994 h ^= h >> 6; 995 } 996 997 return (h); 998 } 999 1000 static uint32_t 1001 oaathash_finalise(register uint32_t h) 1002 { 1003 h += h << 3; 1004 h ^= h >> 11; 1005 h += h << 15; 1006 1007 return (h); 1008 } 1009 1010 uint32_t 1011 oaathash_full(register const uint8_t *bp) 1012 { 1013 register uint32_t h = 0; 1014 register uint8_t c; 1015 1016 while ((c = *bp++)) { 1017 h += c; 1018 h += h << 10; 1019 h ^= h >> 6; 1020 } 1021 1022 return (oaathash_finalise(h)); 1023 } 1024 1025 void 1026 change_random(const void *vp, size_t n) 1027 { 1028 register uint32_t h = 0x100; 1029 #if defined(__OpenBSD__) 1030 int mib[2]; 1031 uint8_t k[3]; 1032 size_t klen; 1033 #endif 1034 1035 kshstate_v.cr_dp = vp; 1036 kshstate_v.cr_dsz = n; 1037 gettimeofday(&kshstate_v.cr_tv, NULL); 1038 h = oaathash_update(oaathash_update(h, (void *)&kshstate_v, 1039 sizeof(kshstate_v)), vp, n); 1040 kshstate_v.lcg_state_ = oaathash_finalise(h); 1041 1042 #if defined(__OpenBSD__) 1043 /* OpenBSD, MirBSD: proper kernel entropy comes at zero cost */ 1044 1045 mib[0] = CTL_KERN; 1046 mib[1] = KERN_ARND; 1047 klen = sizeof(k); 1048 sysctl(mib, 2, k, &klen, &kshstate_v.lcg_state_, 1049 sizeof(kshstate_v.lcg_state_)); 1050 /* we ignore failures and take in k anyway */ 1051 h = oaathash_update(h, k, sizeof(k)); 1052 kshstate_v.lcg_state_ = oaathash_finalise(h); 1053 #elif defined(MKSH_A4PB) 1054 /* forced by the user to use arc4random_pushb(3) Cygwin? */ 1055 { 1056 uint32_t prv; 1057 1058 prv = arc4random_pushb(&kshstate_v.lcg_state_, 1059 sizeof(kshstate_v.lcg_state_)); 1060 h = oaathash_update(h, &prv, sizeof(prv)); 1061 } 1062 kshstate_v.lcg_state_ = oaathash_finalise(h); 1063 #endif 1064 } 1065 1066 /* 1067 * handle special variables with side effects - PATH, SECONDS. 1068 */ 1069 1070 /* Test if name is a special parameter */ 1071 static int 1072 special(const char *name) 1073 { 1074 struct tbl *tp; 1075 1076 tp = ktsearch(&specials, name, hash(name)); 1077 return (tp && (tp->flag & ISSET) ? tp->type : V_NONE); 1078 } 1079 1080 /* Make a variable non-special */ 1081 static void 1082 unspecial(const char *name) 1083 { 1084 struct tbl *tp; 1085 1086 tp = ktsearch(&specials, name, hash(name)); 1087 if (tp) 1088 ktdelete(tp); 1089 } 1090 1091 static time_t seconds; /* time SECONDS last set */ 1092 static int user_lineno; /* what user set $LINENO to */ 1093 1094 static void 1095 getspec(struct tbl *vp) 1096 { 1097 register mksh_ari_t i; 1098 int st; 1099 1100 switch ((st = special(vp->name))) { 1101 case V_SECONDS: 1102 /* 1103 * On start up the value of SECONDS is used before 1104 * it has been set - don't do anything in this case 1105 * (see initcoms[] in main.c). 1106 */ 1107 if (vp->flag & ISSET) { 1108 struct timeval tv; 1109 1110 gettimeofday(&tv, NULL); 1111 i = tv.tv_sec - seconds; 1112 } else 1113 return; 1114 break; 1115 case V_RANDOM: 1116 /* 1117 * this is the same Linear Congruential PRNG as Borland 1118 * C/C++ allegedly uses in its built-in rand() function 1119 */ 1120 i = ((kshstate_v.lcg_state_ = 1121 22695477 * kshstate_v.lcg_state_ + 1) >> 16) & 0x7FFF; 1122 break; 1123 case V_HISTSIZE: 1124 i = histsize; 1125 break; 1126 case V_OPTIND: 1127 i = user_opt.uoptind; 1128 break; 1129 case V_LINENO: 1130 i = current_lineno + user_lineno; 1131 break; 1132 case V_COLUMNS: 1133 case V_LINES: 1134 /* 1135 * Do NOT export COLUMNS/LINES. Many applications 1136 * check COLUMNS/LINES before checking ws.ws_col/row, 1137 * so if the app is started with C/L in the environ 1138 * and the window is then resized, the app won't 1139 * see the change cause the environ doesn't change. 1140 */ 1141 change_winsz(); 1142 i = st == V_COLUMNS ? x_cols : x_lins; 1143 break; 1144 default: 1145 /* do nothing, do not touch vp at all */ 1146 return; 1147 } 1148 vp->flag &= ~SPECIAL; 1149 setint(vp, i); 1150 vp->flag |= SPECIAL; 1151 } 1152 1153 static void 1154 setspec(struct tbl *vp) 1155 { 1156 mksh_ari_t i; 1157 char *s; 1158 int st; 1159 1160 switch ((st = special(vp->name))) { 1161 case V_PATH: 1162 if (path) 1163 afree(path, APERM); 1164 s = str_val(vp); 1165 strdupx(path, s, APERM); 1166 flushcom(1); /* clear tracked aliases */ 1167 return; 1168 case V_IFS: 1169 setctypes(s = str_val(vp), C_IFS); 1170 ifs0 = *s; 1171 return; 1172 case V_TMPDIR: 1173 if (tmpdir) { 1174 afree(tmpdir, APERM); 1175 tmpdir = NULL; 1176 } 1177 /* Use tmpdir iff it is an absolute path, is writable and 1178 * searchable and is a directory... 1179 */ 1180 { 1181 struct stat statb; 1182 1183 s = str_val(vp); 1184 if (s[0] == '/' && access(s, W_OK|X_OK) == 0 && 1185 stat(s, &statb) == 0 && S_ISDIR(statb.st_mode)) 1186 strdupx(tmpdir, s, APERM); 1187 } 1188 break; 1189 #if HAVE_PERSISTENT_HISTORY 1190 case V_HISTFILE: 1191 sethistfile(str_val(vp)); 1192 break; 1193 #endif 1194 case V_TMOUT: 1195 /* AT&T ksh seems to do this (only listen if integer) */ 1196 if (vp->flag & INTEGER) 1197 ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0; 1198 break; 1199 1200 /* common sub-cases */ 1201 case V_OPTIND: 1202 case V_HISTSIZE: 1203 case V_COLUMNS: 1204 case V_LINES: 1205 case V_RANDOM: 1206 case V_SECONDS: 1207 case V_LINENO: 1208 vp->flag &= ~SPECIAL; 1209 i = intval(vp); 1210 vp->flag |= SPECIAL; 1211 break; 1212 default: 1213 /* do nothing, do not touch vp at all */ 1214 return; 1215 } 1216 1217 /* process the singular parts of the common cases */ 1218 1219 switch (st) { 1220 case V_OPTIND: 1221 getopts_reset((int)i); 1222 break; 1223 case V_HISTSIZE: 1224 sethistsize((int)i); 1225 break; 1226 case V_COLUMNS: 1227 if (i >= MIN_COLS) 1228 x_cols = i; 1229 break; 1230 case V_LINES: 1231 if (i >= MIN_LINS) 1232 x_lins = i; 1233 break; 1234 case V_RANDOM: 1235 /* 1236 * mksh R39d+ no longer has the traditional repeatability 1237 * of $RANDOM sequences, but always retains state 1238 */ 1239 change_random(&i, sizeof(i)); 1240 break; 1241 case V_SECONDS: 1242 { 1243 struct timeval tv; 1244 1245 gettimeofday(&tv, NULL); 1246 seconds = tv.tv_sec - i; 1247 } 1248 break; 1249 case V_LINENO: 1250 /* The -1 is because line numbering starts at 1. */ 1251 user_lineno = (unsigned int)i - current_lineno - 1; 1252 break; 1253 } 1254 } 1255 1256 static void 1257 unsetspec(struct tbl *vp) 1258 { 1259 switch (special(vp->name)) { 1260 case V_PATH: 1261 if (path) 1262 afree(path, APERM); 1263 strdupx(path, def_path, APERM); 1264 flushcom(1); /* clear tracked aliases */ 1265 break; 1266 case V_IFS: 1267 setctypes(" \t\n", C_IFS); 1268 ifs0 = ' '; 1269 break; 1270 case V_TMPDIR: 1271 /* should not become unspecial */ 1272 if (tmpdir) { 1273 afree(tmpdir, APERM); 1274 tmpdir = NULL; 1275 } 1276 break; 1277 case V_LINENO: 1278 case V_RANDOM: 1279 case V_SECONDS: 1280 case V_TMOUT: /* AT&T ksh leaves previous value in place */ 1281 unspecial(vp->name); 1282 break; 1283 1284 /* 1285 * AT&T ksh man page says OPTIND, OPTARG and _ lose special 1286 * meaning, but OPTARG does not (still set by getopts) and _ is 1287 * also still set in various places. Don't know what AT&T does 1288 * for HISTSIZE, HISTFILE. Unsetting these in AT&T ksh does not 1289 * loose the 'specialness': IFS, COLUMNS, PATH, TMPDIR 1290 */ 1291 } 1292 } 1293 1294 /* 1295 * Search for (and possibly create) a table entry starting with 1296 * vp, indexed by val. 1297 */ 1298 static struct tbl * 1299 arraysearch(struct tbl *vp, uint32_t val) 1300 { 1301 struct tbl *prev, *curr, *news; 1302 size_t len; 1303 1304 vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC; 1305 /* The table entry is always [0] */ 1306 if (val == 0) 1307 return (vp); 1308 prev = vp; 1309 curr = vp->u.array; 1310 while (curr && curr->ua.index < val) { 1311 prev = curr; 1312 curr = curr->u.array; 1313 } 1314 if (curr && curr->ua.index == val) { 1315 if (curr->flag&ISSET) 1316 return (curr); 1317 news = curr; 1318 } else 1319 news = NULL; 1320 len = strlen(vp->name) + 1; 1321 if (!news) { 1322 news = alloc(offsetof(struct tbl, name[0]) + len, vp->areap); 1323 memcpy(news->name, vp->name, len); 1324 } 1325 news->flag = (vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL)) | AINDEX; 1326 news->type = vp->type; 1327 news->areap = vp->areap; 1328 news->u2.field = vp->u2.field; 1329 news->ua.index = val; 1330 1331 if (curr != news) { /* not reusing old array entry */ 1332 prev->u.array = news; 1333 news->u.array = curr; 1334 } 1335 return (news); 1336 } 1337 1338 /* Return the length of an array reference (eg, [1+2]) - cp is assumed 1339 * to point to the open bracket. Returns 0 if there is no matching closing 1340 * bracket. 1341 */ 1342 int 1343 array_ref_len(const char *cp) 1344 { 1345 const char *s = cp; 1346 int c; 1347 int depth = 0; 1348 1349 while ((c = *s++) && (c != ']' || --depth)) 1350 if (c == '[') 1351 depth++; 1352 if (!c) 1353 return (0); 1354 return (s - cp); 1355 } 1356 1357 /* 1358 * Make a copy of the base of an array name 1359 */ 1360 char * 1361 arrayname(const char *str) 1362 { 1363 const char *p; 1364 char *rv; 1365 1366 if ((p = cstrchr(str, '[')) == 0) 1367 /* Shouldn't happen, but why worry? */ 1368 strdupx(rv, str, ATEMP); 1369 else 1370 strndupx(rv, str, p - str, ATEMP); 1371 1372 return (rv); 1373 } 1374 1375 /* set (or overwrite, if reset) the array variable var to the values in vals */ 1376 mksh_uari_t 1377 set_array(const char *var, bool reset, const char **vals) 1378 { 1379 struct tbl *vp, *vq; 1380 mksh_uari_t i; 1381 const char *ccp; 1382 #ifndef MKSH_SMALL 1383 char *cp; 1384 mksh_uari_t j; 1385 #endif 1386 1387 /* to get local array, use "typeset foo; set -A foo" */ 1388 vp = global(var); 1389 1390 /* Note: AT&T ksh allows set -A but not set +A of a read-only var */ 1391 if ((vp->flag&RDONLY)) 1392 errorf("%s: is read only", var); 1393 /* This code is quite non-optimal */ 1394 if (reset) 1395 /* trash existing values and attributes */ 1396 unset(vp, 1); 1397 /* todo: would be nice for assignment to completely succeed or 1398 * completely fail. Only really effects integer arrays: 1399 * evaluation of some of vals[] may fail... 1400 */ 1401 i = 0; 1402 #ifndef MKSH_SMALL 1403 j = 0; 1404 #else 1405 #define j i 1406 #endif 1407 while ((ccp = vals[i])) { 1408 #ifndef MKSH_SMALL 1409 if (*ccp == '[') { 1410 int level = 0; 1411 1412 while (*ccp) { 1413 if (*ccp == ']' && --level == 0) 1414 break; 1415 if (*ccp == '[') 1416 ++level; 1417 ++ccp; 1418 } 1419 if (*ccp == ']' && level == 0 && ccp[1] == '=') { 1420 strndupx(cp, vals[i] + 1, ccp - (vals[i] + 1), 1421 ATEMP); 1422 evaluate(substitute(cp, 0), (mksh_ari_t *)&j, 1423 KSH_UNWIND_ERROR, true); 1424 afree(cp, ATEMP); 1425 ccp += 2; 1426 } else 1427 ccp = vals[i]; 1428 } 1429 #endif 1430 1431 vq = arraysearch(vp, j); 1432 /* would be nice to deal with errors here... (see above) */ 1433 setstr(vq, ccp, KSH_RETURN_ERROR); 1434 i++; 1435 #ifndef MKSH_SMALL 1436 j++; 1437 #endif 1438 } 1439 1440 return (i); 1441 } 1442 1443 void 1444 change_winsz(void) 1445 { 1446 if (x_lins < 0) { 1447 /* first time initialisation */ 1448 #ifdef TIOCGWINSZ 1449 if (tty_fd < 0) 1450 /* non-FTALKING, try to get an fd anyway */ 1451 tty_init(false, false); 1452 #endif 1453 x_cols = -1; 1454 } 1455 1456 #ifdef TIOCGWINSZ 1457 /* check if window size has changed */ 1458 if (tty_fd >= 0) { 1459 struct winsize ws; 1460 1461 if (ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) { 1462 if (ws.ws_col) 1463 x_cols = ws.ws_col; 1464 if (ws.ws_row) 1465 x_lins = ws.ws_row; 1466 } 1467 } 1468 #endif 1469 1470 /* bounds check for sane values, use defaults otherwise */ 1471 if (x_cols < MIN_COLS) 1472 x_cols = 80; 1473 if (x_lins < MIN_LINS) 1474 x_lins = 24; 1475 1476 #ifdef SIGWINCH 1477 got_winch = 0; 1478 #endif 1479 } 1480 1481 uint32_t 1482 evilhash(const char *s) 1483 { 1484 register uint32_t h = 0x100; 1485 1486 h = oaathash_update(h, (void *)&kshstate_f, sizeof(kshstate_f)); 1487 kshstate_f.h = oaathash_full((const uint8_t *)s); 1488 return (oaathash_finalise(oaathash_update(h, 1489 (void *)&kshstate_f.h, sizeof(kshstate_f.h)))); 1490 } 1491