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