1 /* $OpenBSD: eval.c,v 1.34 2009/01/29 23:27:26 jaredy Exp $ */ 2 3 /* 4 * Expansion - quoting, separation, substitution, globbing 5 */ 6 7 #include "sh.h" 8 #include <pwd.h> 9 #include <dirent.h> 10 #include <sys/stat.h> 11 12 /* 13 * string expansion 14 * 15 * first pass: quoting, IFS separation, ~, ${}, $() and $(()) substitution. 16 * second pass: alternation ({,}), filename expansion (*?[]). 17 */ 18 19 /* expansion generator state */ 20 typedef struct Expand { 21 /* int type; */ /* see expand() */ 22 const char *str; /* string */ 23 union { 24 const char **strv;/* string[] */ 25 struct shf *shf;/* file */ 26 } u; /* source */ 27 struct tbl *var; /* variable in ${var..} */ 28 short split; /* split "$@" / call waitlast $() */ 29 } Expand; 30 31 #define XBASE 0 /* scanning original */ 32 #define XSUB 1 /* expanding ${} string */ 33 #define XARGSEP 2 /* ifs0 between "$*" */ 34 #define XARG 3 /* expanding $*, $@ */ 35 #define XCOM 4 /* expanding $() */ 36 #define XNULLSUB 5 /* "$@" when $# is 0 (don't generate word) */ 37 #define XSUBMID 6 /* middle of expanding ${} */ 38 39 /* States used for field splitting */ 40 #define IFS_WORD 0 /* word has chars (or quotes) */ 41 #define IFS_WS 1 /* have seen IFS white-space */ 42 #define IFS_NWS 2 /* have seen IFS non-white-space */ 43 44 static int varsub(Expand *, char *, char *, int *, int *); 45 static int comsub(Expand *, char *); 46 static char *trimsub(char *, char *, int); 47 static void glob(char *, XPtrV *, int); 48 static void globit(XString *, char **, char *, XPtrV *, int); 49 static char *maybe_expand_tilde(char *, XString *, char **, int); 50 static char *tilde(char *); 51 static char *homedir(char *); 52 #ifdef BRACE_EXPAND 53 static void alt_expand(XPtrV *, char *, char *, char *, int); 54 #endif 55 56 /* compile and expand word */ 57 char * 58 substitute(const char *cp, int f) 59 { 60 struct source *s, *sold; 61 62 sold = source; 63 s = pushs(SWSTR, ATEMP); 64 s->start = s->str = cp; 65 source = s; 66 if (yylex(ONEWORD) != LWORD) 67 internal_errorf(1, "substitute"); 68 source = sold; 69 afree(s, ATEMP); 70 return evalstr(yylval.cp, f); 71 } 72 73 /* 74 * expand arg-list 75 */ 76 char ** 77 eval(char **ap, int f) 78 { 79 XPtrV w; 80 81 if (*ap == NULL) 82 return ap; 83 XPinit(w, 32); 84 XPput(w, NULL); /* space for shell name */ 85 while (*ap != NULL) 86 expand(*ap++, &w, f); 87 XPput(w, NULL); 88 return (char **) XPclose(w) + 1; 89 } 90 91 /* 92 * expand string 93 */ 94 char * 95 evalstr(char *cp, int f) 96 { 97 XPtrV w; 98 99 XPinit(w, 1); 100 expand(cp, &w, f); 101 cp = (XPsize(w) == 0) ? null : (char*) *XPptrv(w); 102 XPfree(w); 103 return cp; 104 } 105 106 /* 107 * expand string - return only one component 108 * used from iosetup to expand redirection files 109 */ 110 char * 111 evalonestr(char *cp, int f) 112 { 113 XPtrV w; 114 115 XPinit(w, 1); 116 expand(cp, &w, f); 117 switch (XPsize(w)) { 118 case 0: 119 cp = null; 120 break; 121 case 1: 122 cp = (char*) *XPptrv(w); 123 break; 124 default: 125 cp = evalstr(cp, f&~DOGLOB); 126 break; 127 } 128 XPfree(w); 129 return cp; 130 } 131 132 /* for nested substitution: ${var:=$var2} */ 133 typedef struct SubType { 134 short stype; /* [=+-?%#] action after expanded word */ 135 short base; /* begin position of expanded word */ 136 short f; /* saved value of f (DOPAT, etc) */ 137 struct tbl *var; /* variable for ${var..} */ 138 short quote; /* saved value of quote (for ${..[%#]..}) */ 139 struct SubType *prev; /* old type */ 140 struct SubType *next; /* poped type (to avoid re-allocating) */ 141 } SubType; 142 143 void 144 expand(char *cp, /* input word */ 145 XPtrV *wp, /* output words */ 146 int f) /* DO* flags */ 147 { 148 int c = 0; 149 int type; /* expansion type */ 150 int quote = 0; /* quoted */ 151 XString ds; /* destination string */ 152 char *dp, *sp; /* dest., source */ 153 int fdo, word; /* second pass flags; have word */ 154 int doblank; /* field splitting of parameter/command subst */ 155 Expand x; /* expansion variables */ 156 SubType st_head, *st; 157 int newlines = 0; /* For trailing newlines in COMSUB */ 158 int saw_eq, tilde_ok; 159 int make_magic; 160 size_t len; 161 162 if (cp == NULL) 163 internal_errorf(1, "expand(NULL)"); 164 /* for alias, readonly, set, typeset commands */ 165 if ((f & DOVACHECK) && is_wdvarassign(cp)) { 166 f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE); 167 f |= DOASNTILDE; 168 } 169 if (Flag(FNOGLOB)) 170 f &= ~DOGLOB; 171 if (Flag(FMARKDIRS)) 172 f |= DOMARKDIRS; 173 #ifdef BRACE_EXPAND 174 if (Flag(FBRACEEXPAND) && (f & DOGLOB)) 175 f |= DOBRACE_; 176 #endif /* BRACE_EXPAND */ 177 178 Xinit(ds, dp, 128, ATEMP); /* init dest. string */ 179 type = XBASE; 180 sp = cp; 181 fdo = 0; 182 saw_eq = 0; 183 tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; /* must be 1/0 */ 184 doblank = 0; 185 make_magic = 0; 186 word = (f&DOBLANK) ? IFS_WS : IFS_WORD; 187 st_head.next = (SubType *) 0; 188 st = &st_head; 189 190 while (1) { 191 Xcheck(ds, dp); 192 193 switch (type) { 194 case XBASE: /* original prefixed string */ 195 c = *sp++; 196 switch (c) { 197 case EOS: 198 c = 0; 199 break; 200 case CHAR: 201 c = *sp++; 202 break; 203 case QCHAR: 204 quote |= 2; /* temporary quote */ 205 c = *sp++; 206 break; 207 case OQUOTE: 208 word = IFS_WORD; 209 tilde_ok = 0; 210 quote = 1; 211 continue; 212 case CQUOTE: 213 quote = 0; 214 continue; 215 case COMSUB: 216 tilde_ok = 0; 217 if (f & DONTRUNCOMMAND) { 218 word = IFS_WORD; 219 *dp++ = '$'; *dp++ = '('; 220 while (*sp != '\0') { 221 Xcheck(ds, dp); 222 *dp++ = *sp++; 223 } 224 *dp++ = ')'; 225 } else { 226 type = comsub(&x, sp); 227 if (type == XCOM && (f&DOBLANK)) 228 doblank++; 229 sp = strchr(sp, 0) + 1; 230 newlines = 0; 231 } 232 continue; 233 case EXPRSUB: 234 word = IFS_WORD; 235 tilde_ok = 0; 236 if (f & DONTRUNCOMMAND) { 237 *dp++ = '$'; *dp++ = '('; *dp++ = '('; 238 while (*sp != '\0') { 239 Xcheck(ds, dp); 240 *dp++ = *sp++; 241 } 242 *dp++ = ')'; *dp++ = ')'; 243 } else { 244 struct tbl v; 245 char *p; 246 247 v.flag = DEFINED|ISSET|INTEGER; 248 v.type = 10; /* not default */ 249 v.name[0] = '\0'; 250 v_evaluate(&v, substitute(sp, 0), 251 KSH_UNWIND_ERROR, true); 252 sp = strchr(sp, 0) + 1; 253 for (p = str_val(&v); *p; ) { 254 Xcheck(ds, dp); 255 *dp++ = *p++; 256 } 257 } 258 continue; 259 case OSUBST: /* ${{#}var{:}[=+-?#%]word} */ 260 /* format is: 261 * OSUBST [{x] plain-variable-part \0 262 * compiled-word-part CSUBST [}x] 263 * This is where all syntax checking gets done... 264 */ 265 { 266 char *varname = ++sp; /* skip the { or x (}) */ 267 int stype; 268 int slen; 269 270 sp = strchr(sp, '\0') + 1; /* skip variable */ 271 type = varsub(&x, varname, sp, &stype, &slen); 272 if (type < 0) { 273 char endc; 274 char *str, *end; 275 276 sp = varname - 2; /* restore sp */ 277 end = (char *) wdscan(sp, CSUBST); 278 /* ({) the } or x is already skipped */ 279 endc = *end; 280 *end = EOS; 281 str = snptreef(NULL, 64, "%S", sp); 282 *end = endc; 283 errorf("%s: bad substitution", str); 284 } 285 if (f&DOBLANK) 286 doblank++; 287 tilde_ok = 0; 288 if (type == XBASE) { /* expand? */ 289 if (!st->next) { 290 SubType *newst; 291 292 newst = (SubType *) alloc( 293 sizeof(SubType), ATEMP); 294 newst->next = (SubType *) 0; 295 newst->prev = st; 296 st->next = newst; 297 } 298 st = st->next; 299 st->stype = stype; 300 st->base = Xsavepos(ds, dp); 301 st->f = f; 302 st->var = x.var; 303 st->quote = quote; 304 /* skip qualifier(s) */ 305 if (stype) 306 sp += slen; 307 switch (stype & 0x7f) { 308 case '#': 309 case '%': 310 /* ! DOBLANK,DOBRACE_,DOTILDE */ 311 f = DOPAT | (f&DONTRUNCOMMAND) | 312 DOTEMP_; 313 quote = 0; 314 /* Prepend open pattern (so | 315 * in a trim will work as 316 * expected) 317 */ 318 *dp++ = MAGIC; 319 *dp++ = '@' + 0x80; 320 break; 321 case '=': 322 /* Enabling tilde expansion 323 * after :'s here is 324 * non-standard ksh, but is 325 * consistent with rules for 326 * other assignments. Not 327 * sure what POSIX thinks of 328 * this. 329 * Not doing tilde expansion 330 * for integer variables is a 331 * non-POSIX thing - makes 332 * sense though, since ~ is 333 * a arithmetic operator. 334 */ 335 if (!(x.var->flag & INTEGER)) 336 f |= DOASNTILDE|DOTILDE; 337 f |= DOTEMP_; 338 /* These will be done after the 339 * value has been assigned. 340 */ 341 f &= ~(DOBLANK|DOGLOB|DOBRACE_); 342 tilde_ok = 1; 343 break; 344 case '?': 345 f &= ~DOBLANK; 346 f |= DOTEMP_; 347 /* FALLTHROUGH */ 348 default: 349 /* Enable tilde expansion */ 350 tilde_ok = 1; 351 f |= DOTILDE; 352 } 353 } else 354 /* skip word */ 355 sp = (char *) wdscan(sp, CSUBST); 356 continue; 357 } 358 case CSUBST: /* only get here if expanding word */ 359 sp++; /* ({) skip the } or x */ 360 tilde_ok = 0; /* in case of ${unset:-} */ 361 *dp = '\0'; 362 quote = st->quote; 363 f = st->f; 364 if (f&DOBLANK) 365 doblank--; 366 switch (st->stype&0x7f) { 367 case '#': 368 case '%': 369 /* Append end-pattern */ 370 *dp++ = MAGIC; *dp++ = ')'; *dp = '\0'; 371 dp = Xrestpos(ds, dp, st->base); 372 /* Must use st->var since calling 373 * global would break things 374 * like x[i+=1]. 375 */ 376 x.str = trimsub(str_val(st->var), 377 dp, st->stype); 378 type = XSUB; 379 if (f&DOBLANK) 380 doblank++; 381 st = st->prev; 382 continue; 383 case '=': 384 /* Restore our position and substitute 385 * the value of st->var (may not be 386 * the assigned value in the presence 387 * of integer/right-adj/etc attributes). 388 */ 389 dp = Xrestpos(ds, dp, st->base); 390 /* Must use st->var since calling 391 * global would cause with things 392 * like x[i+=1] to be evaluated twice. 393 */ 394 /* Note: not exported by FEXPORT 395 * in at&t ksh. 396 */ 397 /* XXX POSIX says readonly is only 398 * fatal for special builtins (setstr 399 * does readonly check). 400 */ 401 len = strlen(dp) + 1; 402 setstr(st->var, 403 debunk((char *) alloc(len, ATEMP), 404 dp, len), KSH_UNWIND_ERROR); 405 x.str = str_val(st->var); 406 type = XSUB; 407 if (f&DOBLANK) 408 doblank++; 409 st = st->prev; 410 continue; 411 case '?': 412 { 413 char *s = Xrestpos(ds, dp, st->base); 414 415 errorf("%s: %s", st->var->name, 416 dp == s ? 417 "parameter null or not set" : 418 (debunk(s, s, strlen(s) + 1), s)); 419 } 420 } 421 st = st->prev; 422 type = XBASE; 423 continue; 424 425 case OPAT: /* open pattern: *(foo|bar) */ 426 /* Next char is the type of pattern */ 427 make_magic = 1; 428 c = *sp++ + 0x80; 429 break; 430 431 case SPAT: /* pattern separator (|) */ 432 make_magic = 1; 433 c = '|'; 434 break; 435 436 case CPAT: /* close pattern */ 437 make_magic = 1; 438 c = /*(*/ ')'; 439 break; 440 } 441 break; 442 443 case XNULLSUB: 444 /* Special case for "$@" (and "${foo[@]}") - no 445 * word is generated if $# is 0 (unless there is 446 * other stuff inside the quotes). 447 */ 448 type = XBASE; 449 if (f&DOBLANK) { 450 doblank--; 451 /* not really correct: x=; "$x$@" should 452 * generate a null argument and 453 * set A; "${@:+}" shouldn't. 454 */ 455 if (dp == Xstring(ds, dp)) 456 word = IFS_WS; 457 } 458 continue; 459 460 case XSUB: 461 case XSUBMID: 462 if ((c = *x.str++) == 0) { 463 type = XBASE; 464 if (f&DOBLANK) 465 doblank--; 466 continue; 467 } 468 break; 469 470 case XARGSEP: 471 type = XARG; 472 quote = 1; 473 case XARG: 474 if ((c = *x.str++) == '\0') { 475 /* force null words to be created so 476 * set -- '' 2 ''; foo "$@" will do 477 * the right thing 478 */ 479 if (quote && x.split) 480 word = IFS_WORD; 481 if ((x.str = *x.u.strv++) == NULL) { 482 type = XBASE; 483 if (f&DOBLANK) 484 doblank--; 485 continue; 486 } 487 c = ifs0; 488 if (c == 0) { 489 if (quote && !x.split) 490 continue; 491 c = ' '; 492 } 493 if (quote && x.split) { 494 /* terminate word for "$@" */ 495 type = XARGSEP; 496 quote = 0; 497 } 498 } 499 break; 500 501 case XCOM: 502 if (newlines) { /* Spit out saved nl's */ 503 c = '\n'; 504 --newlines; 505 } else { 506 while ((c = shf_getc(x.u.shf)) == 0 || c == '\n') 507 if (c == '\n') 508 newlines++; /* Save newlines */ 509 if (newlines && c != EOF) { 510 shf_ungetc(c, x.u.shf); 511 c = '\n'; 512 --newlines; 513 } 514 } 515 if (c == EOF) { 516 newlines = 0; 517 shf_close(x.u.shf); 518 if (x.split) 519 subst_exstat = waitlast(); 520 type = XBASE; 521 if (f&DOBLANK) 522 doblank--; 523 continue; 524 } 525 break; 526 } 527 528 /* check for end of word or IFS separation */ 529 if (c == 0 || (!quote && (f & DOBLANK) && doblank && 530 !make_magic && ctype(c, C_IFS))) { 531 /* How words are broken up: 532 * | value of c 533 * word | ws nws 0 534 * ----------------------------------- 535 * IFS_WORD w/WS w/NWS w 536 * IFS_WS -/WS w/NWS - 537 * IFS_NWS -/NWS w/NWS w 538 * (w means generate a word) 539 * Note that IFS_NWS/0 generates a word (at&t ksh 540 * doesn't do this, but POSIX does). 541 */ 542 if (word == IFS_WORD || 543 (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) { 544 char *p; 545 546 *dp++ = '\0'; 547 p = Xclose(ds, dp); 548 #ifdef BRACE_EXPAND 549 if (fdo & DOBRACE_) 550 /* also does globbing */ 551 alt_expand(wp, p, p, 552 p + Xlength(ds, (dp - 1)), 553 fdo | (f & DOMARKDIRS)); 554 else 555 #endif /* BRACE_EXPAND */ 556 if (fdo & DOGLOB) 557 glob(p, wp, f & DOMARKDIRS); 558 else if ((f & DOPAT) || !(fdo & DOMAGIC_)) 559 XPput(*wp, p); 560 else 561 XPput(*wp, debunk(p, p, strlen(p) + 1)); 562 fdo = 0; 563 saw_eq = 0; 564 tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; 565 if (c != 0) 566 Xinit(ds, dp, 128, ATEMP); 567 } 568 if (c == 0) 569 return; 570 if (word != IFS_NWS) 571 word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; 572 } else { 573 if (type == XSUB) { 574 if (word == IFS_NWS && 575 Xlength(ds, dp) == 0) { 576 char *p; 577 578 if ((p = strdup("")) == NULL) 579 internal_errorf(1, "unable " 580 "to allocate memory"); 581 XPput(*wp, p); 582 } 583 type = XSUBMID; 584 } 585 586 /* age tilde_ok info - ~ code tests second bit */ 587 tilde_ok <<= 1; 588 /* mark any special second pass chars */ 589 if (!quote) 590 switch (c) { 591 case '[': 592 case NOT: 593 case '-': 594 case ']': 595 /* For character classes - doesn't hurt 596 * to have magic !,-,]'s outside of 597 * [...] expressions. 598 */ 599 if (f & (DOPAT | DOGLOB)) { 600 fdo |= DOMAGIC_; 601 if (c == '[') 602 fdo |= f & DOGLOB; 603 *dp++ = MAGIC; 604 } 605 break; 606 case '*': 607 case '?': 608 if (f & (DOPAT | DOGLOB)) { 609 fdo |= DOMAGIC_ | (f & DOGLOB); 610 *dp++ = MAGIC; 611 } 612 break; 613 #ifdef BRACE_EXPAND 614 case OBRACE: 615 case ',': 616 case CBRACE: 617 if ((f & DOBRACE_) && (c == OBRACE || 618 (fdo & DOBRACE_))) { 619 fdo |= DOBRACE_|DOMAGIC_; 620 *dp++ = MAGIC; 621 } 622 break; 623 #endif /* BRACE_EXPAND */ 624 case '=': 625 /* Note first unquoted = for ~ */ 626 if (!(f & DOTEMP_) && !saw_eq) { 627 saw_eq = 1; 628 tilde_ok = 1; 629 } 630 break; 631 case ':': /* : */ 632 /* Note unquoted : for ~ */ 633 if (!(f & DOTEMP_) && (f & DOASNTILDE)) 634 tilde_ok = 1; 635 break; 636 case '~': 637 /* tilde_ok is reset whenever 638 * any of ' " $( $(( ${ } are seen. 639 * Note that tilde_ok must be preserved 640 * through the sequence ${A=a=}~ 641 */ 642 if (type == XBASE && 643 (f & (DOTILDE|DOASNTILDE)) && 644 (tilde_ok & 2)) { 645 char *p, *dp_x; 646 647 dp_x = dp; 648 p = maybe_expand_tilde(sp, 649 &ds, &dp_x, 650 f & DOASNTILDE); 651 if (p) { 652 if (dp != dp_x) 653 word = IFS_WORD; 654 dp = dp_x; 655 sp = p; 656 continue; 657 } 658 } 659 break; 660 } 661 else 662 quote &= ~2; /* undo temporary */ 663 664 if (make_magic) { 665 make_magic = 0; 666 fdo |= DOMAGIC_ | (f & DOGLOB); 667 *dp++ = MAGIC; 668 } else if (ISMAGIC(c)) { 669 fdo |= DOMAGIC_; 670 *dp++ = MAGIC; 671 } 672 *dp++ = c; /* save output char */ 673 word = IFS_WORD; 674 } 675 } 676 } 677 678 /* 679 * Prepare to generate the string returned by ${} substitution. 680 */ 681 static int 682 varsub(Expand *xp, char *sp, char *word, 683 int *stypep, /* becomes qualifier type */ 684 int *slenp) /* " " len (=, :=, etc.) valid iff *stypep != 0 */ 685 { 686 int c; 687 int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */ 688 int stype; /* substitution type */ 689 int slen; 690 char *p; 691 struct tbl *vp; 692 693 if (sp[0] == '\0') /* Bad variable name */ 694 return -1; 695 696 xp->var = (struct tbl *) 0; 697 698 /* ${#var}, string length or array size */ 699 if (sp[0] == '#' && (c = sp[1]) != '\0') { 700 int zero_ok = 0; 701 702 /* Can't have any modifiers for ${#...} */ 703 if (*word != CSUBST) 704 return -1; 705 sp++; 706 /* Check for size of array */ 707 if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { 708 int n = 0; 709 int max = 0; 710 711 vp = global(arrayname(sp)); 712 if (vp->flag & (ISSET|ARRAY)) 713 zero_ok = 1; 714 for (; vp; vp = vp->u.array) 715 if (vp->flag & ISSET) { 716 max = vp->index + 1; 717 n++; 718 } 719 c = n; /* ksh88/ksh93 go for number, not max index */ 720 } else if (c == '*' || c == '@') 721 c = e->loc->argc; 722 else { 723 p = str_val(global(sp)); 724 zero_ok = p != null; 725 c = strlen(p); 726 } 727 if (Flag(FNOUNSET) && c == 0 && !zero_ok) 728 errorf("%s: parameter not set", sp); 729 *stypep = 0; /* unqualified variable/string substitution */ 730 xp->str = str_save(ulton((unsigned long)c, 10), ATEMP); 731 return XSUB; 732 } 733 734 /* Check for qualifiers in word part */ 735 stype = 0; 736 c = word[slen = 0] == CHAR ? word[1] : 0; 737 if (c == ':') { 738 slen += 2; 739 stype = 0x80; 740 c = word[slen + 0] == CHAR ? word[slen + 1] : 0; 741 } 742 if (ctype(c, C_SUBOP1)) { 743 slen += 2; 744 stype |= c; 745 } else if (ctype(c, C_SUBOP2)) { /* Note: ksh88 allows :%, :%%, etc */ 746 slen += 2; 747 stype = c; 748 if (word[slen + 0] == CHAR && c == word[slen + 1]) { 749 stype |= 0x80; 750 slen += 2; 751 } 752 } else if (stype) /* : is not ok */ 753 return -1; 754 if (!stype && *word != CSUBST) 755 return -1; 756 *stypep = stype; 757 *slenp = slen; 758 759 c = sp[0]; 760 if (c == '*' || c == '@') { 761 switch (stype & 0x7f) { 762 case '=': /* can't assign to a vector */ 763 case '%': /* can't trim a vector (yet) */ 764 case '#': 765 return -1; 766 } 767 if (e->loc->argc == 0) { 768 xp->str = null; 769 xp->var = global(sp); 770 state = c == '@' ? XNULLSUB : XSUB; 771 } else { 772 xp->u.strv = (const char **) e->loc->argv + 1; 773 xp->str = *xp->u.strv++; 774 xp->split = c == '@'; /* $@ */ 775 state = XARG; 776 } 777 } else { 778 if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { 779 XPtrV wv; 780 781 switch (stype & 0x7f) { 782 case '=': /* can't assign to a vector */ 783 case '%': /* can't trim a vector (yet) */ 784 case '#': 785 case '?': 786 return -1; 787 } 788 XPinit(wv, 32); 789 vp = global(arrayname(sp)); 790 for (; vp; vp = vp->u.array) { 791 if (!(vp->flag&ISSET)) 792 continue; 793 XPput(wv, str_val(vp)); 794 } 795 if (XPsize(wv) == 0) { 796 xp->str = null; 797 state = p[1] == '@' ? XNULLSUB : XSUB; 798 XPfree(wv); 799 } else { 800 XPput(wv, 0); 801 xp->u.strv = (const char **) XPptrv(wv); 802 xp->str = *xp->u.strv++; 803 xp->split = p[1] == '@'; /* ${foo[@]} */ 804 state = XARG; 805 } 806 } else { 807 /* Can't assign things like $! or $1 */ 808 if ((stype & 0x7f) == '=' && 809 (ctype(*sp, C_VAR1) || digit(*sp))) 810 return -1; 811 xp->var = global(sp); 812 xp->str = str_val(xp->var); 813 state = XSUB; 814 } 815 } 816 817 c = stype&0x7f; 818 /* test the compiler's code generator */ 819 if (ctype(c, C_SUBOP2) || 820 (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */ 821 c == '=' || c == '-' || c == '?' : c == '+')) 822 state = XBASE; /* expand word instead of variable value */ 823 if (Flag(FNOUNSET) && xp->str == null && 824 (ctype(c, C_SUBOP2) || (state != XBASE && c != '+'))) 825 errorf("%s: parameter not set", sp); 826 return state; 827 } 828 829 /* 830 * Run the command in $(...) and read its output. 831 */ 832 static int 833 comsub(Expand *xp, char *cp) 834 { 835 Source *s, *sold; 836 struct op *t; 837 struct shf *shf; 838 839 s = pushs(SSTRING, ATEMP); 840 s->start = s->str = cp; 841 sold = source; 842 t = compile(s); 843 afree(s, ATEMP); 844 source = sold; 845 846 if (t == NULL) 847 return XBASE; 848 849 if (t != NULL && t->type == TCOM && /* $(<file) */ 850 *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { 851 struct ioword *io = *t->ioact; 852 char *name; 853 854 if ((io->flag&IOTYPE) != IOREAD) 855 errorf("funny $() command: %s", 856 snptreef((char *) 0, 32, "%R", io)); 857 shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0, 858 SHF_MAPHI|SHF_CLEXEC); 859 if (shf == NULL) 860 errorf("%s: cannot open $() input", name); 861 xp->split = 0; /* no waitlast() */ 862 } else { 863 int ofd1, pv[2]; 864 openpipe(pv); 865 shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0); 866 ofd1 = savefd(1); 867 if (pv[1] != 1) { 868 ksh_dup2(pv[1], 1, false); 869 close(pv[1]); 870 } 871 execute(t, XFORK|XXCOM|XPIPEO, NULL); 872 restfd(1, ofd1); 873 startlast(); 874 xp->split = 1; /* waitlast() */ 875 } 876 877 xp->u.shf = shf; 878 return XCOM; 879 } 880 881 /* 882 * perform #pattern and %pattern substitution in ${} 883 */ 884 885 static char * 886 trimsub(char *str, char *pat, int how) 887 { 888 char *end = strchr(str, 0); 889 char *p, c; 890 891 switch (how&0xff) { /* UCHAR_MAX maybe? */ 892 case '#': /* shortest at beginning */ 893 for (p = str; p <= end; p++) { 894 c = *p; *p = '\0'; 895 if (gmatch(str, pat, false)) { 896 *p = c; 897 return p; 898 } 899 *p = c; 900 } 901 break; 902 case '#'|0x80: /* longest match at beginning */ 903 for (p = end; p >= str; p--) { 904 c = *p; *p = '\0'; 905 if (gmatch(str, pat, false)) { 906 *p = c; 907 return p; 908 } 909 *p = c; 910 } 911 break; 912 case '%': /* shortest match at end */ 913 for (p = end; p >= str; p--) { 914 if (gmatch(p, pat, false)) 915 return str_nsave(str, p - str, ATEMP); 916 } 917 break; 918 case '%'|0x80: /* longest match at end */ 919 for (p = str; p <= end; p++) { 920 if (gmatch(p, pat, false)) 921 return str_nsave(str, p - str, ATEMP); 922 } 923 break; 924 } 925 926 return str; /* no match, return string */ 927 } 928 929 /* 930 * glob 931 * Name derived from V6's /etc/glob, the program that expanded filenames. 932 */ 933 934 /* XXX cp not const 'cause slashes are temporarily replaced with nulls... */ 935 static void 936 glob(char *cp, XPtrV *wp, int markdirs) 937 { 938 int oldsize = XPsize(*wp); 939 940 if (glob_str(cp, wp, markdirs) == 0) 941 XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); 942 else 943 qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize), 944 xstrcmp); 945 } 946 947 #define GF_NONE 0 948 #define GF_EXCHECK BIT(0) /* do existence check on file */ 949 #define GF_GLOBBED BIT(1) /* some globbing has been done */ 950 #define GF_MARKDIR BIT(2) /* add trailing / to directories */ 951 952 /* Apply file globbing to cp and store the matching files in wp. Returns 953 * the number of matches found. 954 */ 955 int 956 glob_str(char *cp, XPtrV *wp, int markdirs) 957 { 958 int oldsize = XPsize(*wp); 959 XString xs; 960 char *xp; 961 962 Xinit(xs, xp, 256, ATEMP); 963 globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE); 964 Xfree(xs, xp); 965 966 return XPsize(*wp) - oldsize; 967 } 968 969 static void 970 globit(XString *xs, /* dest string */ 971 char **xpp, /* ptr to dest end */ 972 char *sp, /* source path */ 973 XPtrV *wp, /* output list */ 974 int check) /* GF_* flags */ 975 { 976 char *np; /* next source component */ 977 char *xp = *xpp; 978 char *se; 979 char odirsep; 980 981 /* This to allow long expansions to be interrupted */ 982 intrcheck(); 983 984 if (sp == NULL) { /* end of source path */ 985 /* We only need to check if the file exists if a pattern 986 * is followed by a non-pattern (eg, foo*x/bar; no check 987 * is needed for foo* since the match must exist) or if 988 * any patterns were expanded and the markdirs option is set. 989 * Symlinks make things a bit tricky... 990 */ 991 if ((check & GF_EXCHECK) || 992 ((check & GF_MARKDIR) && (check & GF_GLOBBED))) { 993 #define stat_check() (stat_done ? stat_done : \ 994 (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \ 995 ? -1 : 1)) 996 struct stat lstatb, statb; 997 int stat_done = 0; /* -1: failed, 1 ok */ 998 999 if (lstat(Xstring(*xs, xp), &lstatb) < 0) 1000 return; 1001 /* special case for systems which strip trailing 1002 * slashes from regular files (eg, /etc/passwd/). 1003 * SunOS 4.1.3 does this... 1004 */ 1005 if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) && 1006 xp[-1] == '/' && !S_ISDIR(lstatb.st_mode) && 1007 (!S_ISLNK(lstatb.st_mode) || 1008 stat_check() < 0 || !S_ISDIR(statb.st_mode))) 1009 return; 1010 /* Possibly tack on a trailing / if there isn't already 1011 * one and if the file is a directory or a symlink to a 1012 * directory 1013 */ 1014 if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) && 1015 xp > Xstring(*xs, xp) && xp[-1] != '/' && 1016 (S_ISDIR(lstatb.st_mode) || 1017 (S_ISLNK(lstatb.st_mode) && stat_check() > 0 && 1018 S_ISDIR(statb.st_mode)))) { 1019 *xp++ = '/'; 1020 *xp = '\0'; 1021 } 1022 } 1023 XPput(*wp, str_nsave(Xstring(*xs, xp), Xlength(*xs, xp), ATEMP)); 1024 return; 1025 } 1026 1027 if (xp > Xstring(*xs, xp)) 1028 *xp++ = '/'; 1029 while (*sp == '/') { 1030 Xcheck(*xs, xp); 1031 *xp++ = *sp++; 1032 } 1033 np = strchr(sp, '/'); 1034 if (np != NULL) { 1035 se = np; 1036 odirsep = *np; /* don't assume '/', can be multiple kinds */ 1037 *np++ = '\0'; 1038 } else { 1039 odirsep = '\0'; /* keep gcc quiet */ 1040 se = sp + strlen(sp); 1041 } 1042 1043 1044 /* Check if sp needs globbing - done to avoid pattern checks for strings 1045 * containing MAGIC characters, open ['s without the matching close ], 1046 * etc. (otherwise opendir() will be called which may fail because the 1047 * directory isn't readable - if no globbing is needed, only execute 1048 * permission should be required (as per POSIX)). 1049 */ 1050 if (!has_globbing(sp, se)) { 1051 XcheckN(*xs, xp, se - sp + 1); 1052 debunk(xp, sp, Xnleft(*xs, xp)); 1053 xp += strlen(xp); 1054 *xpp = xp; 1055 globit(xs, xpp, np, wp, check); 1056 } else { 1057 DIR *dirp; 1058 struct dirent *d; 1059 char *name; 1060 int len; 1061 int prefix_len; 1062 1063 /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */ 1064 *xp = '\0'; 1065 prefix_len = Xlength(*xs, xp); 1066 dirp = opendir(prefix_len ? Xstring(*xs, xp) : "."); 1067 if (dirp == NULL) 1068 goto Nodir; 1069 while ((d = readdir(dirp)) != NULL) { 1070 name = d->d_name; 1071 if (name[0] == '.' && 1072 (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 1073 continue; /* always ignore . and .. */ 1074 if ((*name == '.' && *sp != '.') || 1075 !gmatch(name, sp, true)) 1076 continue; 1077 1078 len = strlen(d->d_name) + 1; 1079 XcheckN(*xs, xp, len); 1080 memcpy(xp, name, len); 1081 *xpp = xp + len - 1; 1082 globit(xs, xpp, np, wp, 1083 (check & GF_MARKDIR) | GF_GLOBBED 1084 | (np ? GF_EXCHECK : GF_NONE)); 1085 xp = Xstring(*xs, xp) + prefix_len; 1086 } 1087 closedir(dirp); 1088 Nodir:; 1089 } 1090 1091 if (np != NULL) 1092 *--np = odirsep; 1093 } 1094 1095 #if 0 1096 /* Check if p contains something that needs globbing; if it does, 0 is 1097 * returned; if not, p is copied into xs/xp after stripping any MAGICs 1098 */ 1099 static int copy_non_glob(XString *xs, char **xpp, char *p); 1100 static int 1101 copy_non_glob(XString *xs, char **xpp, char *p) 1102 { 1103 char *xp; 1104 int len = strlen(p); 1105 1106 XcheckN(*xs, *xpp, len); 1107 xp = *xpp; 1108 for (; *p; p++) { 1109 if (ISMAGIC(*p)) { 1110 int c = *++p; 1111 1112 if (c == '*' || c == '?') 1113 return 0; 1114 if (*p == '[') { 1115 char *q = p + 1; 1116 1117 if (ISMAGIC(*q) && q[1] == NOT) 1118 q += 2; 1119 if (ISMAGIC(*q) && q[1] == ']') 1120 q += 2; 1121 for (; *q; q++) 1122 if (ISMAGIC(*q) && *++q == ']') 1123 return 0; 1124 /* pass a literal [ through */ 1125 } 1126 /* must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, etc. */ 1127 } 1128 *xp++ = *p; 1129 } 1130 *xp = '\0'; 1131 *xpp = xp; 1132 return 1; 1133 } 1134 #endif /* 0 */ 1135 1136 /* remove MAGIC from string */ 1137 char * 1138 debunk(char *dp, const char *sp, size_t dlen) 1139 { 1140 char *d, *s; 1141 1142 if ((s = strchr(sp, MAGIC))) { 1143 if (s - sp >= dlen) 1144 return dp; 1145 memcpy(dp, sp, s - sp); 1146 for (d = dp + (s - sp); *s && (d - dp < dlen); s++) 1147 if (!ISMAGIC(*s) || !(*++s & 0x80) || 1148 !strchr("*+?@! ", *s & 0x7f)) 1149 *d++ = *s; 1150 else { 1151 /* extended pattern operators: *+?@! */ 1152 if ((*s & 0x7f) != ' ') 1153 *d++ = *s & 0x7f; 1154 if (d - dp < dlen) 1155 *d++ = '('; 1156 } 1157 *d = '\0'; 1158 } else if (dp != sp) 1159 strlcpy(dp, sp, dlen); 1160 return dp; 1161 } 1162 1163 /* Check if p is an unquoted name, possibly followed by a / or :. If so 1164 * puts the expanded version in *dcp,dp and returns a pointer in p just 1165 * past the name, otherwise returns 0. 1166 */ 1167 static char * 1168 maybe_expand_tilde(char *p, XString *dsp, char **dpp, int isassign) 1169 { 1170 XString ts; 1171 char *dp = *dpp; 1172 char *tp, *r; 1173 1174 Xinit(ts, tp, 16, ATEMP); 1175 /* : only for DOASNTILDE form */ 1176 while (p[0] == CHAR && p[1] != '/' && (!isassign || p[1] != ':')) 1177 { 1178 Xcheck(ts, tp); 1179 *tp++ = p[1]; 1180 p += 2; 1181 } 1182 *tp = '\0'; 1183 r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? 1184 tilde(Xstring(ts, tp)) : (char *) 0; 1185 Xfree(ts, tp); 1186 if (r) { 1187 while (*r) { 1188 Xcheck(*dsp, dp); 1189 if (ISMAGIC(*r)) 1190 *dp++ = MAGIC; 1191 *dp++ = *r++; 1192 } 1193 *dpp = dp; 1194 r = p; 1195 } 1196 return r; 1197 } 1198 1199 /* 1200 * tilde expansion 1201 * 1202 * based on a version by Arnold Robbins 1203 */ 1204 1205 static char * 1206 tilde(char *cp) 1207 { 1208 char *dp; 1209 1210 if (cp[0] == '\0') 1211 dp = str_val(global("HOME")); 1212 else if (cp[0] == '+' && cp[1] == '\0') 1213 dp = str_val(global("PWD")); 1214 else if (cp[0] == '-' && cp[1] == '\0') 1215 dp = str_val(global("OLDPWD")); 1216 else 1217 dp = homedir(cp); 1218 /* If HOME, PWD or OLDPWD are not set, don't expand ~ */ 1219 if (dp == null) 1220 dp = (char *) 0; 1221 return dp; 1222 } 1223 1224 /* 1225 * map userid to user's home directory. 1226 * note that 4.3's getpw adds more than 6K to the shell, 1227 * and the YP version probably adds much more. 1228 * we might consider our own version of getpwnam() to keep the size down. 1229 */ 1230 1231 static char * 1232 homedir(char *name) 1233 { 1234 struct tbl *ap; 1235 1236 ap = ktenter(&homedirs, name, hash(name)); 1237 if (!(ap->flag & ISSET)) { 1238 struct passwd *pw; 1239 1240 pw = getpwnam(name); 1241 if (pw == NULL) 1242 return NULL; 1243 ap->val.s = str_save(pw->pw_dir, APERM); 1244 ap->flag |= DEFINED|ISSET|ALLOC; 1245 } 1246 return ap->val.s; 1247 } 1248 1249 #ifdef BRACE_EXPAND 1250 static void 1251 alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) 1252 { 1253 int count = 0; 1254 char *brace_start, *brace_end, *comma = NULL; 1255 char *field_start; 1256 char *p; 1257 1258 /* search for open brace */ 1259 for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != OBRACE; p += 2) 1260 ; 1261 brace_start = p; 1262 1263 /* find matching close brace, if any */ 1264 if (p) { 1265 comma = (char *) 0; 1266 count = 1; 1267 for (p += 2; *p && count; p++) { 1268 if (ISMAGIC(*p)) { 1269 if (*++p == OBRACE) 1270 count++; 1271 else if (*p == CBRACE) 1272 --count; 1273 else if (*p == ',' && count == 1) 1274 comma = p; 1275 } 1276 } 1277 } 1278 /* no valid expansions... */ 1279 if (!p || count != 0) { 1280 /* Note that given a{{b,c} we do not expand anything (this is 1281 * what at&t ksh does. This may be changed to do the {b,c} 1282 * expansion. } 1283 */ 1284 if (fdo & DOGLOB) 1285 glob(start, wp, fdo & DOMARKDIRS); 1286 else 1287 XPput(*wp, debunk(start, start, end - start)); 1288 return; 1289 } 1290 brace_end = p; 1291 if (!comma) { 1292 alt_expand(wp, start, brace_end, end, fdo); 1293 return; 1294 } 1295 1296 /* expand expression */ 1297 field_start = brace_start + 2; 1298 count = 1; 1299 for (p = brace_start + 2; p != brace_end; p++) { 1300 if (ISMAGIC(*p)) { 1301 if (*++p == OBRACE) 1302 count++; 1303 else if ((*p == CBRACE && --count == 0) || 1304 (*p == ',' && count == 1)) { 1305 char *new; 1306 int l1, l2, l3; 1307 1308 l1 = brace_start - start; 1309 l2 = (p - 1) - field_start; 1310 l3 = end - brace_end; 1311 new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP); 1312 memcpy(new, start, l1); 1313 memcpy(new + l1, field_start, l2); 1314 memcpy(new + l1 + l2, brace_end, l3); 1315 new[l1 + l2 + l3] = '\0'; 1316 alt_expand(wp, new, new + l1, 1317 new + l1 + l2 + l3, fdo); 1318 field_start = p + 1; 1319 } 1320 } 1321 } 1322 return; 1323 } 1324 #endif /* BRACE_EXPAND */ 1325