1 /* $OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $ */ 2 3 #include "sh.h" 4 #include <time.h> 5 #include "ksh_limval.h" 6 #include <sys/stat.h> 7 #include <ctype.h> 8 9 /* 10 * Variables 11 * 12 * WARNING: unreadable code, needs a rewrite 13 * 14 * if (flag&INTEGER), val.i contains integer value, and type contains base. 15 * otherwise, (val.s + type) contains string value. 16 * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting. 17 */ 18 static struct tbl vtemp; 19 static struct table specials; 20 static char *formatstr(struct tbl *, const char *); 21 static void export(struct tbl *, const char *); 22 static int special(const char *); 23 static void unspecial(const char *); 24 static void getspec(struct tbl *); 25 static void setspec(struct tbl *); 26 static void unsetspec(struct tbl *); 27 static struct tbl *arraysearch(struct tbl *, int); 28 29 /* 30 * create a new block for function calls and simple commands 31 * assume caller has allocated and set up e->loc 32 */ 33 void 34 newblock(void) 35 { 36 struct block *l; 37 static char *const empty[] = {null}; 38 39 l = (struct block *) alloc(sizeof(struct block), ATEMP); 40 l->flags = 0; 41 ainit(&l->area); /* todo: could use e->area (l->area => l->areap) */ 42 if (!e->loc) { 43 l->argc = 0; 44 l->argv = (char **) empty; 45 } else { 46 l->argc = e->loc->argc; 47 l->argv = e->loc->argv; 48 } 49 l->exit = l->error = NULL; 50 ktinit(&l->vars, &l->area, 0); 51 ktinit(&l->funs, &l->area, 0); 52 l->next = e->loc; 53 e->loc = l; 54 } 55 56 /* 57 * pop a block handling special variables 58 */ 59 void 60 popblock(void) 61 { 62 struct block *l = e->loc; 63 struct tbl *vp, **vpp = l->vars.tbls, *vq; 64 int i; 65 66 e->loc = l->next; /* pop block */ 67 for (i = l->vars.size; --i >= 0; ) 68 if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) { 69 if ((vq = global(vp->name))->flag & ISSET) 70 setspec(vq); 71 else 72 unsetspec(vq); 73 } 74 if (l->flags & BF_DOGETOPTS) 75 user_opt = l->getopts_state; 76 afreeall(&l->area); 77 afree(l, ATEMP); 78 } 79 80 /* called by main() to initialize variable data structures */ 81 void 82 initvar(void) 83 { 84 static const struct { 85 const char *name; 86 int v; 87 } names[] = { 88 { "COLUMNS", V_COLUMNS }, 89 { "IFS", V_IFS }, 90 { "OPTIND", V_OPTIND }, 91 { "PATH", V_PATH }, 92 { "POSIXLY_CORRECT", V_POSIXLY_CORRECT }, 93 { "TMPDIR", V_TMPDIR }, 94 #ifdef HISTORY 95 { "HISTFILE", V_HISTFILE }, 96 { "HISTSIZE", V_HISTSIZE }, 97 #endif /* HISTORY */ 98 #ifdef EDIT 99 { "EDITOR", V_EDITOR }, 100 { "VISUAL", V_VISUAL }, 101 #endif /* EDIT */ 102 { "MAIL", V_MAIL }, 103 { "MAILCHECK", V_MAILCHECK }, 104 { "MAILPATH", V_MAILPATH }, 105 { "RANDOM", V_RANDOM }, 106 { "SECONDS", V_SECONDS }, 107 { "TMOUT", V_TMOUT }, 108 { "LINENO", V_LINENO }, 109 { (char *) 0, 0 } 110 }; 111 int i; 112 struct tbl *tp; 113 114 ktinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */ 115 for (i = 0; names[i].name; i++) { 116 tp = ktenter(&specials, names[i].name, hash(names[i].name)); 117 tp->flag = DEFINED|ISSET; 118 tp->type = names[i].v; 119 } 120 } 121 122 /* Used to calculate an array index for global()/local(). Sets *arrayp to 123 * non-zero if this is an array, sets *valp to the array index, returns 124 * the basename of the array. 125 */ 126 static const char * 127 array_index_calc(const char *n, bool *arrayp, int *valp) 128 { 129 const char *p; 130 int len; 131 132 *arrayp = false; 133 p = skip_varname(n, false); 134 if (p != n && *p == '[' && (len = array_ref_len(p))) { 135 char *sub, *tmp; 136 long rval; 137 138 /* Calculate the value of the subscript */ 139 *arrayp = true; 140 tmp = str_nsave(p+1, len-2, ATEMP); 141 sub = substitute(tmp, 0); 142 afree(tmp, ATEMP); 143 n = str_nsave(n, p - n, ATEMP); 144 evaluate(sub, &rval, KSH_UNWIND_ERROR, true); 145 if (rval < 0 || rval > ARRAYMAX) 146 errorf("%s: subscript %ld out of range", n, rval); 147 *valp = rval; 148 afree(sub, ATEMP); 149 } 150 return n; 151 } 152 153 /* 154 * Search for variable, if not found create globally. 155 */ 156 struct tbl * 157 global(const char *n) 158 { 159 struct block *l = e->loc; 160 struct tbl *vp; 161 int c; 162 unsigned int h; 163 bool array; 164 int val; 165 166 /* Check to see if this is an array */ 167 n = array_index_calc(n, &array, &val); 168 h = hash(n); 169 c = n[0]; 170 if (!letter(c)) { 171 if (array) 172 errorf("bad substitution"); 173 vp = &vtemp; 174 vp->flag = DEFINED; 175 vp->type = 0; 176 vp->areap = ATEMP; 177 *vp->name = c; 178 if (digit(c)) { 179 for (c = 0; digit(*n); n++) 180 c = c*10 + *n-'0'; 181 if (c <= l->argc) 182 /* setstr can't fail here */ 183 setstr(vp, l->argv[c], KSH_RETURN_ERROR); 184 vp->flag |= RDONLY; 185 return vp; 186 } 187 vp->flag |= RDONLY; 188 if (n[1] != '\0') 189 return vp; 190 vp->flag |= ISSET|INTEGER; 191 switch (c) { 192 case '$': 193 vp->val.i = kshpid; 194 break; 195 case '!': 196 /* If no job, expand to nothing */ 197 if ((vp->val.i = j_async()) == 0) 198 vp->flag &= ~(ISSET|INTEGER); 199 break; 200 case '?': 201 vp->val.i = exstat; 202 break; 203 case '#': 204 vp->val.i = l->argc; 205 break; 206 case '-': 207 vp->flag &= ~INTEGER; 208 vp->val.s = getoptions(); 209 break; 210 default: 211 vp->flag &= ~(ISSET|INTEGER); 212 } 213 return vp; 214 } 215 for (l = e->loc; ; l = l->next) { 216 vp = ktsearch(&l->vars, n, h); 217 if (vp != NULL) { 218 if (array) 219 return arraysearch(vp, val); 220 else 221 return vp; 222 } 223 if (l->next == NULL) 224 break; 225 } 226 vp = ktenter(&l->vars, n, h); 227 if (array) 228 vp = arraysearch(vp, val); 229 vp->flag |= DEFINED; 230 if (special(n)) 231 vp->flag |= SPECIAL; 232 return vp; 233 } 234 235 /* 236 * Search for local variable, if not found create locally. 237 */ 238 struct tbl * 239 local(const char *n, bool copy) 240 { 241 struct block *l = e->loc; 242 struct tbl *vp; 243 unsigned int h; 244 bool array; 245 int val; 246 247 /* Check to see if this is an array */ 248 n = array_index_calc(n, &array, &val); 249 h = hash(n); 250 if (!letter(*n)) { 251 vp = &vtemp; 252 vp->flag = DEFINED|RDONLY; 253 vp->type = 0; 254 vp->areap = ATEMP; 255 return vp; 256 } 257 vp = ktenter(&l->vars, n, h); 258 if (copy && !(vp->flag & DEFINED)) { 259 struct block *ll = l; 260 struct tbl *vq = (struct tbl *) 0; 261 262 while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h))) 263 ; 264 if (vq) { 265 vp->flag |= vq->flag & 266 (EXPORT | INTEGER | RDONLY | LJUST | RJUST | 267 ZEROFIL | LCASEV | UCASEV_AL | INT_U | INT_L); 268 if (vq->flag & INTEGER) 269 vp->type = vq->type; 270 vp->u2.field = vq->u2.field; 271 } 272 } 273 if (array) 274 vp = arraysearch(vp, val); 275 vp->flag |= DEFINED; 276 if (special(n)) 277 vp->flag |= SPECIAL; 278 return vp; 279 } 280 281 /* get variable string value */ 282 char * 283 str_val(struct tbl *vp) 284 { 285 char *s; 286 287 if ((vp->flag&SPECIAL)) 288 getspec(vp); 289 if (!(vp->flag&ISSET)) 290 s = null; /* special to dollar() */ 291 else if (!(vp->flag&INTEGER)) /* string source */ 292 s = vp->val.s + vp->type; 293 else { /* integer source */ 294 /* worst case number length is when base=2, so use BITS(long) */ 295 /* minus base # number null */ 296 char strbuf[1 + 2 + 1 + BITS(long) + 1]; 297 const char *digits = (vp->flag & UCASEV_AL) ? 298 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : 299 "0123456789abcdefghijklmnopqrstuvwxyz"; 300 unsigned long n; 301 int base; 302 303 s = strbuf + sizeof(strbuf); 304 if (vp->flag & INT_U) 305 n = (unsigned long) vp->val.i; 306 else 307 n = (vp->val.i < 0) ? -vp->val.i : vp->val.i; 308 base = (vp->type == 0) ? 10 : vp->type; 309 310 *--s = '\0'; 311 do { 312 *--s = digits[n % base]; 313 n /= base; 314 } while (n != 0); 315 if (base != 10) { 316 *--s = '#'; 317 *--s = digits[base % 10]; 318 if (base >= 10) 319 *--s = digits[base / 10]; 320 } 321 if (!(vp->flag & INT_U) && vp->val.i < 0) 322 *--s = '-'; 323 if (vp->flag & (RJUST|LJUST)) /* case already dealt with */ 324 s = formatstr(vp, s); 325 else 326 s = str_save(s, ATEMP); 327 } 328 return s; 329 } 330 331 /* get variable integer value, with error checking */ 332 long 333 intval(struct tbl *vp) 334 { 335 long num; 336 int base; 337 338 base = getint(vp, &num, false); 339 if (base == -1) 340 /* XXX check calls - is error here ok by POSIX? */ 341 errorf("%s: bad number", str_val(vp)); 342 return num; 343 } 344 345 /* set variable to string value */ 346 int 347 setstr(struct tbl *vq, const char *s, int error_ok) 348 { 349 const char *fs = NULL; 350 int no_ro_check = error_ok & 0x4; 351 error_ok &= ~0x4; 352 if ((vq->flag & RDONLY) && !no_ro_check) { 353 warningf(true, "%s: is read only", vq->name); 354 if (!error_ok) 355 errorf(null); 356 return 0; 357 } 358 if (!(vq->flag&INTEGER)) { /* string dest */ 359 if ((vq->flag&ALLOC)) { 360 /* debugging */ 361 if (s >= vq->val.s && 362 s <= vq->val.s + strlen(vq->val.s)) 363 internal_errorf(true, 364 "setstr: %s=%s: assigning to self", 365 vq->name, s); 366 afree((void*)vq->val.s, vq->areap); 367 } 368 vq->flag &= ~(ISSET|ALLOC); 369 vq->type = 0; 370 if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST))) 371 fs = s = formatstr(vq, s); 372 if ((vq->flag&EXPORT)) 373 export(vq, s); 374 else { 375 vq->val.s = str_save(s, vq->areap); 376 vq->flag |= ALLOC; 377 } 378 } else { /* integer dest */ 379 if (!v_evaluate(vq, s, error_ok, true)) 380 return 0; 381 } 382 vq->flag |= ISSET; 383 if ((vq->flag&SPECIAL)) 384 setspec(vq); 385 if (fs) 386 afree((char *)fs, ATEMP); 387 return 1; 388 } 389 390 /* set variable to integer */ 391 void 392 setint(struct tbl *vq, long int n) 393 { 394 if (!(vq->flag&INTEGER)) { 395 struct tbl *vp = &vtemp; 396 vp->flag = (ISSET|INTEGER); 397 vp->type = 0; 398 vp->areap = ATEMP; 399 vp->val.i = n; 400 /* setstr can't fail here */ 401 setstr(vq, str_val(vp), KSH_RETURN_ERROR); 402 } else 403 vq->val.i = n; 404 vq->flag |= ISSET; 405 if ((vq->flag&SPECIAL)) 406 setspec(vq); 407 } 408 409 int 410 getint(struct tbl *vp, long int *nump, bool arith) 411 { 412 char *s; 413 int c; 414 int base, neg; 415 int have_base = 0; 416 long num; 417 418 if (vp->flag&SPECIAL) 419 getspec(vp); 420 /* XXX is it possible for ISSET to be set and val.s to be 0? */ 421 if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL)) 422 return -1; 423 if (vp->flag&INTEGER) { 424 *nump = vp->val.i; 425 return vp->type; 426 } 427 s = vp->val.s + vp->type; 428 if (s == NULL) /* redundant given initial test */ 429 s = null; 430 base = 10; 431 num = 0; 432 neg = 0; 433 if (arith && *s == '0' && *(s+1)) { 434 s++; 435 if (*s == 'x' || *s == 'X') { 436 s++; 437 base = 16; 438 } else if (vp->flag & ZEROFIL) { 439 while (*s == '0') 440 s++; 441 } else 442 base = 8; 443 have_base++; 444 } 445 for (c = *s++; c ; c = *s++) { 446 if (c == '-') { 447 neg++; 448 } else if (c == '#') { 449 base = (int) num; 450 if (have_base || base < 2 || base > 36) 451 return -1; 452 num = 0; 453 have_base = 1; 454 } else if (letnum(c)) { 455 if (isdigit(c)) 456 c -= '0'; 457 else if (islower(c)) 458 c -= 'a' - 10; /* todo: assumes ascii */ 459 else if (isupper(c)) 460 c -= 'A' - 10; /* todo: assumes ascii */ 461 else 462 c = -1; /* _: force error */ 463 if (c < 0 || c >= base) 464 return -1; 465 num = num * base + c; 466 } else 467 return -1; 468 } 469 if (neg) 470 num = -num; 471 *nump = num; 472 return base; 473 } 474 475 /* convert variable vq to integer variable, setting its value from vp 476 * (vq and vp may be the same) 477 */ 478 struct tbl * 479 setint_v(struct tbl *vq, struct tbl *vp, bool arith) 480 { 481 int base; 482 long num; 483 484 if ((base = getint(vp, &num, arith)) == -1) 485 return NULL; 486 if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) { 487 vq->flag &= ~ALLOC; 488 afree(vq->val.s, vq->areap); 489 } 490 vq->val.i = num; 491 if (vq->type == 0) /* default base */ 492 vq->type = base; 493 vq->flag |= ISSET|INTEGER; 494 if (vq->flag&SPECIAL) 495 setspec(vq); 496 return vq; 497 } 498 499 static char * 500 formatstr(struct tbl *vp, const char *s) 501 { 502 int olen, nlen; 503 char *p, *q; 504 505 olen = strlen(s); 506 507 if (vp->flag & (RJUST|LJUST)) { 508 if (!vp->u2.field) /* default field width */ 509 vp->u2.field = olen; 510 nlen = vp->u2.field; 511 } else 512 nlen = olen; 513 514 p = (char *) alloc(nlen + 1, ATEMP); 515 if (vp->flag & (RJUST|LJUST)) { 516 int slen; 517 518 if (vp->flag & RJUST) { 519 const char *q = s + olen; 520 /* strip trailing spaces (at&t ksh uses q[-1] == ' ') */ 521 while (q > s && isspace(q[-1])) 522 --q; 523 slen = q - s; 524 if (slen > vp->u2.field) { 525 s += slen - vp->u2.field; 526 slen = vp->u2.field; 527 } 528 shf_snprintf(p, nlen + 1, 529 ((vp->flag & ZEROFIL) && digit(*s)) ? 530 "%0*s%.*s" : "%*s%.*s", 531 vp->u2.field - slen, null, slen, s); 532 } else { 533 /* strip leading spaces/zeros */ 534 while (isspace(*s)) 535 s++; 536 if (vp->flag & ZEROFIL) 537 while (*s == '0') 538 s++; 539 shf_snprintf(p, nlen + 1, "%-*.*s", 540 vp->u2.field, vp->u2.field, s); 541 } 542 } else 543 memcpy(p, s, olen + 1); 544 545 if (vp->flag & UCASEV_AL) { 546 for (q = p; *q; q++) 547 if (islower(*q)) 548 *q = toupper(*q); 549 } else if (vp->flag & LCASEV) { 550 for (q = p; *q; q++) 551 if (isupper(*q)) 552 *q = tolower(*q); 553 } 554 555 return p; 556 } 557 558 /* 559 * make vp->val.s be "name=value" for quick exporting. 560 */ 561 static void 562 export(struct tbl *vp, const char *val) 563 { 564 char *xp; 565 char *op = (vp->flag&ALLOC) ? vp->val.s : NULL; 566 int namelen = strlen(vp->name); 567 int vallen = strlen(val) + 1; 568 569 vp->flag |= ALLOC; 570 xp = (char*)alloc(namelen + 1 + vallen, vp->areap); 571 memcpy(vp->val.s = xp, vp->name, namelen); 572 xp += namelen; 573 *xp++ = '='; 574 vp->type = xp - vp->val.s; /* offset to value */ 575 memcpy(xp, val, vallen); 576 if (op != NULL) 577 afree((void*)op, vp->areap); 578 } 579 580 /* 581 * lookup variable (according to (set&LOCAL)), 582 * set its attributes (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL, 583 * LCASEV, UCASEV_AL), and optionally set its value if an assignment. 584 */ 585 struct tbl * 586 typeset(const char *var, Tflag set, Tflag clr, int field, int base) 587 { 588 struct tbl *vp; 589 struct tbl *vpbase, *t; 590 char *tvar; 591 const char *val; 592 593 /* check for valid variable name, search for value */ 594 val = skip_varname(var, false); 595 if (val == var) 596 return NULL; 597 if (*val == '[') { 598 int len; 599 600 len = array_ref_len(val); 601 if (len == 0) 602 return NULL; 603 /* IMPORT is only used when the shell starts up and is 604 * setting up its environment. Allow only simple array 605 * references at this time since parameter/command substitution 606 * is preformed on the [expression], which would be a major 607 * security hole. 608 */ 609 if (set & IMPORT) { 610 int i; 611 for (i = 1; i < len - 1; i++) 612 if (!digit(val[i])) 613 return NULL; 614 } 615 val += len; 616 } 617 if (*val == '=') 618 tvar = str_nsave(var, val++ - var, ATEMP); 619 else { 620 /* Importing from original environment: must have an = */ 621 if (set & IMPORT) 622 return NULL; 623 tvar = (char *) var; 624 val = NULL; 625 } 626 627 /* Prevent typeset from creating a local PATH/ENV/SHELL */ 628 if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0 || 629 strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0)) 630 errorf("%s: restricted", tvar); 631 632 vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) : 633 global(tvar); 634 set &= ~(LOCAL|LOCAL_COPY); 635 636 vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp; 637 638 /* only allow export flag to be set. at&t ksh allows any attribute to 639 * be changed, which means it can be truncated or modified 640 * (-L/-R/-Z/-i). 641 */ 642 if ((vpbase->flag&RDONLY) && 643 (val || clr || (set & ~EXPORT))) 644 /* XXX check calls - is error here ok by POSIX? */ 645 errorf("%s: is read only", tvar); 646 if (val) 647 afree(tvar, ATEMP); 648 649 /* most calls are with set/clr == 0 */ 650 if (set | clr) { 651 int ok = 1; 652 /* XXX if x[0] isn't set, there will be problems: need to have 653 * one copy of attributes for arrays... 654 */ 655 for (t = vpbase; t; t = t->u.array) { 656 int fake_assign; 657 char *s = NULL; 658 char *free_me = NULL; 659 660 fake_assign = (t->flag & ISSET) && (!val || t != vp) && 661 ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL)) || 662 ((t->flag & INTEGER) && (clr & INTEGER)) || 663 (!(t->flag & INTEGER) && (set & INTEGER))); 664 if (fake_assign) { 665 if (t->flag & INTEGER) { 666 s = str_val(t); 667 free_me = (char *) 0; 668 } else { 669 s = t->val.s + t->type; 670 free_me = (t->flag & ALLOC) ? t->val.s : 671 (char *) 0; 672 } 673 t->flag &= ~ALLOC; 674 } 675 if (!(t->flag & INTEGER) && (set & INTEGER)) { 676 t->type = 0; 677 t->flag &= ~ALLOC; 678 } 679 t->flag = (t->flag | set) & ~clr; 680 /* Don't change base if assignment is to be done, 681 * in case assignment fails. 682 */ 683 if ((set & INTEGER) && base > 0 && (!val || t != vp)) 684 t->type = base; 685 if (set & (LJUST|RJUST|ZEROFIL)) 686 t->u2.field = field; 687 if (fake_assign) { 688 if (!setstr(t, s, KSH_RETURN_ERROR)) { 689 /* Somewhat arbitrary action here: 690 * zap contents of variable, but keep 691 * the flag settings. 692 */ 693 ok = 0; 694 if (t->flag & INTEGER) 695 t->flag &= ~ISSET; 696 else { 697 if (t->flag & ALLOC) 698 afree((void*) t->val.s, 699 t->areap); 700 t->flag &= ~(ISSET|ALLOC); 701 t->type = 0; 702 } 703 } 704 if (free_me) 705 afree((void *) free_me, t->areap); 706 } 707 } 708 if (!ok) 709 errorf(null); 710 } 711 712 if (val != NULL) { 713 if (vp->flag&INTEGER) { 714 /* do not zero base before assignment */ 715 setstr(vp, val, KSH_UNWIND_ERROR | 0x4); 716 /* Done after assignment to override default */ 717 if (base > 0) 718 vp->type = base; 719 } else 720 /* setstr can't fail (readonly check already done) */ 721 setstr(vp, val, KSH_RETURN_ERROR | 0x4); 722 } 723 724 /* only x[0] is ever exported, so use vpbase */ 725 if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) && 726 vpbase->type == 0) 727 export(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null); 728 729 return vp; 730 } 731 732 /* Unset a variable. array_ref is set if there was an array reference in 733 * the name lookup (eg, x[2]). 734 */ 735 void 736 unset(struct tbl *vp, int array_ref) 737 { 738 if (vp->flag & ALLOC) 739 afree((void*)vp->val.s, vp->areap); 740 if ((vp->flag & ARRAY) && !array_ref) { 741 struct tbl *a, *tmp; 742 743 /* Free up entire array */ 744 for (a = vp->u.array; a; ) { 745 tmp = a; 746 a = a->u.array; 747 if (tmp->flag & ALLOC) 748 afree((void *) tmp->val.s, tmp->areap); 749 afree(tmp, tmp->areap); 750 } 751 vp->u.array = (struct tbl *) 0; 752 } 753 /* If foo[0] is being unset, the remainder of the array is kept... */ 754 vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0); 755 if (vp->flag & SPECIAL) 756 unsetspec(vp); /* responsible for `unspecial'ing var */ 757 } 758 759 /* return a pointer to the first char past a legal variable name (returns the 760 * argument if there is no legal name, returns * a pointer to the terminating 761 * null if whole string is legal). 762 */ 763 char * 764 skip_varname(const char *s, int aok) 765 { 766 int alen; 767 768 if (s && letter(*s)) { 769 while (*++s && letnum(*s)) 770 ; 771 if (aok && *s == '[' && (alen = array_ref_len(s))) 772 s += alen; 773 } 774 return (char *) s; 775 } 776 777 /* Return a pointer to the first character past any legal variable name. */ 778 char * 779 skip_wdvarname(const char *s, 780 int aok) /* skip array de-reference? */ 781 { 782 if (s[0] == CHAR && letter(s[1])) { 783 do { 784 s += 2; 785 } while (s[0] == CHAR && letnum(s[1])); 786 if (aok && s[0] == CHAR && s[1] == '[') { 787 /* skip possible array de-reference */ 788 const char *p = s; 789 char c; 790 int depth = 0; 791 792 while (1) { 793 if (p[0] != CHAR) 794 break; 795 c = p[1]; 796 p += 2; 797 if (c == '[') 798 depth++; 799 else if (c == ']' && --depth == 0) { 800 s = p; 801 break; 802 } 803 } 804 } 805 } 806 return (char *) s; 807 } 808 809 /* Check if coded string s is a variable name */ 810 int 811 is_wdvarname(const char *s, int aok) 812 { 813 char *p = skip_wdvarname(s, aok); 814 815 return p != s && p[0] == EOS; 816 } 817 818 /* Check if coded string s is a variable assignment */ 819 int 820 is_wdvarassign(const char *s) 821 { 822 char *p = skip_wdvarname(s, true); 823 824 return p != s && p[0] == CHAR && p[1] == '='; 825 } 826 827 /* 828 * Make the exported environment from the exported names in the dictionary. 829 */ 830 char ** 831 makenv(void) 832 { 833 struct block *l = e->loc; 834 XPtrV env; 835 struct tbl *vp, **vpp; 836 int i; 837 838 XPinit(env, 64); 839 for (l = e->loc; l != NULL; l = l->next) 840 for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; ) 841 if ((vp = *vpp++) != NULL && 842 (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) { 843 struct block *l2; 844 struct tbl *vp2; 845 unsigned int h = hash(vp->name); 846 847 /* unexport any redefined instances */ 848 for (l2 = l->next; l2 != NULL; l2 = l2->next) { 849 vp2 = ktsearch(&l2->vars, vp->name, h); 850 if (vp2 != NULL) 851 vp2->flag &= ~EXPORT; 852 } 853 if ((vp->flag&INTEGER)) { 854 /* integer to string */ 855 char *val; 856 val = str_val(vp); 857 vp->flag &= ~(INTEGER|RDONLY); 858 /* setstr can't fail here */ 859 setstr(vp, val, KSH_RETURN_ERROR); 860 } 861 XPput(env, vp->val.s); 862 } 863 XPput(env, NULL); 864 return (char **) XPclose(env); 865 } 866 867 /* 868 * Someone has set the srand() value, therefore from now on 869 * we return values from rand() instead of arc4random() 870 */ 871 int use_rand = 0; 872 873 /* 874 * Called after a fork in parent to bump the random number generator. 875 * Done to ensure children will not get the same random number sequence 876 * if the parent doesn't use $RANDOM. 877 */ 878 void 879 change_random(void) 880 { 881 if (use_rand) 882 rand(); 883 } 884 885 /* 886 * handle special variables with side effects - PATH, SECONDS. 887 */ 888 889 /* Test if name is a special parameter */ 890 static int 891 special(const char *name) 892 { 893 struct tbl *tp; 894 895 tp = ktsearch(&specials, name, hash(name)); 896 return tp && (tp->flag & ISSET) ? tp->type : V_NONE; 897 } 898 899 /* Make a variable non-special */ 900 static void 901 unspecial(const char *name) 902 { 903 struct tbl *tp; 904 905 tp = ktsearch(&specials, name, hash(name)); 906 if (tp) 907 ktdelete(tp); 908 } 909 910 static time_t seconds; /* time SECONDS last set */ 911 static int user_lineno; /* what user set $LINENO to */ 912 913 static void 914 getspec(struct tbl *vp) 915 { 916 switch (special(vp->name)) { 917 case V_SECONDS: 918 vp->flag &= ~SPECIAL; 919 /* On start up the value of SECONDS is used before seconds 920 * has been set - don't do anything in this case 921 * (see initcoms[] in main.c). 922 */ 923 if (vp->flag & ISSET) 924 setint(vp, (long) (time((time_t *)0) - seconds)); 925 vp->flag |= SPECIAL; 926 break; 927 case V_RANDOM: 928 vp->flag &= ~SPECIAL; 929 if (use_rand) 930 setint(vp, (long) (rand() & 0x7fff)); 931 else 932 setint(vp, (long) (arc4random() & 0x7fff)); 933 vp->flag |= SPECIAL; 934 break; 935 #ifdef HISTORY 936 case V_HISTSIZE: 937 vp->flag &= ~SPECIAL; 938 setint(vp, (long) histsize); 939 vp->flag |= SPECIAL; 940 break; 941 #endif /* HISTORY */ 942 case V_OPTIND: 943 vp->flag &= ~SPECIAL; 944 setint(vp, (long) user_opt.uoptind); 945 vp->flag |= SPECIAL; 946 break; 947 case V_LINENO: 948 vp->flag &= ~SPECIAL; 949 setint(vp, (long) current_lineno + user_lineno); 950 vp->flag |= SPECIAL; 951 break; 952 } 953 } 954 955 static void 956 setspec(struct tbl *vp) 957 { 958 char *s; 959 960 switch (special(vp->name)) { 961 case V_PATH: 962 if (path) 963 afree(path, APERM); 964 path = str_save(str_val(vp), APERM); 965 flushcom(1); /* clear tracked aliases */ 966 break; 967 case V_IFS: 968 setctypes(s = str_val(vp), C_IFS); 969 ifs0 = *s; 970 break; 971 case V_OPTIND: 972 vp->flag &= ~SPECIAL; 973 getopts_reset((int) intval(vp)); 974 vp->flag |= SPECIAL; 975 break; 976 case V_POSIXLY_CORRECT: 977 change_flag(FPOSIX, OF_SPECIAL, 1); 978 break; 979 case V_TMPDIR: 980 if (tmpdir) { 981 afree(tmpdir, APERM); 982 tmpdir = (char *) 0; 983 } 984 /* Use tmpdir iff it is an absolute path, is writable and 985 * searchable and is a directory... 986 */ 987 { 988 struct stat statb; 989 990 s = str_val(vp); 991 if (s[0] == '/' && access(s, W_OK|X_OK) == 0 && 992 stat(s, &statb) == 0 && S_ISDIR(statb.st_mode)) 993 tmpdir = str_save(s, APERM); 994 } 995 break; 996 #ifdef HISTORY 997 case V_HISTSIZE: 998 vp->flag &= ~SPECIAL; 999 sethistsize((int) intval(vp)); 1000 vp->flag |= SPECIAL; 1001 break; 1002 case V_HISTFILE: 1003 sethistfile(str_val(vp)); 1004 break; 1005 #endif /* HISTORY */ 1006 #ifdef EDIT 1007 case V_VISUAL: 1008 set_editmode(str_val(vp)); 1009 break; 1010 case V_EDITOR: 1011 if (!(global("VISUAL")->flag & ISSET)) 1012 set_editmode(str_val(vp)); 1013 break; 1014 case V_COLUMNS: 1015 if ((x_cols = intval(vp)) <= MIN_COLS) 1016 x_cols = MIN_COLS; 1017 break; 1018 #endif /* EDIT */ 1019 case V_MAIL: 1020 mbset(str_val(vp)); 1021 break; 1022 case V_MAILPATH: 1023 mpset(str_val(vp)); 1024 break; 1025 case V_MAILCHECK: 1026 vp->flag &= ~SPECIAL; 1027 mcset(intval(vp)); 1028 vp->flag |= SPECIAL; 1029 break; 1030 case V_RANDOM: 1031 vp->flag &= ~SPECIAL; 1032 srand((unsigned int)intval(vp)); 1033 use_rand = 1; 1034 vp->flag |= SPECIAL; 1035 break; 1036 case V_SECONDS: 1037 vp->flag &= ~SPECIAL; 1038 seconds = time((time_t*) 0) - intval(vp); 1039 vp->flag |= SPECIAL; 1040 break; 1041 case V_TMOUT: 1042 /* at&t ksh seems to do this (only listen if integer) */ 1043 if (vp->flag & INTEGER) 1044 ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0; 1045 break; 1046 case V_LINENO: 1047 vp->flag &= ~SPECIAL; 1048 /* The -1 is because line numbering starts at 1. */ 1049 user_lineno = (unsigned int) intval(vp) - current_lineno - 1; 1050 vp->flag |= SPECIAL; 1051 break; 1052 } 1053 } 1054 1055 static void 1056 unsetspec(struct tbl *vp) 1057 { 1058 switch (special(vp->name)) { 1059 case V_PATH: 1060 if (path) 1061 afree(path, APERM); 1062 path = str_save(def_path, APERM); 1063 flushcom(1); /* clear tracked aliases */ 1064 break; 1065 case V_IFS: 1066 setctypes(" \t\n", C_IFS); 1067 ifs0 = ' '; 1068 break; 1069 case V_TMPDIR: 1070 /* should not become unspecial */ 1071 if (tmpdir) { 1072 afree(tmpdir, APERM); 1073 tmpdir = (char *) 0; 1074 } 1075 break; 1076 case V_MAIL: 1077 mbset((char *) 0); 1078 break; 1079 case V_MAILPATH: 1080 mpset((char *) 0); 1081 break; 1082 case V_LINENO: 1083 case V_MAILCHECK: /* at&t ksh leaves previous value in place */ 1084 case V_RANDOM: 1085 case V_SECONDS: 1086 case V_TMOUT: /* at&t ksh leaves previous value in place */ 1087 unspecial(vp->name); 1088 break; 1089 1090 /* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning, 1091 * but OPTARG does not (still set by getopts) and _ is also still 1092 * set in various places. 1093 * Don't know what at&t does for: 1094 * MAIL, MAILPATH, HISTSIZE, HISTFILE, 1095 * Unsetting these in at&t ksh does not loose the `specialness': 1096 * no effect: IFS, COLUMNS, PATH, TMPDIR, 1097 * VISUAL, EDITOR, 1098 * pdkshisms: no effect: 1099 * POSIXLY_CORRECT (use set +o posix instead) 1100 */ 1101 } 1102 } 1103 1104 /* 1105 * Search for (and possibly create) a table entry starting with 1106 * vp, indexed by val. 1107 */ 1108 static struct tbl * 1109 arraysearch(struct tbl *vp, int val) 1110 { 1111 struct tbl *prev, *curr, *new; 1112 size_t namelen = strlen(vp->name) + 1; 1113 1114 vp->flag |= ARRAY|DEFINED; 1115 vp->index = 0; 1116 /* The table entry is always [0] */ 1117 if (val == 0) 1118 return vp; 1119 prev = vp; 1120 curr = vp->u.array; 1121 while (curr && curr->index < val) { 1122 prev = curr; 1123 curr = curr->u.array; 1124 } 1125 if (curr && curr->index == val) { 1126 if (curr->flag&ISSET) 1127 return curr; 1128 else 1129 new = curr; 1130 } else 1131 new = (struct tbl *)alloc(sizeof(struct tbl) + namelen, 1132 vp->areap); 1133 strlcpy(new->name, vp->name, namelen); 1134 new->flag = vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL); 1135 new->type = vp->type; 1136 new->areap = vp->areap; 1137 new->u2.field = vp->u2.field; 1138 new->index = val; 1139 if (curr != new) { /* not reusing old array entry */ 1140 prev->u.array = new; 1141 new->u.array = curr; 1142 } 1143 return new; 1144 } 1145 1146 /* Return the length of an array reference (eg, [1+2]) - cp is assumed 1147 * to point to the open bracket. Returns 0 if there is no matching closing 1148 * bracket. 1149 */ 1150 int 1151 array_ref_len(const char *cp) 1152 { 1153 const char *s = cp; 1154 int c; 1155 int depth = 0; 1156 1157 while ((c = *s++) && (c != ']' || --depth)) 1158 if (c == '[') 1159 depth++; 1160 if (!c) 1161 return 0; 1162 return s - cp; 1163 } 1164 1165 /* 1166 * Make a copy of the base of an array name 1167 */ 1168 char * 1169 arrayname(const char *str) 1170 { 1171 const char *p; 1172 1173 if ((p = strchr(str, '[')) == 0) 1174 /* Shouldn't happen, but why worry? */ 1175 return (char *) str; 1176 1177 return str_nsave(str, p - str, ATEMP); 1178 } 1179 1180 /* Set (or overwrite, if !reset) the array variable var to the values in vals. 1181 */ 1182 void 1183 set_array(const char *var, int reset, char **vals) 1184 { 1185 struct tbl *vp, *vq; 1186 int i; 1187 1188 /* to get local array, use "typeset foo; set -A foo" */ 1189 vp = global(var); 1190 1191 /* Note: at&t ksh allows set -A but not set +A of a read-only var */ 1192 if ((vp->flag&RDONLY)) 1193 errorf("%s: is read only", var); 1194 /* This code is quite non-optimal */ 1195 if (reset > 0) 1196 /* trash existing values and attributes */ 1197 unset(vp, 0); 1198 /* todo: would be nice for assignment to completely succeed or 1199 * completely fail. Only really effects integer arrays: 1200 * evaluation of some of vals[] may fail... 1201 */ 1202 for (i = 0; vals[i]; i++) { 1203 vq = arraysearch(vp, i); 1204 /* would be nice to deal with errors here... (see above) */ 1205 setstr(vq, vals[i], KSH_RETURN_ERROR); 1206 } 1207 } 1208