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