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