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