1 /* $OpenBSD: eval.c,v 1.36 2011/03/15 08:39:54 okan 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 (newlines) { /* Spit out saved nl's */ 509 c = '\n'; 510 --newlines; 511 } else { 512 while ((c = shf_getc(x.u.shf)) == 0 || c == '\n') 513 if (c == '\n') 514 newlines++; /* Save newlines */ 515 if (newlines && c != EOF) { 516 shf_ungetc(c, x.u.shf); 517 c = '\n'; 518 --newlines; 519 } 520 } 521 if (c == EOF) { 522 newlines = 0; 523 shf_close(x.u.shf); 524 if (x.split) 525 subst_exstat = waitlast(); 526 type = XBASE; 527 if (f&DOBLANK) 528 doblank--; 529 continue; 530 } 531 break; 532 } 533 534 /* check for end of word or IFS separation */ 535 if (c == 0 || (!quote && (f & DOBLANK) && doblank && 536 !make_magic && ctype(c, C_IFS))) { 537 /* How words are broken up: 538 * | value of c 539 * word | ws nws 0 540 * ----------------------------------- 541 * IFS_WORD w/WS w/NWS w 542 * IFS_WS -/WS w/NWS - 543 * IFS_NWS -/NWS w/NWS w 544 * (w means generate a word) 545 * Note that IFS_NWS/0 generates a word (at&t ksh 546 * doesn't do this, but POSIX does). 547 */ 548 if (word == IFS_WORD || 549 (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) { 550 char *p; 551 552 *dp++ = '\0'; 553 p = Xclose(ds, dp); 554 #ifdef BRACE_EXPAND 555 if (fdo & DOBRACE_) 556 /* also does globbing */ 557 alt_expand(wp, p, p, 558 p + Xlength(ds, (dp - 1)), 559 fdo | (f & DOMARKDIRS)); 560 else 561 #endif /* BRACE_EXPAND */ 562 if (fdo & DOGLOB) 563 glob(p, wp, f & DOMARKDIRS); 564 else if ((f & DOPAT) || !(fdo & DOMAGIC_)) 565 XPput(*wp, p); 566 else 567 XPput(*wp, debunk(p, p, strlen(p) + 1)); 568 fdo = 0; 569 saw_eq = 0; 570 tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; 571 if (c != 0) 572 Xinit(ds, dp, 128, ATEMP); 573 } 574 if (c == 0) 575 return; 576 if (word != IFS_NWS) 577 word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; 578 } else { 579 if (type == XSUB) { 580 if (word == IFS_NWS && 581 Xlength(ds, dp) == 0) { 582 char *p; 583 584 if ((p = strdup("")) == NULL) 585 internal_errorf(1, "unable " 586 "to allocate memory"); 587 XPput(*wp, p); 588 } 589 type = XSUBMID; 590 } 591 592 /* age tilde_ok info - ~ code tests second bit */ 593 tilde_ok <<= 1; 594 /* mark any special second pass chars */ 595 if (!quote) 596 switch (c) { 597 case '[': 598 case NOT: 599 case '-': 600 case ']': 601 /* For character classes - doesn't hurt 602 * to have magic !,-,]'s outside of 603 * [...] expressions. 604 */ 605 if (f & (DOPAT | DOGLOB)) { 606 fdo |= DOMAGIC_; 607 if (c == '[') 608 fdo |= f & DOGLOB; 609 *dp++ = MAGIC; 610 } 611 break; 612 case '*': 613 case '?': 614 if (f & (DOPAT | DOGLOB)) { 615 fdo |= DOMAGIC_ | (f & DOGLOB); 616 *dp++ = MAGIC; 617 } 618 break; 619 #ifdef BRACE_EXPAND 620 case OBRACE: 621 case ',': 622 case CBRACE: 623 if ((f & DOBRACE_) && (c == OBRACE || 624 (fdo & DOBRACE_))) { 625 fdo |= DOBRACE_|DOMAGIC_; 626 *dp++ = MAGIC; 627 } 628 break; 629 #endif /* BRACE_EXPAND */ 630 case '=': 631 /* Note first unquoted = for ~ */ 632 if (!(f & DOTEMP_) && !saw_eq) { 633 saw_eq = 1; 634 tilde_ok = 1; 635 } 636 break; 637 case ':': /* : */ 638 /* Note unquoted : for ~ */ 639 if (!(f & DOTEMP_) && (f & DOASNTILDE)) 640 tilde_ok = 1; 641 break; 642 case '~': 643 /* tilde_ok is reset whenever 644 * any of ' " $( $(( ${ } are seen. 645 * Note that tilde_ok must be preserved 646 * through the sequence ${A=a=}~ 647 */ 648 if (type == XBASE && 649 (f & (DOTILDE|DOASNTILDE)) && 650 (tilde_ok & 2)) { 651 char *p, *dp_x; 652 653 dp_x = dp; 654 p = maybe_expand_tilde(sp, 655 &ds, &dp_x, 656 f & DOASNTILDE); 657 if (p) { 658 if (dp != dp_x) 659 word = IFS_WORD; 660 dp = dp_x; 661 sp = p; 662 continue; 663 } 664 } 665 break; 666 } 667 else 668 quote &= ~2; /* undo temporary */ 669 670 if (make_magic) { 671 make_magic = 0; 672 fdo |= DOMAGIC_ | (f & DOGLOB); 673 *dp++ = MAGIC; 674 } else if (ISMAGIC(c)) { 675 fdo |= DOMAGIC_; 676 *dp++ = MAGIC; 677 } 678 *dp++ = c; /* save output char */ 679 word = IFS_WORD; 680 } 681 } 682 } 683 684 /* 685 * Prepare to generate the string returned by ${} substitution. 686 */ 687 static int 688 varsub(Expand *xp, char *sp, char *word, 689 int *stypep, /* becomes qualifier type */ 690 int *slenp) /* " " len (=, :=, etc.) valid iff *stypep != 0 */ 691 { 692 int c; 693 int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */ 694 int stype; /* substitution type */ 695 int slen; 696 char *p; 697 struct tbl *vp; 698 699 if (sp[0] == '\0') /* Bad variable name */ 700 return -1; 701 702 xp->var = (struct tbl *) 0; 703 704 /* ${#var}, string length or array size */ 705 if (sp[0] == '#' && (c = sp[1]) != '\0') { 706 int zero_ok = 0; 707 708 /* Can't have any modifiers for ${#...} */ 709 if (*word != CSUBST) 710 return -1; 711 sp++; 712 /* Check for size of array */ 713 if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { 714 int n = 0; 715 int max = 0; 716 717 vp = global(arrayname(sp)); 718 if (vp->flag & (ISSET|ARRAY)) 719 zero_ok = 1; 720 for (; vp; vp = vp->u.array) 721 if (vp->flag & ISSET) { 722 max = vp->index + 1; 723 n++; 724 } 725 c = n; /* ksh88/ksh93 go for number, not max index */ 726 } else if (c == '*' || c == '@') 727 c = e->loc->argc; 728 else { 729 p = str_val(global(sp)); 730 zero_ok = p != null; 731 c = strlen(p); 732 } 733 if (Flag(FNOUNSET) && c == 0 && !zero_ok) 734 errorf("%s: parameter not set", sp); 735 *stypep = 0; /* unqualified variable/string substitution */ 736 xp->str = str_save(ulton((unsigned long)c, 10), ATEMP); 737 return XSUB; 738 } 739 740 /* Check for qualifiers in word part */ 741 stype = 0; 742 c = word[slen = 0] == CHAR ? word[1] : 0; 743 if (c == ':') { 744 slen += 2; 745 stype = 0x80; 746 c = word[slen + 0] == CHAR ? word[slen + 1] : 0; 747 } 748 if (ctype(c, C_SUBOP1)) { 749 slen += 2; 750 stype |= c; 751 } else if (ctype(c, C_SUBOP2)) { /* Note: ksh88 allows :%, :%%, etc */ 752 slen += 2; 753 stype = c; 754 if (word[slen + 0] == CHAR && c == word[slen + 1]) { 755 stype |= 0x80; 756 slen += 2; 757 } 758 } else if (stype) /* : is not ok */ 759 return -1; 760 if (!stype && *word != CSUBST) 761 return -1; 762 *stypep = stype; 763 *slenp = slen; 764 765 c = sp[0]; 766 if (c == '*' || c == '@') { 767 switch (stype & 0x7f) { 768 case '=': /* can't assign to a vector */ 769 case '%': /* can't trim a vector (yet) */ 770 case '#': 771 return -1; 772 } 773 if (e->loc->argc == 0) { 774 xp->str = null; 775 xp->var = global(sp); 776 state = c == '@' ? XNULLSUB : XSUB; 777 } else { 778 xp->u.strv = (const char **) e->loc->argv + 1; 779 xp->str = *xp->u.strv++; 780 xp->split = c == '@'; /* $@ */ 781 state = XARG; 782 } 783 } else { 784 if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { 785 XPtrV wv; 786 787 switch (stype & 0x7f) { 788 case '=': /* can't assign to a vector */ 789 case '%': /* can't trim a vector (yet) */ 790 case '#': 791 case '?': 792 return -1; 793 } 794 XPinit(wv, 32); 795 vp = global(arrayname(sp)); 796 for (; vp; vp = vp->u.array) { 797 if (!(vp->flag&ISSET)) 798 continue; 799 XPput(wv, str_val(vp)); 800 } 801 if (XPsize(wv) == 0) { 802 xp->str = null; 803 state = p[1] == '@' ? XNULLSUB : XSUB; 804 XPfree(wv); 805 } else { 806 XPput(wv, 0); 807 xp->u.strv = (const char **) XPptrv(wv); 808 xp->str = *xp->u.strv++; 809 xp->split = p[1] == '@'; /* ${foo[@]} */ 810 state = XARG; 811 } 812 } else { 813 /* Can't assign things like $! or $1 */ 814 if ((stype & 0x7f) == '=' && 815 (ctype(*sp, C_VAR1) || digit(*sp))) 816 return -1; 817 xp->var = global(sp); 818 xp->str = str_val(xp->var); 819 state = XSUB; 820 } 821 } 822 823 c = stype&0x7f; 824 /* test the compiler's code generator */ 825 if (ctype(c, C_SUBOP2) || 826 (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */ 827 c == '=' || c == '-' || c == '?' : c == '+')) 828 state = XBASE; /* expand word instead of variable value */ 829 if (Flag(FNOUNSET) && xp->str == null && 830 (ctype(c, C_SUBOP2) || (state != XBASE && c != '+'))) 831 errorf("%s: parameter not set", sp); 832 return state; 833 } 834 835 /* 836 * Run the command in $(...) and read its output. 837 */ 838 static int 839 comsub(Expand *xp, char *cp) 840 { 841 Source *s, *sold; 842 struct op *t; 843 struct shf *shf; 844 845 s = pushs(SSTRING, ATEMP); 846 s->start = s->str = cp; 847 sold = source; 848 t = compile(s); 849 afree(s, ATEMP); 850 source = sold; 851 852 if (t == NULL) 853 return XBASE; 854 855 if (t != NULL && t->type == TCOM && /* $(<file) */ 856 *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { 857 struct ioword *io = *t->ioact; 858 char *name; 859 860 if ((io->flag&IOTYPE) != IOREAD) 861 errorf("funny $() command: %s", 862 snptreef((char *) 0, 32, "%R", io)); 863 shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0, 864 SHF_MAPHI|SHF_CLEXEC); 865 if (shf == NULL) 866 errorf("%s: cannot open $() input", name); 867 xp->split = 0; /* no waitlast() */ 868 } else { 869 int ofd1, pv[2]; 870 openpipe(pv); 871 shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0); 872 ofd1 = savefd(1); 873 if (pv[1] != 1) { 874 ksh_dup2(pv[1], 1, false); 875 close(pv[1]); 876 } 877 execute(t, XFORK|XXCOM|XPIPEO, NULL); 878 restfd(1, ofd1); 879 startlast(); 880 xp->split = 1; /* waitlast() */ 881 } 882 883 xp->u.shf = shf; 884 return XCOM; 885 } 886 887 /* 888 * perform #pattern and %pattern substitution in ${} 889 */ 890 891 static char * 892 trimsub(char *str, char *pat, int how) 893 { 894 char *end = strchr(str, 0); 895 char *p, c; 896 897 switch (how&0xff) { /* UCHAR_MAX maybe? */ 898 case '#': /* shortest at beginning */ 899 for (p = str; p <= end; p++) { 900 c = *p; *p = '\0'; 901 if (gmatch(str, pat, false)) { 902 *p = c; 903 return p; 904 } 905 *p = c; 906 } 907 break; 908 case '#'|0x80: /* longest match at beginning */ 909 for (p = end; p >= str; p--) { 910 c = *p; *p = '\0'; 911 if (gmatch(str, pat, false)) { 912 *p = c; 913 return p; 914 } 915 *p = c; 916 } 917 break; 918 case '%': /* shortest match at end */ 919 for (p = end; p >= str; p--) { 920 if (gmatch(p, pat, false)) 921 return str_nsave(str, p - str, ATEMP); 922 } 923 break; 924 case '%'|0x80: /* longest match at end */ 925 for (p = str; p <= end; p++) { 926 if (gmatch(p, pat, false)) 927 return str_nsave(str, p - str, ATEMP); 928 } 929 break; 930 } 931 932 return str; /* no match, return string */ 933 } 934 935 /* 936 * glob 937 * Name derived from V6's /etc/glob, the program that expanded filenames. 938 */ 939 940 /* XXX cp not const 'cause slashes are temporarily replaced with nulls... */ 941 static void 942 glob(char *cp, XPtrV *wp, int markdirs) 943 { 944 int oldsize = XPsize(*wp); 945 946 if (glob_str(cp, wp, markdirs) == 0) 947 XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); 948 else 949 qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize), 950 xstrcmp); 951 } 952 953 #define GF_NONE 0 954 #define GF_EXCHECK BIT(0) /* do existence check on file */ 955 #define GF_GLOBBED BIT(1) /* some globbing has been done */ 956 #define GF_MARKDIR BIT(2) /* add trailing / to directories */ 957 958 /* Apply file globbing to cp and store the matching files in wp. Returns 959 * the number of matches found. 960 */ 961 int 962 glob_str(char *cp, XPtrV *wp, int markdirs) 963 { 964 int oldsize = XPsize(*wp); 965 XString xs; 966 char *xp; 967 968 Xinit(xs, xp, 256, ATEMP); 969 globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE); 970 Xfree(xs, xp); 971 972 return XPsize(*wp) - oldsize; 973 } 974 975 static void 976 globit(XString *xs, /* dest string */ 977 char **xpp, /* ptr to dest end */ 978 char *sp, /* source path */ 979 XPtrV *wp, /* output list */ 980 int check) /* GF_* flags */ 981 { 982 char *np; /* next source component */ 983 char *xp = *xpp; 984 char *se; 985 char odirsep; 986 987 /* This to allow long expansions to be interrupted */ 988 intrcheck(); 989 990 if (sp == NULL) { /* end of source path */ 991 /* We only need to check if the file exists if a pattern 992 * is followed by a non-pattern (eg, foo*x/bar; no check 993 * is needed for foo* since the match must exist) or if 994 * any patterns were expanded and the markdirs option is set. 995 * Symlinks make things a bit tricky... 996 */ 997 if ((check & GF_EXCHECK) || 998 ((check & GF_MARKDIR) && (check & GF_GLOBBED))) { 999 #define stat_check() (stat_done ? stat_done : \ 1000 (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \ 1001 ? -1 : 1)) 1002 struct stat lstatb, statb; 1003 int stat_done = 0; /* -1: failed, 1 ok */ 1004 1005 if (lstat(Xstring(*xs, xp), &lstatb) < 0) 1006 return; 1007 /* special case for systems which strip trailing 1008 * slashes from regular files (eg, /etc/passwd/). 1009 * SunOS 4.1.3 does this... 1010 */ 1011 if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) && 1012 xp[-1] == '/' && !S_ISDIR(lstatb.st_mode) && 1013 (!S_ISLNK(lstatb.st_mode) || 1014 stat_check() < 0 || !S_ISDIR(statb.st_mode))) 1015 return; 1016 /* Possibly tack on a trailing / if there isn't already 1017 * one and if the file is a directory or a symlink to a 1018 * directory 1019 */ 1020 if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) && 1021 xp > Xstring(*xs, xp) && xp[-1] != '/' && 1022 (S_ISDIR(lstatb.st_mode) || 1023 (S_ISLNK(lstatb.st_mode) && stat_check() > 0 && 1024 S_ISDIR(statb.st_mode)))) { 1025 *xp++ = '/'; 1026 *xp = '\0'; 1027 } 1028 } 1029 XPput(*wp, str_nsave(Xstring(*xs, xp), Xlength(*xs, xp), ATEMP)); 1030 return; 1031 } 1032 1033 if (xp > Xstring(*xs, xp)) 1034 *xp++ = '/'; 1035 while (*sp == '/') { 1036 Xcheck(*xs, xp); 1037 *xp++ = *sp++; 1038 } 1039 np = strchr(sp, '/'); 1040 if (np != NULL) { 1041 se = np; 1042 odirsep = *np; /* don't assume '/', can be multiple kinds */ 1043 *np++ = '\0'; 1044 } else { 1045 odirsep = '\0'; /* keep gcc quiet */ 1046 se = sp + strlen(sp); 1047 } 1048 1049 1050 /* Check if sp needs globbing - done to avoid pattern checks for strings 1051 * containing MAGIC characters, open ['s without the matching close ], 1052 * etc. (otherwise opendir() will be called which may fail because the 1053 * directory isn't readable - if no globbing is needed, only execute 1054 * permission should be required (as per POSIX)). 1055 */ 1056 if (!has_globbing(sp, se)) { 1057 XcheckN(*xs, xp, se - sp + 1); 1058 debunk(xp, sp, Xnleft(*xs, xp)); 1059 xp += strlen(xp); 1060 *xpp = xp; 1061 globit(xs, xpp, np, wp, check); 1062 } else { 1063 DIR *dirp; 1064 struct dirent *d; 1065 char *name; 1066 int len; 1067 int prefix_len; 1068 1069 /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */ 1070 *xp = '\0'; 1071 prefix_len = Xlength(*xs, xp); 1072 dirp = opendir(prefix_len ? Xstring(*xs, xp) : "."); 1073 if (dirp == NULL) 1074 goto Nodir; 1075 while ((d = readdir(dirp)) != NULL) { 1076 name = d->d_name; 1077 if (name[0] == '.' && 1078 (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 1079 continue; /* always ignore . and .. */ 1080 if ((*name == '.' && *sp != '.') || 1081 !gmatch(name, sp, true)) 1082 continue; 1083 1084 len = strlen(d->d_name) + 1; 1085 XcheckN(*xs, xp, len); 1086 memcpy(xp, name, len); 1087 *xpp = xp + len - 1; 1088 globit(xs, xpp, np, wp, 1089 (check & GF_MARKDIR) | GF_GLOBBED 1090 | (np ? GF_EXCHECK : GF_NONE)); 1091 xp = Xstring(*xs, xp) + prefix_len; 1092 } 1093 closedir(dirp); 1094 Nodir:; 1095 } 1096 1097 if (np != NULL) 1098 *--np = odirsep; 1099 } 1100 1101 #if 0 1102 /* Check if p contains something that needs globbing; if it does, 0 is 1103 * returned; if not, p is copied into xs/xp after stripping any MAGICs 1104 */ 1105 static int copy_non_glob(XString *xs, char **xpp, char *p); 1106 static int 1107 copy_non_glob(XString *xs, char **xpp, char *p) 1108 { 1109 char *xp; 1110 int len = strlen(p); 1111 1112 XcheckN(*xs, *xpp, len); 1113 xp = *xpp; 1114 for (; *p; p++) { 1115 if (ISMAGIC(*p)) { 1116 int c = *++p; 1117 1118 if (c == '*' || c == '?') 1119 return 0; 1120 if (*p == '[') { 1121 char *q = p + 1; 1122 1123 if (ISMAGIC(*q) && q[1] == NOT) 1124 q += 2; 1125 if (ISMAGIC(*q) && q[1] == ']') 1126 q += 2; 1127 for (; *q; q++) 1128 if (ISMAGIC(*q) && *++q == ']') 1129 return 0; 1130 /* pass a literal [ through */ 1131 } 1132 /* must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, etc. */ 1133 } 1134 *xp++ = *p; 1135 } 1136 *xp = '\0'; 1137 *xpp = xp; 1138 return 1; 1139 } 1140 #endif /* 0 */ 1141 1142 /* remove MAGIC from string */ 1143 char * 1144 debunk(char *dp, const char *sp, size_t dlen) 1145 { 1146 char *d, *s; 1147 1148 if ((s = strchr(sp, MAGIC))) { 1149 if (s - sp >= dlen) 1150 return dp; 1151 memcpy(dp, sp, s - sp); 1152 for (d = dp + (s - sp); *s && (d - dp < dlen); s++) 1153 if (!ISMAGIC(*s) || !(*++s & 0x80) || 1154 !strchr("*+?@! ", *s & 0x7f)) 1155 *d++ = *s; 1156 else { 1157 /* extended pattern operators: *+?@! */ 1158 if ((*s & 0x7f) != ' ') 1159 *d++ = *s & 0x7f; 1160 if (d - dp < dlen) 1161 *d++ = '('; 1162 } 1163 *d = '\0'; 1164 } else if (dp != sp) 1165 strlcpy(dp, sp, dlen); 1166 return dp; 1167 } 1168 1169 /* Check if p is an unquoted name, possibly followed by a / or :. If so 1170 * puts the expanded version in *dcp,dp and returns a pointer in p just 1171 * past the name, otherwise returns 0. 1172 */ 1173 static char * 1174 maybe_expand_tilde(char *p, XString *dsp, char **dpp, int isassign) 1175 { 1176 XString ts; 1177 char *dp = *dpp; 1178 char *tp, *r; 1179 1180 Xinit(ts, tp, 16, ATEMP); 1181 /* : only for DOASNTILDE form */ 1182 while (p[0] == CHAR && p[1] != '/' && (!isassign || p[1] != ':')) 1183 { 1184 Xcheck(ts, tp); 1185 *tp++ = p[1]; 1186 p += 2; 1187 } 1188 *tp = '\0'; 1189 r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? 1190 tilde(Xstring(ts, tp)) : (char *) 0; 1191 Xfree(ts, tp); 1192 if (r) { 1193 while (*r) { 1194 Xcheck(*dsp, dp); 1195 if (ISMAGIC(*r)) 1196 *dp++ = MAGIC; 1197 *dp++ = *r++; 1198 } 1199 *dpp = dp; 1200 r = p; 1201 } 1202 return r; 1203 } 1204 1205 /* 1206 * tilde expansion 1207 * 1208 * based on a version by Arnold Robbins 1209 */ 1210 1211 static char * 1212 tilde(char *cp) 1213 { 1214 char *dp; 1215 1216 if (cp[0] == '\0') 1217 dp = str_val(global("HOME")); 1218 else if (cp[0] == '+' && cp[1] == '\0') 1219 dp = str_val(global("PWD")); 1220 else if (cp[0] == '-' && cp[1] == '\0') 1221 dp = str_val(global("OLDPWD")); 1222 else 1223 dp = homedir(cp); 1224 /* If HOME, PWD or OLDPWD are not set, don't expand ~ */ 1225 if (dp == null) 1226 dp = (char *) 0; 1227 return dp; 1228 } 1229 1230 /* 1231 * map userid to user's home directory. 1232 * note that 4.3's getpw adds more than 6K to the shell, 1233 * and the YP version probably adds much more. 1234 * we might consider our own version of getpwnam() to keep the size down. 1235 */ 1236 1237 static char * 1238 homedir(char *name) 1239 { 1240 struct tbl *ap; 1241 1242 ap = ktenter(&homedirs, name, hash(name)); 1243 if (!(ap->flag & ISSET)) { 1244 struct passwd *pw; 1245 1246 pw = getpwnam(name); 1247 if (pw == NULL) 1248 return NULL; 1249 ap->val.s = str_save(pw->pw_dir, APERM); 1250 ap->flag |= DEFINED|ISSET|ALLOC; 1251 } 1252 return ap->val.s; 1253 } 1254 1255 #ifdef BRACE_EXPAND 1256 static void 1257 alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) 1258 { 1259 int count = 0; 1260 char *brace_start, *brace_end, *comma = NULL; 1261 char *field_start; 1262 char *p; 1263 1264 /* search for open brace */ 1265 for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != OBRACE; p += 2) 1266 ; 1267 brace_start = p; 1268 1269 /* find matching close brace, if any */ 1270 if (p) { 1271 comma = (char *) 0; 1272 count = 1; 1273 for (p += 2; *p && count; p++) { 1274 if (ISMAGIC(*p)) { 1275 if (*++p == OBRACE) 1276 count++; 1277 else if (*p == CBRACE) 1278 --count; 1279 else if (*p == ',' && count == 1) 1280 comma = p; 1281 } 1282 } 1283 } 1284 /* no valid expansions... */ 1285 if (!p || count != 0) { 1286 /* Note that given a{{b,c} we do not expand anything (this is 1287 * what at&t ksh does. This may be changed to do the {b,c} 1288 * expansion. } 1289 */ 1290 if (fdo & DOGLOB) 1291 glob(start, wp, fdo & DOMARKDIRS); 1292 else 1293 XPput(*wp, debunk(start, start, end - start)); 1294 return; 1295 } 1296 brace_end = p; 1297 if (!comma) { 1298 alt_expand(wp, start, brace_end, end, fdo); 1299 return; 1300 } 1301 1302 /* expand expression */ 1303 field_start = brace_start + 2; 1304 count = 1; 1305 for (p = brace_start + 2; p != brace_end; p++) { 1306 if (ISMAGIC(*p)) { 1307 if (*++p == OBRACE) 1308 count++; 1309 else if ((*p == CBRACE && --count == 0) || 1310 (*p == ',' && count == 1)) { 1311 char *new; 1312 int l1, l2, l3; 1313 1314 l1 = brace_start - start; 1315 l2 = (p - 1) - field_start; 1316 l3 = end - brace_end; 1317 new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP); 1318 memcpy(new, start, l1); 1319 memcpy(new + l1, field_start, l2); 1320 memcpy(new + l1 + l2, brace_end, l3); 1321 new[l1 + l2 + l3] = '\0'; 1322 alt_expand(wp, new, new + l1, 1323 new + l1 + l2 + l3, fdo); 1324 field_start = p + 1; 1325 } 1326 } 1327 } 1328 return; 1329 } 1330 #endif /* BRACE_EXPAND */ 1331