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