1 /* $NetBSD: expand.c,v 1.123 2018/06/22 18:19:41 kre Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; 39 #else 40 __RCSID("$NetBSD: expand.c,v 1.123 2018/06/22 18:19:41 kre Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <sys/types.h> 45 #include <sys/time.h> 46 #include <sys/stat.h> 47 #include <errno.h> 48 #include <dirent.h> 49 #include <unistd.h> 50 #include <pwd.h> 51 #include <limits.h> 52 #include <stdlib.h> 53 #include <stdio.h> 54 #include <wctype.h> 55 #include <wchar.h> 56 57 /* 58 * Routines to expand arguments to commands. We have to deal with 59 * backquotes, shell variables, and file metacharacters. 60 */ 61 62 #include "shell.h" 63 #include "main.h" 64 #include "nodes.h" 65 #include "eval.h" 66 #include "expand.h" 67 #include "syntax.h" 68 #include "arithmetic.h" 69 #include "parser.h" 70 #include "jobs.h" 71 #include "options.h" 72 #include "builtins.h" 73 #include "var.h" 74 #include "input.h" 75 #include "output.h" 76 #include "memalloc.h" 77 #include "error.h" 78 #include "mystring.h" 79 #include "show.h" 80 81 /* 82 * Structure specifying which parts of the string should be searched 83 * for IFS characters. 84 */ 85 86 struct ifsregion { 87 struct ifsregion *next; /* next region in list */ 88 int begoff; /* offset of start of region */ 89 int endoff; /* offset of end of region */ 90 int inquotes; /* search for nul bytes only */ 91 }; 92 93 94 char *expdest; /* output of current string */ 95 struct nodelist *argbackq; /* list of back quote expressions */ 96 struct ifsregion ifsfirst; /* first struct in list of ifs regions */ 97 struct ifsregion *ifslastp; /* last struct in list */ 98 struct arglist exparg; /* holds expanded arg list */ 99 100 STATIC const char *argstr(const char *, int); 101 STATIC const char *exptilde(const char *, int); 102 STATIC void expbackq(union node *, int, int); 103 STATIC const char *expari(const char *); 104 STATIC int subevalvar(const char *, const char *, int, int, int); 105 STATIC int subevalvar_trim(const char *, int, int, int, int, int); 106 STATIC const char *evalvar(const char *, int); 107 STATIC int varisset(const char *, int); 108 STATIC void varvalue(const char *, int, int, int); 109 STATIC void recordregion(int, int, int); 110 STATIC void removerecordregions(int); 111 STATIC void ifsbreakup(char *, struct arglist *); 112 STATIC void ifsfree(void); 113 STATIC void expandmeta(struct strlist *, int); 114 STATIC void expmeta(char *, char *); 115 STATIC void addfname(char *); 116 STATIC struct strlist *expsort(struct strlist *); 117 STATIC struct strlist *msort(struct strlist *, int); 118 STATIC int patmatch(const char *, const char *, int); 119 STATIC char *cvtnum(int, char *); 120 static int collate_range_cmp(wchar_t, wchar_t); 121 STATIC void add_args(struct strlist *); 122 STATIC void rmescapes_nl(char *); 123 124 #ifdef DEBUG 125 #define NULLTERM_4_TRACE(p) STACKSTRNUL(p) 126 #else 127 #define NULLTERM_4_TRACE(p) do { /* nothing */ } while (/*CONSTCOND*/0) 128 #endif 129 130 /* 131 * Expand shell variables and backquotes inside a here document. 132 */ 133 134 void 135 expandhere(union node *arg, int fd) 136 { 137 138 herefd = fd; 139 expandarg(arg, NULL, 0); 140 xwrite(fd, stackblock(), expdest - stackblock()); 141 } 142 143 144 static int 145 collate_range_cmp(wchar_t c1, wchar_t c2) 146 { 147 wchar_t s1[2], s2[2]; 148 149 s1[0] = c1; 150 s1[1] = L'\0'; 151 s2[0] = c2; 152 s2[1] = L'\0'; 153 return (wcscoll(s1, s2)); 154 } 155 156 /* 157 * Perform variable substitution and command substitution on an argument, 158 * placing the resulting list of arguments in arglist. If EXP_FULL is true, 159 * perform splitting and file name expansion. When arglist is NULL, perform 160 * here document expansion. 161 */ 162 163 void 164 expandarg(union node *arg, struct arglist *arglist, int flag) 165 { 166 struct strlist *sp; 167 char *p; 168 169 CTRACE(DBG_EXPAND, ("expandarg(fl=%#x)\n", flag)); 170 if (fflag) /* no filename expandsion */ 171 flag &= ~EXP_GLOB; 172 173 argbackq = arg->narg.backquote; 174 STARTSTACKSTR(expdest); 175 ifsfirst.next = NULL; 176 ifslastp = NULL; 177 line_number = arg->narg.lineno; 178 argstr(arg->narg.text, flag); 179 if (arglist == NULL) { 180 STACKSTRNUL(expdest); 181 CTRACE(DBG_EXPAND, ("expandarg: no arglist, done (%d) \"%s\"\n", 182 expdest - stackblock(), stackblock())); 183 return; /* here document expanded */ 184 } 185 STPUTC('\0', expdest); 186 CTRACE(DBG_EXPAND, ("expandarg: arglist got (%d) \"%s\"\n", 187 expdest - stackblock() - 1, stackblock())); 188 p = grabstackstr(expdest); 189 exparg.lastp = &exparg.list; 190 /* 191 * TODO - EXP_REDIR 192 */ 193 if (flag & EXP_SPLIT) { 194 ifsbreakup(p, &exparg); 195 *exparg.lastp = NULL; 196 exparg.lastp = &exparg.list; 197 if (flag & EXP_GLOB) 198 expandmeta(exparg.list, flag); 199 else 200 add_args(exparg.list); 201 } else { 202 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ 203 rmescapes(p); 204 sp = stalloc(sizeof(*sp)); 205 sp->text = p; 206 *exparg.lastp = sp; 207 exparg.lastp = &sp->next; 208 } 209 ifsfree(); 210 *exparg.lastp = NULL; 211 if (exparg.list) { 212 *arglist->lastp = exparg.list; 213 arglist->lastp = exparg.lastp; 214 } 215 } 216 217 218 219 /* 220 * Perform variable and command substitution. 221 * If EXP_GLOB is set, output CTLESC characters to allow for further processing. 222 * If EXP_SPLIT is set, remember location of result for later, 223 * Otherwise treat $@ like $* since no splitting will be performed. 224 */ 225 226 STATIC const char * 227 argstr(const char *p, int flag) 228 { 229 char c; 230 int quotes = flag & (EXP_GLOB | EXP_CASE | EXP_REDIR); /* do CTLESC */ 231 int firsteq = 1; 232 const char *ifs = NULL; 233 int ifs_split = EXP_IFS_SPLIT; 234 235 if (flag & EXP_IFS_SPLIT) 236 ifs = ifsval(); 237 238 CTRACE(DBG_EXPAND, ("argstr(\"%s\", %#x) quotes=%#x\n", p,flag,quotes)); 239 240 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) 241 p = exptilde(p, flag); 242 for (;;) { 243 switch (c = *p++) { 244 case '\0': 245 NULLTERM_4_TRACE(expdest); 246 VTRACE(DBG_EXPAND, ("argstr returning at \"\" " 247 "added \"%s\" to expdest\n", stackblock())); 248 return p - 1; 249 case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */ 250 case CTLENDARI: /* end of a $(( )) string */ 251 NULLTERM_4_TRACE(expdest); 252 VTRACE(DBG_EXPAND, ("argstr returning at \"%.6s\"..." 253 " after %2.2X; added \"%s\" to expdest\n", 254 p, (c&0xff), stackblock())); 255 return p; 256 case CTLQUOTEMARK: 257 /* "$@" syntax adherence hack */ 258 if (p[0] == CTLVAR && p[1] & VSQUOTE && 259 p[2] == '@' && p[3] == '=') 260 break; 261 if ((flag & EXP_SPLIT) != 0) 262 STPUTC(c, expdest); 263 ifs_split = 0; 264 break; 265 case CTLNONL: 266 if (flag & EXP_NL) 267 STPUTC(c, expdest); 268 line_number++; 269 break; 270 case CTLCNL: 271 STPUTC('\n', expdest); /* no line_number++ */ 272 break; 273 case CTLQUOTEEND: 274 ifs_split = EXP_IFS_SPLIT; 275 break; 276 case CTLESC: 277 if (quotes) 278 STPUTC(c, expdest); 279 c = *p++; 280 STPUTC(c, expdest); 281 if (c == '\n') /* should not happen, but ... */ 282 line_number++; 283 break; 284 case CTLVAR: { 285 #ifdef DEBUG 286 unsigned int pos = expdest - stackblock(); 287 #endif 288 p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split)); 289 NULLTERM_4_TRACE(expdest); 290 VTRACE(DBG_EXPAND, ("argstr evalvar " 291 "added \"%s\" to expdest\n", 292 stackblock() + pos)); 293 break; 294 } 295 case CTLBACKQ: 296 case CTLBACKQ|CTLQUOTE: { 297 #ifdef DEBUG 298 unsigned int pos = expdest - stackblock(); 299 #endif 300 expbackq(argbackq->n, c & CTLQUOTE, flag); 301 argbackq = argbackq->next; 302 NULLTERM_4_TRACE(expdest); 303 VTRACE(DBG_EXPAND, ("argstr expbackq added \"%s\" " 304 "to expdest\n", stackblock() + pos)); 305 break; 306 } 307 case CTLARI: { 308 #ifdef DEBUG 309 unsigned int pos = expdest - stackblock(); 310 #endif 311 p = expari(p); 312 NULLTERM_4_TRACE(expdest); 313 VTRACE(DBG_EXPAND, ("argstr expari " 314 "+ \"%s\" to expdest p=\"%.5s...\"\n", 315 stackblock() + pos, p)); 316 break; 317 } 318 case ':': 319 case '=': 320 /* 321 * sort of a hack - expand tildes in variable 322 * assignments (after the first '=' and after ':'s). 323 */ 324 STPUTC(c, expdest); 325 if (flag & EXP_VARTILDE && *p == '~') { 326 if (c == '=') { 327 if (firsteq) 328 firsteq = 0; 329 else 330 break; 331 } 332 p = exptilde(p, flag); 333 } 334 break; 335 default: 336 if (c == '\n') 337 line_number++; 338 STPUTC(c, expdest); 339 if (flag & ifs_split && strchr(ifs, c) != NULL) { 340 /* We need to get the output split here... */ 341 recordregion(expdest - stackblock() - 1, 342 expdest - stackblock(), 0); 343 } 344 break; 345 } 346 } 347 } 348 349 STATIC const char * 350 exptilde(const char *p, int flag) 351 { 352 char c; 353 const char *startp = p; 354 struct passwd *pw; 355 const char *home; 356 int quotes = flag & (EXP_GLOB | EXP_CASE); 357 char *user; 358 struct stackmark smark; 359 #ifdef DEBUG 360 unsigned int offs = expdest - stackblock(); 361 #endif 362 363 setstackmark(&smark); 364 (void) grabstackstr(expdest); 365 user = stackblock(); /* we will just borrow top of stack */ 366 367 while ((c = *++p) != '\0') { 368 switch(c) { 369 case CTLESC: /* any of these occurring */ 370 case CTLVAR: /* means ~ expansion */ 371 case CTLBACKQ: /* does not happen at all */ 372 case CTLBACKQ | CTLQUOTE: 373 case CTLARI: /* just leave original unchanged */ 374 case CTLENDARI: 375 case CTLQUOTEMARK: 376 case '\n': 377 popstackmark(&smark); 378 return (startp); 379 case CTLNONL: 380 continue; 381 case ':': 382 if (!posix || flag & EXP_VARTILDE) 383 goto done; 384 break; 385 case CTLENDVAR: 386 case '/': 387 goto done; 388 } 389 STPUTC(c, user); 390 } 391 done: 392 STACKSTRNUL(user); 393 user = stackblock(); /* to start of collected username */ 394 395 CTRACE(DBG_EXPAND, ("exptilde, found \"~%s\"", user)); 396 if (*user == '\0') { 397 home = lookupvar("HOME"); 398 /* 399 * if HOME is unset, results are unspecified... 400 * we used to just leave the ~ unchanged, but 401 * (some) other shells do ... and this seems more useful. 402 */ 403 if (home == NULL && (pw = getpwuid(getuid())) != NULL) 404 home = pw->pw_dir; 405 } else if ((pw = getpwnam(user)) == NULL) { 406 /* 407 * If user does not exist, results are undefined. 408 * so we can abort() here if we want, but let's not! 409 */ 410 home = NULL; 411 } else 412 home = pw->pw_dir; 413 414 VTRACE(DBG_EXPAND, (" ->\"%s\"", home ? home : "<<NULL>>")); 415 popstackmark(&smark); /* now expdest is valid again */ 416 417 /* 418 * Posix XCU 2.6.1: The value of $HOME (for ~) or the initial 419 * working directory from getpwnam() for ~user 420 * Nothing there about "except if a null string". So do what it wants. 421 */ 422 if (home == NULL /* || *home == '\0' */) { 423 CTRACE(DBG_EXPAND, (": returning unused \"%s\"\n", startp)); 424 return startp; 425 } while ((c = *home++) != '\0') { 426 if (quotes && SQSYNTAX[(int)c] == CCTL) 427 STPUTC(CTLESC, expdest); 428 STPUTC(c, expdest); 429 } 430 CTRACE(DBG_EXPAND, (": added %d \"%.*s\" returning \"%s\"\n", 431 expdest - stackblock() - offs, expdest - stackblock() - offs, 432 stackblock() + offs, p)); 433 434 return (p); 435 } 436 437 438 STATIC void 439 removerecordregions(int endoff) 440 { 441 442 VTRACE(DBG_EXPAND, ("removerecordregions(%d):", endoff)); 443 if (ifslastp == NULL) { 444 VTRACE(DBG_EXPAND, (" none\n", endoff)); 445 return; 446 } 447 448 if (ifsfirst.endoff > endoff) { 449 VTRACE(DBG_EXPAND, (" first(%d)", ifsfirst.endoff)); 450 while (ifsfirst.next != NULL) { 451 struct ifsregion *ifsp; 452 INTOFF; 453 ifsp = ifsfirst.next->next; 454 ckfree(ifsfirst.next); 455 ifsfirst.next = ifsp; 456 INTON; 457 } 458 if (ifsfirst.begoff > endoff) 459 ifslastp = NULL; 460 else { 461 VTRACE(DBG_EXPAND,("->(%d,%d)",ifsfirst.begoff,endoff)); 462 ifslastp = &ifsfirst; 463 ifsfirst.endoff = endoff; 464 } 465 VTRACE(DBG_EXPAND, ("\n")); 466 return; 467 } 468 469 ifslastp = &ifsfirst; 470 while (ifslastp->next && ifslastp->next->begoff < endoff) 471 ifslastp=ifslastp->next; 472 VTRACE(DBG_EXPAND, (" found(%d,%d)", ifslastp->begoff,ifslastp->endoff)); 473 while (ifslastp->next != NULL) { 474 struct ifsregion *ifsp; 475 INTOFF; 476 ifsp = ifslastp->next->next; 477 ckfree(ifslastp->next); 478 ifslastp->next = ifsp; 479 INTON; 480 } 481 if (ifslastp->endoff > endoff) 482 ifslastp->endoff = endoff; 483 VTRACE(DBG_EXPAND, ("->(%d,%d)", ifslastp->begoff,ifslastp->endoff)); 484 } 485 486 487 /* 488 * Expand arithmetic expression. 489 * 490 * In this incarnation, we start at the beginning (yes, "Let's start at the 491 * very beginning. A very good place to start.") and collect the expression 492 * until the end - which means expanding anything contained within. 493 * 494 * Fortunately, argstr() just happens to do that for us... 495 */ 496 STATIC const char * 497 expari(const char *p) 498 { 499 char *q, *start; 500 intmax_t result; 501 int adjustment; 502 int begoff; 503 int quoted; 504 struct stackmark smark; 505 506 /* ifsfree(); */ 507 508 /* 509 * SPACE_NEEDED is enough for all possible digits (rounded up) 510 * plus possible "-", and the terminating '\0', hence, plus 2 511 * 512 * The calculation produces the number of bytes needed to 513 * represent the biggest possible value, in octal. We only 514 * generate decimal, which takes (often) less digits (never more) 515 * so this is safe, if occasionally slightly wasteful. 516 */ 517 #define SPACE_NEEDED ((int)((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 2)) 518 519 quoted = *p++ == '"'; 520 begoff = expdest - stackblock(); 521 VTRACE(DBG_EXPAND, ("expari%s: \"%s\" begoff %d\n", 522 quoted ? "(quoted)" : "", p, begoff)); 523 524 p = argstr(p, EXP_NL); /* expand $(( )) string */ 525 STPUTC('\0', expdest); 526 start = stackblock() + begoff; 527 528 removerecordregions(begoff); /* nothing there is kept */ 529 rmescapes_nl(start); /* convert CRTNONL back into \n's */ 530 531 setstackmark(&smark); 532 q = grabstackstr(expdest); /* keep the expression while eval'ing */ 533 result = arith(start, line_number); 534 popstackmark(&smark); /* return the stack to before grab */ 535 536 start = stackblock() + begoff; /* block may have moved */ 537 adjustment = expdest - start; 538 STADJUST(-adjustment, expdest); /* remove the argstr() result */ 539 540 CHECKSTRSPACE(SPACE_NEEDED, expdest); /* nb: stack block might move */ 541 fmtstr(expdest, SPACE_NEEDED, "%"PRIdMAX, result); 542 543 for (q = expdest; *q++ != '\0'; ) /* find end of what we added */ 544 ; 545 546 if (quoted == 0) /* allow weird splitting */ 547 recordregion(begoff, begoff + q - 1 - expdest, 0); 548 adjustment = q - expdest - 1; 549 STADJUST(adjustment, expdest); /* move expdest to end */ 550 VTRACE(DBG_EXPAND, ("expari: adding %d \"%s\", returning \"%.5s...\"\n", 551 adjustment, stackblock() + begoff, p)); 552 553 return p; 554 } 555 556 557 /* 558 * Expand stuff in backwards quotes (these days, any command substitution). 559 */ 560 561 STATIC void 562 expbackq(union node *cmd, int quoted, int flag) 563 { 564 struct backcmd in; 565 int i; 566 char buf[128]; 567 char *p; 568 char *dest = expdest; /* expdest may be reused by eval, use an alt */ 569 struct ifsregion saveifs, *savelastp; 570 struct nodelist *saveargbackq; 571 char lastc; 572 int startloc = dest - stackblock(); 573 char const *syntax = quoted? DQSYNTAX : BASESYNTAX; 574 int saveherefd; 575 int quotes = flag & (EXP_GLOB | EXP_CASE); 576 int nnl; 577 struct stackmark smark; 578 579 VTRACE(DBG_EXPAND, ("expbackq( ..., q=%d flag=%#x) have %d\n", 580 quoted, flag, startloc)); 581 INTOFF; 582 saveifs = ifsfirst; 583 savelastp = ifslastp; 584 saveargbackq = argbackq; 585 saveherefd = herefd; 586 herefd = -1; 587 588 setstackmark(&smark); /* preserve the stack */ 589 p = grabstackstr(dest); /* save what we have there currently */ 590 evalbackcmd(cmd, &in); /* evaluate the $( ) tree (using stack) */ 591 popstackmark(&smark); /* and return stack to when we entered */ 592 593 ifsfirst = saveifs; 594 ifslastp = savelastp; 595 argbackq = saveargbackq; 596 herefd = saveherefd; 597 598 p = in.buf; /* now extract the results */ 599 nnl = 0; /* dropping trailing \n's */ 600 for (;;) { 601 if (--in.nleft < 0) { 602 if (in.fd < 0) 603 break; 604 INTON; 605 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR) 606 continue; 607 INTOFF; 608 VTRACE(DBG_EXPAND, ("expbackq: read returns %d\n", i)); 609 if (i <= 0) 610 break; 611 p = buf; 612 in.nleft = i - 1; 613 } 614 lastc = *p++; 615 if (lastc != '\0') { 616 if (lastc == '\n') /* don't save \n yet */ 617 nnl++; /* it might be trailing */ 618 else { 619 /* 620 * We have something other than \n 621 * 622 * Before saving it, we need to insert 623 * any \n's that we have just skipped. 624 */ 625 626 /* XXX 627 * this hack is just because our 628 * CHECKSTRSPACE() is lazy, and only 629 * ever grows the stack once, even 630 * if that does not allocate the space 631 * we requested. ie: safe for small 632 * requests, but not large ones. 633 * FIXME someday... 634 */ 635 if (nnl < 20) { 636 CHECKSTRSPACE(nnl + 2, dest); 637 while (nnl > 0) { 638 nnl--; 639 USTPUTC('\n', dest); 640 } 641 } else { 642 /* The slower, safer, way */ 643 while (nnl > 0) { 644 nnl--; 645 STPUTC('\n', dest); 646 } 647 CHECKSTRSPACE(2, dest); 648 } 649 if (quotes && syntax[(int)lastc] == CCTL) 650 USTPUTC(CTLESC, dest); 651 USTPUTC(lastc, dest); 652 } 653 } 654 } 655 656 if (in.fd >= 0) 657 close(in.fd); 658 if (in.buf) 659 ckfree(in.buf); 660 if (in.jp) 661 back_exitstatus = waitforjob(in.jp); 662 if (quoted == 0) 663 recordregion(startloc, dest - stackblock(), 0); 664 CTRACE(DBG_EXPAND, ("evalbackq: size=%d: \"%.*s\"\n", 665 (int)((dest - stackblock()) - startloc), 666 (int)((dest - stackblock()) - startloc), 667 stackblock() + startloc)); 668 669 expdest = dest; /* all done, expdest is all ours again */ 670 INTON; 671 } 672 673 674 STATIC int 675 subevalvar(const char *p, const char *str, int subtype, int startloc, 676 int varflags) 677 { 678 char *startp; 679 int saveherefd = herefd; 680 struct nodelist *saveargbackq = argbackq; 681 int amount; 682 683 herefd = -1; 684 VTRACE(DBG_EXPAND, ("subevalvar(%d) \"%.20s\" ${%.*s} sloc=%d vf=%x\n", 685 subtype, p, p-str, str, startloc, varflags)); 686 argstr(p, subtype == VSASSIGN ? EXP_VARTILDE : EXP_TILDE); 687 STACKSTRNUL(expdest); 688 herefd = saveherefd; 689 argbackq = saveargbackq; 690 startp = stackblock() + startloc; 691 692 switch (subtype) { 693 case VSASSIGN: 694 setvar(str, startp, 0); 695 amount = startp - expdest; /* remove what argstr added */ 696 STADJUST(amount, expdest); 697 varflags &= ~VSNUL; /*XXX Huh? What's that achieve? */ 698 return 1; /* go back and eval var again */ 699 700 case VSQUESTION: 701 if (*p != CTLENDVAR) { 702 outfmt(&errout, "%s\n", startp); 703 error(NULL); 704 } 705 error("%.*s: parameter %snot set", 706 (int)(p - str - 1), 707 str, (varflags & VSNUL) ? "null or " 708 : nullstr); 709 /* NOTREACHED */ 710 711 default: 712 abort(); 713 } 714 } 715 716 STATIC int 717 subevalvar_trim(const char *p, int strloc, int subtype, int startloc, 718 int varflags, int quotes) 719 { 720 char *startp; 721 char *str; 722 char *loc = NULL; 723 char *q; 724 int c = 0; 725 int saveherefd = herefd; 726 struct nodelist *saveargbackq = argbackq; 727 int amount; 728 729 herefd = -1; 730 switch (subtype) { 731 case VSTRIMLEFT: 732 case VSTRIMLEFTMAX: 733 case VSTRIMRIGHT: 734 case VSTRIMRIGHTMAX: 735 break; 736 default: 737 abort(); 738 break; 739 } 740 741 VTRACE(DBG_EXPAND, 742 ("subevalvar_trim(\"%.9s\", STR@%d, SUBT=%d, start@%d, vf=%x, q=%x)\n", 743 p, strloc, subtype, startloc, varflags, quotes)); 744 745 argstr(p, (varflags & (VSQUOTE|VSPATQ)) == VSQUOTE ? 0 : EXP_CASE); 746 STACKSTRNUL(expdest); 747 herefd = saveherefd; 748 argbackq = saveargbackq; 749 startp = stackblock() + startloc; 750 str = stackblock() + strloc; 751 752 switch (subtype) { 753 754 case VSTRIMLEFT: 755 for (loc = startp; loc < str; loc++) { 756 c = *loc; 757 *loc = '\0'; 758 if (patmatch(str, startp, quotes)) 759 goto recordleft; 760 *loc = c; 761 if (quotes && *loc == CTLESC) 762 loc++; 763 } 764 return 0; 765 766 case VSTRIMLEFTMAX: 767 for (loc = str - 1; loc >= startp;) { 768 c = *loc; 769 *loc = '\0'; 770 if (patmatch(str, startp, quotes)) 771 goto recordleft; 772 *loc = c; 773 loc--; 774 if (quotes && loc > startp && 775 *(loc - 1) == CTLESC) { 776 for (q = startp; q < loc; q++) 777 if (*q == CTLESC) 778 q++; 779 if (q > loc) 780 loc--; 781 } 782 } 783 return 0; 784 785 case VSTRIMRIGHT: 786 for (loc = str - 1; loc >= startp;) { 787 if (patmatch(str, loc, quotes)) 788 goto recordright; 789 loc--; 790 if (quotes && loc > startp && 791 *(loc - 1) == CTLESC) { 792 for (q = startp; q < loc; q++) 793 if (*q == CTLESC) 794 q++; 795 if (q > loc) 796 loc--; 797 } 798 } 799 return 0; 800 801 case VSTRIMRIGHTMAX: 802 for (loc = startp; loc < str - 1; loc++) { 803 if (patmatch(str, loc, quotes)) 804 goto recordright; 805 if (quotes && *loc == CTLESC) 806 loc++; 807 } 808 return 0; 809 810 default: 811 abort(); 812 } 813 814 recordleft: 815 *loc = c; 816 amount = ((str - 1) - (loc - startp)) - expdest; 817 STADJUST(amount, expdest); 818 while (loc != str - 1) 819 *startp++ = *loc++; 820 return 1; 821 822 recordright: 823 amount = loc - expdest; 824 STADJUST(amount, expdest); 825 STPUTC('\0', expdest); 826 STADJUST(-1, expdest); 827 return 1; 828 } 829 830 831 /* 832 * Expand a variable, and return a pointer to the next character in the 833 * input string. 834 */ 835 836 STATIC const char * 837 evalvar(const char *p, int flag) 838 { 839 int subtype; 840 int varflags; 841 const char *var; 842 char *val; 843 int patloc; 844 int c; 845 int set; 846 int special; 847 int startloc; 848 int varlen; 849 int apply_ifs; 850 int quotes = flag & (EXP_GLOB | EXP_CASE | EXP_REDIR); 851 852 varflags = (unsigned char)*p++; 853 subtype = varflags & VSTYPE; 854 var = p; 855 special = !is_name(*p); 856 p = strchr(p, '=') + 1; 857 858 CTRACE(DBG_EXPAND, 859 ("evalvar \"%.*s\", flag=%#X quotes=%#X vf=%#X subtype=%X\n", 860 p - var - 1, var, flag, quotes, varflags, subtype)); 861 862 again: /* jump here after setting a variable with ${var=text} */ 863 if (varflags & VSLINENO) { 864 if (line_num.flags & VUNSET) { 865 set = 0; 866 val = NULL; 867 } else { 868 set = 1; 869 special = p - var; 870 val = NULL; 871 } 872 } else if (special) { 873 set = varisset(var, varflags & VSNUL); 874 val = NULL; 875 } else { 876 val = lookupvar(var); 877 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { 878 val = NULL; 879 set = 0; 880 } else 881 set = 1; 882 } 883 884 varlen = 0; 885 startloc = expdest - stackblock(); 886 887 if (!set && uflag && *var != '@' && *var != '*') { 888 switch (subtype) { 889 case VSNORMAL: 890 case VSTRIMLEFT: 891 case VSTRIMLEFTMAX: 892 case VSTRIMRIGHT: 893 case VSTRIMRIGHTMAX: 894 case VSLENGTH: 895 error("%.*s: parameter not set", 896 (int)(p - var - 1), var); 897 /* NOTREACHED */ 898 } 899 } 900 901 if (set && subtype != VSPLUS) { 902 /* insert the value of the variable */ 903 if (special) { 904 if (varflags & VSLINENO) { 905 /* 906 * The LINENO hack (expansion part) 907 */ 908 while (--special > 0) { 909 /* not needed, it is a number... 910 if (quotes && syntax[(int)*var] == CCTL) 911 STPUTC(CTLESC, expdest); 912 */ 913 STPUTC(*var++, expdest); 914 } 915 } else 916 varvalue(var, varflags&VSQUOTE, subtype, flag); 917 if (subtype == VSLENGTH) { 918 varlen = expdest - stackblock() - startloc; 919 STADJUST(-varlen, expdest); 920 } 921 } else { 922 char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX 923 : BASESYNTAX; 924 925 if (subtype == VSLENGTH) { 926 for (;*val; val++) 927 varlen++; 928 } else { 929 while (*val) { 930 if (quotes && syntax[(int)*val] == CCTL) 931 STPUTC(CTLESC, expdest); 932 STPUTC(*val++, expdest); 933 } 934 } 935 } 936 } 937 938 939 if (flag & EXP_IN_QUOTES) 940 apply_ifs = 0; 941 else if (varflags & VSQUOTE) { 942 if (*var == '@' && shellparam.nparam != 1) 943 apply_ifs = 1; 944 else { 945 /* 946 * Mark so that we don't apply IFS if we recurse through 947 * here expanding $bar from "${foo-$bar}". 948 */ 949 flag |= EXP_IN_QUOTES; 950 apply_ifs = 0; 951 } 952 } else 953 apply_ifs = 1; 954 955 switch (subtype) { 956 case VSLENGTH: 957 expdest = cvtnum(varlen, expdest); 958 break; 959 960 case VSNORMAL: 961 break; 962 963 case VSPLUS: 964 set = !set; 965 /* FALLTHROUGH */ 966 case VSMINUS: 967 if (!set) { 968 argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0)); 969 /* 970 * ${x-a b c} doesn't get split, but removing the 971 * 'apply_ifs = 0' apparently breaks ${1+"$@"}.. 972 * ${x-'a b' c} should generate 2 args. 973 */ 974 if (*p != CTLENDVAR) 975 /* We should have marked stuff already */ 976 apply_ifs = 0; 977 } 978 break; 979 980 case VSTRIMLEFT: 981 case VSTRIMLEFTMAX: 982 case VSTRIMRIGHT: 983 case VSTRIMRIGHTMAX: 984 if (!set) { 985 set = 1; /* allow argbackq to be advanced if needed */ 986 break; 987 } 988 /* 989 * Terminate the string and start recording the pattern 990 * right after it 991 */ 992 STPUTC('\0', expdest); 993 patloc = expdest - stackblock(); 994 if (subevalvar_trim(p, patloc, subtype, startloc, varflags, 995 quotes) == 0) { 996 int amount = (expdest - stackblock() - patloc) + 1; 997 STADJUST(-amount, expdest); 998 } 999 /* Remove any recorded regions beyond start of variable */ 1000 removerecordregions(startloc); 1001 apply_ifs = 1; 1002 break; 1003 1004 case VSASSIGN: 1005 case VSQUESTION: 1006 if (set) 1007 break; 1008 if (subevalvar(p, var, subtype, startloc, varflags)) { 1009 /* if subevalvar() returns, it always returns 1 */ 1010 1011 varflags &= ~VSNUL; 1012 /* 1013 * Remove any recorded regions beyond 1014 * start of variable 1015 */ 1016 removerecordregions(startloc); 1017 goto again; 1018 } 1019 apply_ifs = 0; /* never executed */ 1020 break; 1021 1022 default: 1023 abort(); 1024 } 1025 1026 if (apply_ifs) 1027 recordregion(startloc, expdest - stackblock(), 1028 varflags & VSQUOTE); 1029 1030 if (subtype != VSNORMAL) { /* skip to end of alternative */ 1031 int nesting = 1; 1032 for (;;) { 1033 if ((c = *p++) == CTLESC) 1034 p++; 1035 else if (c == CTLNONL) 1036 ; 1037 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { 1038 if (set) 1039 argbackq = argbackq->next; 1040 } else if (c == CTLVAR) { 1041 if ((*p++ & VSTYPE) != VSNORMAL) 1042 nesting++; 1043 } else if (c == CTLENDVAR) { 1044 if (--nesting == 0) 1045 break; 1046 } 1047 } 1048 } 1049 return p; 1050 } 1051 1052 1053 1054 /* 1055 * Test whether a special parameter is set. 1056 */ 1057 1058 STATIC int 1059 varisset(const char *name, int nulok) 1060 { 1061 if (*name == '!') 1062 return backgndpid != -1; 1063 else if (*name == '@' || *name == '*') { 1064 if (*shellparam.p == NULL) 1065 return 0; 1066 1067 if (nulok) { 1068 char **av; 1069 1070 for (av = shellparam.p; *av; av++) 1071 if (**av != '\0') 1072 return 1; 1073 return 0; 1074 } 1075 } else if (is_digit(*name)) { 1076 char *ap; 1077 long num; 1078 1079 /* 1080 * handle overflow sensibly (the *ap tests should never fail) 1081 */ 1082 errno = 0; 1083 num = strtol(name, &ap, 10); 1084 if (errno != 0 || (*ap != '\0' && *ap != '=')) 1085 return 0; 1086 1087 if (num == 0) 1088 ap = arg0; 1089 else if (num > shellparam.nparam) 1090 return 0; 1091 else 1092 ap = shellparam.p[num - 1]; 1093 1094 if (nulok && (ap == NULL || *ap == '\0')) 1095 return 0; 1096 } 1097 return 1; 1098 } 1099 1100 1101 1102 /* 1103 * Add the value of a specialized variable to the stack string. 1104 */ 1105 1106 STATIC void 1107 varvalue(const char *name, int quoted, int subtype, int flag) 1108 { 1109 int num; 1110 char *p; 1111 int i; 1112 char sep; 1113 char **ap; 1114 char const *syntax; 1115 1116 if (subtype == VSLENGTH) /* no magic required ... */ 1117 flag &= ~EXP_FULL; 1118 1119 #define STRTODEST(p) \ 1120 do {\ 1121 if (flag & (EXP_GLOB | EXP_CASE) && subtype != VSLENGTH) { \ 1122 syntax = quoted? DQSYNTAX : BASESYNTAX; \ 1123 while (*p) { \ 1124 if (syntax[(int)*p] == CCTL) \ 1125 STPUTC(CTLESC, expdest); \ 1126 STPUTC(*p++, expdest); \ 1127 } \ 1128 } else \ 1129 while (*p) \ 1130 STPUTC(*p++, expdest); \ 1131 } while (0) 1132 1133 1134 switch (*name) { 1135 case '$': 1136 num = rootpid; 1137 break; 1138 case '?': 1139 num = exitstatus; 1140 break; 1141 case '#': 1142 num = shellparam.nparam; 1143 break; 1144 case '!': 1145 num = backgndpid; 1146 break; 1147 case '-': 1148 for (i = 0; i < option_flags; i++) { 1149 if (optlist[optorder[i]].val) 1150 STPUTC(optlist[optorder[i]].letter, expdest); 1151 } 1152 return; 1153 case '@': 1154 if (flag & EXP_SPLIT && quoted) { 1155 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 1156 STRTODEST(p); 1157 if (*ap) 1158 /* A NUL separates args inside "" */ 1159 STPUTC('\0', expdest); 1160 } 1161 return; 1162 } 1163 /* fall through */ 1164 case '*': 1165 sep = ifsval()[0]; 1166 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 1167 STRTODEST(p); 1168 if (!*ap) 1169 break; 1170 if (sep) 1171 STPUTC(sep, expdest); 1172 else if ((flag & (EXP_SPLIT|EXP_IN_QUOTES)) == EXP_SPLIT 1173 && !quoted && **ap != '\0') 1174 STPUTC('\0', expdest); 1175 } 1176 return; 1177 default: 1178 if (is_digit(*name)) { 1179 long lnum; 1180 1181 errno = 0; 1182 lnum = strtol(name, &p, 10); 1183 if (errno != 0 || (*p != '\0' && *p != '=')) 1184 return; 1185 1186 if (lnum == 0) 1187 p = arg0; 1188 else if (lnum > 0 && lnum <= shellparam.nparam) 1189 p = shellparam.p[lnum - 1]; 1190 else 1191 return; 1192 STRTODEST(p); 1193 } 1194 return; 1195 } 1196 /* 1197 * only the specials with an int value arrive here 1198 */ 1199 expdest = cvtnum(num, expdest); 1200 } 1201 1202 1203 1204 /* 1205 * Record the fact that we have to scan this region of the 1206 * string for IFS characters. 1207 */ 1208 1209 STATIC void 1210 recordregion(int start, int end, int inquotes) 1211 { 1212 struct ifsregion *ifsp; 1213 1214 VTRACE(DBG_EXPAND, ("recordregion(%d,%d,%d)\n", start, end, inquotes)); 1215 if (ifslastp == NULL) { 1216 ifsp = &ifsfirst; 1217 } else { 1218 if (ifslastp->endoff == start 1219 && ifslastp->inquotes == inquotes) { 1220 /* extend previous area */ 1221 ifslastp->endoff = end; 1222 return; 1223 } 1224 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); 1225 ifslastp->next = ifsp; 1226 } 1227 ifslastp = ifsp; 1228 ifslastp->next = NULL; 1229 ifslastp->begoff = start; 1230 ifslastp->endoff = end; 1231 ifslastp->inquotes = inquotes; 1232 } 1233 1234 1235 1236 /* 1237 * Break the argument string into pieces based upon IFS and add the 1238 * strings to the argument list. The regions of the string to be 1239 * searched for IFS characters have been stored by recordregion. 1240 */ 1241 STATIC void 1242 ifsbreakup(char *string, struct arglist *arglist) 1243 { 1244 struct ifsregion *ifsp; 1245 struct strlist *sp; 1246 char *start; 1247 char *p; 1248 char *q; 1249 const char *ifs; 1250 const char *ifsspc; 1251 int had_param_ch = 0; 1252 1253 start = string; 1254 1255 VTRACE(DBG_EXPAND, ("ifsbreakup(\"%s\")", string)); /* misses \0's */ 1256 if (ifslastp == NULL) { 1257 /* Return entire argument, IFS doesn't apply to any of it */ 1258 VTRACE(DBG_EXPAND, ("no regions\n", string)); 1259 sp = stalloc(sizeof(*sp)); 1260 sp->text = start; 1261 *arglist->lastp = sp; 1262 arglist->lastp = &sp->next; 1263 return; 1264 } 1265 1266 ifs = ifsval(); 1267 1268 for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { 1269 p = string + ifsp->begoff; 1270 VTRACE(DBG_EXPAND, (" !%.*s!(%d)", ifsp->endoff-ifsp->begoff, 1271 p, ifsp->endoff-ifsp->begoff)); 1272 while (p < string + ifsp->endoff) { 1273 had_param_ch = 1; 1274 q = p; 1275 if (*p == CTLNONL) { 1276 p++; 1277 continue; 1278 } 1279 if (*p == CTLESC) 1280 p++; 1281 if (ifsp->inquotes) { 1282 /* Only NULs (should be from "$@") end args */ 1283 if (*p != 0) { 1284 p++; 1285 continue; 1286 } 1287 ifsspc = NULL; 1288 VTRACE(DBG_EXPAND, (" \\0 nxt:\"%s\" ", p)); 1289 } else { 1290 if (!strchr(ifs, *p)) { 1291 p++; 1292 continue; 1293 } 1294 had_param_ch = 0; 1295 ifsspc = strchr(" \t\n", *p); 1296 1297 /* Ignore IFS whitespace at start */ 1298 if (q == start && ifsspc != NULL) { 1299 p++; 1300 start = p; 1301 continue; 1302 } 1303 } 1304 1305 /* Save this argument... */ 1306 *q = '\0'; 1307 VTRACE(DBG_EXPAND, ("<%s>", start)); 1308 sp = stalloc(sizeof(*sp)); 1309 sp->text = start; 1310 *arglist->lastp = sp; 1311 arglist->lastp = &sp->next; 1312 p++; 1313 1314 if (ifsspc != NULL) { 1315 /* Ignore further trailing IFS whitespace */ 1316 for (; p < string + ifsp->endoff; p++) { 1317 q = p; 1318 if (*p == CTLNONL) 1319 continue; 1320 if (*p == CTLESC) 1321 p++; 1322 if (strchr(ifs, *p) == NULL) { 1323 p = q; 1324 break; 1325 } 1326 if (strchr(" \t\n", *p) == NULL) { 1327 p++; 1328 break; 1329 } 1330 } 1331 } 1332 start = p; 1333 } 1334 } 1335 1336 /* 1337 * Save anything left as an argument. 1338 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as 1339 * generating 2 arguments, the second of which is empty. 1340 * Some recent clarification of the Posix spec say that it 1341 * should only generate one.... 1342 */ 1343 if (had_param_ch || *start != 0) { 1344 VTRACE(DBG_EXPAND, (" T<%s>", start)); 1345 sp = stalloc(sizeof(*sp)); 1346 sp->text = start; 1347 *arglist->lastp = sp; 1348 arglist->lastp = &sp->next; 1349 } 1350 VTRACE(DBG_EXPAND, ("\n")); 1351 } 1352 1353 STATIC void 1354 ifsfree(void) 1355 { 1356 while (ifsfirst.next != NULL) { 1357 struct ifsregion *ifsp; 1358 INTOFF; 1359 ifsp = ifsfirst.next->next; 1360 ckfree(ifsfirst.next); 1361 ifsfirst.next = ifsp; 1362 INTON; 1363 } 1364 ifslastp = NULL; 1365 ifsfirst.next = NULL; 1366 } 1367 1368 1369 1370 /* 1371 * Expand shell metacharacters. At this point, the only control characters 1372 * should be escapes. The results are stored in the list exparg. 1373 */ 1374 1375 char *expdir; 1376 1377 1378 STATIC void 1379 expandmeta(struct strlist *str, int flag) 1380 { 1381 char *p; 1382 struct strlist **savelastp; 1383 struct strlist *sp; 1384 char c; 1385 /* TODO - EXP_REDIR */ 1386 1387 while (str) { 1388 p = str->text; 1389 for (;;) { /* fast check for meta chars */ 1390 if ((c = *p++) == '\0') 1391 goto nometa; 1392 if (c == '*' || c == '?' || c == '[' || c == '!') 1393 break; 1394 } 1395 savelastp = exparg.lastp; 1396 INTOFF; 1397 if (expdir == NULL) { 1398 int i = strlen(str->text); 1399 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ 1400 } 1401 1402 expmeta(expdir, str->text); 1403 ckfree(expdir); 1404 expdir = NULL; 1405 INTON; 1406 if (exparg.lastp == savelastp) { 1407 /* 1408 * no matches 1409 */ 1410 nometa: 1411 *exparg.lastp = str; 1412 rmescapes(str->text); 1413 exparg.lastp = &str->next; 1414 } else { 1415 *exparg.lastp = NULL; 1416 *savelastp = sp = expsort(*savelastp); 1417 while (sp->next != NULL) 1418 sp = sp->next; 1419 exparg.lastp = &sp->next; 1420 } 1421 str = str->next; 1422 } 1423 } 1424 1425 STATIC void 1426 add_args(struct strlist *str) 1427 { 1428 while (str) { 1429 *exparg.lastp = str; 1430 rmescapes(str->text); 1431 exparg.lastp = &str->next; 1432 str = str->next; 1433 } 1434 } 1435 1436 1437 /* 1438 * Do metacharacter (i.e. *, ?, [...]) expansion. 1439 */ 1440 1441 STATIC void 1442 expmeta(char *enddir, char *name) 1443 { 1444 char *p; 1445 const char *cp; 1446 char *q; 1447 char *start; 1448 char *endname; 1449 int metaflag; 1450 struct stat statb; 1451 DIR *dirp; 1452 struct dirent *dp; 1453 int atend; 1454 int matchdot; 1455 1456 metaflag = 0; 1457 start = name; 1458 for (p = name ; ; p++) { 1459 if (*p == '*' || *p == '?') 1460 metaflag = 1; 1461 else if (*p == '[') { 1462 q = p + 1; 1463 if (*q == '!') 1464 q++; 1465 for (;;) { 1466 while (*q == CTLQUOTEMARK || *q == CTLNONL) 1467 q++; 1468 if (*q == CTLESC) 1469 q++; 1470 if (*q == '/' || *q == '\0') 1471 break; 1472 if (*++q == ']') { 1473 metaflag = 1; 1474 break; 1475 } 1476 } 1477 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { 1478 metaflag = 1; 1479 } else if (*p == '\0') 1480 break; 1481 else if (*p == CTLQUOTEMARK || *p == CTLNONL) 1482 continue; 1483 else if (*p == CTLESC) 1484 p++; 1485 if (*p == '/') { 1486 if (metaflag) 1487 break; 1488 start = p + 1; 1489 } 1490 } 1491 if (metaflag == 0) { /* we've reached the end of the file name */ 1492 if (enddir != expdir) 1493 metaflag++; 1494 for (p = name ; ; p++) { 1495 if (*p == CTLQUOTEMARK || *p == CTLNONL) 1496 continue; 1497 if (*p == CTLESC) 1498 p++; 1499 *enddir++ = *p; 1500 if (*p == '\0') 1501 break; 1502 } 1503 if (metaflag == 0 || lstat(expdir, &statb) >= 0) 1504 addfname(expdir); 1505 return; 1506 } 1507 endname = p; 1508 if (start != name) { 1509 p = name; 1510 while (p < start) { 1511 while (*p == CTLQUOTEMARK || *p == CTLNONL) 1512 p++; 1513 if (*p == CTLESC) 1514 p++; 1515 *enddir++ = *p++; 1516 } 1517 } 1518 if (enddir == expdir) { 1519 cp = "."; 1520 } else if (enddir == expdir + 1 && *expdir == '/') { 1521 cp = "/"; 1522 } else { 1523 cp = expdir; 1524 enddir[-1] = '\0'; 1525 } 1526 if ((dirp = opendir(cp)) == NULL) 1527 return; 1528 if (enddir != expdir) 1529 enddir[-1] = '/'; 1530 if (*endname == 0) { 1531 atend = 1; 1532 } else { 1533 atend = 0; 1534 *endname++ = '\0'; 1535 } 1536 matchdot = 0; 1537 p = start; 1538 while (*p == CTLQUOTEMARK || *p == CTLNONL) 1539 p++; 1540 if (*p == CTLESC) 1541 p++; 1542 if (*p == '.') 1543 matchdot++; 1544 while (! int_pending() && (dp = readdir(dirp)) != NULL) { 1545 if (dp->d_name[0] == '.' && ! matchdot) 1546 continue; 1547 if (patmatch(start, dp->d_name, 0)) { 1548 if (atend) { 1549 scopy(dp->d_name, enddir); 1550 addfname(expdir); 1551 } else { 1552 for (p = enddir, cp = dp->d_name; 1553 (*p++ = *cp++) != '\0';) 1554 continue; 1555 p[-1] = '/'; 1556 expmeta(p, endname); 1557 } 1558 } 1559 } 1560 closedir(dirp); 1561 if (! atend) 1562 endname[-1] = '/'; 1563 } 1564 1565 1566 /* 1567 * Add a file name to the list. 1568 */ 1569 1570 STATIC void 1571 addfname(char *name) 1572 { 1573 char *p; 1574 struct strlist *sp; 1575 1576 p = stalloc(strlen(name) + 1); 1577 scopy(name, p); 1578 sp = stalloc(sizeof(*sp)); 1579 sp->text = p; 1580 *exparg.lastp = sp; 1581 exparg.lastp = &sp->next; 1582 } 1583 1584 1585 /* 1586 * Sort the results of file name expansion. It calculates the number of 1587 * strings to sort and then calls msort (short for merge sort) to do the 1588 * work. 1589 */ 1590 1591 STATIC struct strlist * 1592 expsort(struct strlist *str) 1593 { 1594 int len; 1595 struct strlist *sp; 1596 1597 len = 0; 1598 for (sp = str ; sp ; sp = sp->next) 1599 len++; 1600 return msort(str, len); 1601 } 1602 1603 1604 STATIC struct strlist * 1605 msort(struct strlist *list, int len) 1606 { 1607 struct strlist *p, *q = NULL; 1608 struct strlist **lpp; 1609 int half; 1610 int n; 1611 1612 if (len <= 1) 1613 return list; 1614 half = len >> 1; 1615 p = list; 1616 for (n = half ; --n >= 0 ; ) { 1617 q = p; 1618 p = p->next; 1619 } 1620 q->next = NULL; /* terminate first half of list */ 1621 q = msort(list, half); /* sort first half of list */ 1622 p = msort(p, len - half); /* sort second half */ 1623 lpp = &list; 1624 for (;;) { 1625 if (strcmp(p->text, q->text) < 0) { 1626 *lpp = p; 1627 lpp = &p->next; 1628 if ((p = *lpp) == NULL) { 1629 *lpp = q; 1630 break; 1631 } 1632 } else { 1633 *lpp = q; 1634 lpp = &q->next; 1635 if ((q = *lpp) == NULL) { 1636 *lpp = p; 1637 break; 1638 } 1639 } 1640 } 1641 return list; 1642 } 1643 1644 1645 /* 1646 * See if a character matches a character class, starting at the first colon 1647 * of "[:class:]". 1648 * If a valid character class is recognized, a pointer to the next character 1649 * after the final closing bracket is stored into *end, otherwise a null 1650 * pointer is stored into *end. 1651 */ 1652 static int 1653 match_charclass(const char *p, wchar_t chr, const char **end) 1654 { 1655 char name[20]; 1656 char *nameend; 1657 wctype_t cclass; 1658 1659 *end = NULL; 1660 p++; 1661 nameend = strstr(p, ":]"); 1662 if (nameend == NULL || nameend == p) /* not a valid class */ 1663 return 0; 1664 1665 if (!is_alpha(*p) || strspn(p, /* '_' is a local extension */ 1666 "0123456789" "_" 1667 "abcdefghijklmnopqrstuvwxyz" 1668 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != (size_t)(nameend - p)) 1669 return 0; 1670 1671 *end = nameend + 2; /* committed to it being a char class */ 1672 if ((size_t)(nameend - p) >= sizeof(name)) /* but too long */ 1673 return 0; /* so no match */ 1674 memcpy(name, p, nameend - p); 1675 name[nameend - p] = '\0'; 1676 cclass = wctype(name); 1677 /* An unknown class matches nothing but is valid nevertheless. */ 1678 if (cclass == 0) 1679 return 0; 1680 return iswctype(chr, cclass); 1681 } 1682 1683 1684 /* 1685 * Returns true if the pattern matches the string. 1686 */ 1687 1688 STATIC int 1689 patmatch(const char *pattern, const char *string, int squoted) 1690 { 1691 const char *p, *q, *end; 1692 const char *bt_p, *bt_q; 1693 char c; 1694 wchar_t wc, wc2; 1695 1696 p = pattern; 1697 q = string; 1698 bt_p = NULL; 1699 bt_q = NULL; 1700 for (;;) { 1701 switch (c = *p++) { 1702 case '\0': 1703 if (*q != '\0') 1704 goto backtrack; 1705 return 1; 1706 case CTLESC: 1707 if (squoted && *q == CTLESC) 1708 q++; 1709 if (*q++ != *p++) 1710 goto backtrack; 1711 break; 1712 case CTLQUOTEMARK: 1713 case CTLNONL: 1714 continue; 1715 case '?': 1716 if (squoted && *q == CTLESC) 1717 q++; 1718 if (*q++ == '\0') 1719 return 0; 1720 break; 1721 case '*': 1722 c = *p; 1723 while (c == CTLQUOTEMARK || c == '*') 1724 c = *++p; 1725 if (c != CTLESC && c != CTLQUOTEMARK && c != CTLNONL && 1726 c != '?' && c != '*' && c != '[') { 1727 while (*q != c) { 1728 if (squoted && *q == CTLESC && 1729 q[1] == c) 1730 break; 1731 if (*q == '\0') 1732 return 0; 1733 if (squoted && *q == CTLESC) 1734 q++; 1735 q++; 1736 } 1737 } 1738 /* 1739 * First try the shortest match for the '*' that 1740 * could work. We can forget any earlier '*' since 1741 * there is no way having it match more characters 1742 * can help us, given that we are already here. 1743 */ 1744 bt_p = p; 1745 bt_q = q; 1746 break; 1747 case '[': { 1748 const char *savep, *saveq, *endp; 1749 int invert, found; 1750 unsigned char chr; 1751 1752 endp = p; 1753 if (*endp == '!') 1754 endp++; 1755 for (;;) { 1756 while (*endp == CTLQUOTEMARK || *endp==CTLNONL) 1757 endp++; 1758 if (*endp == '\0') 1759 goto dft; /* no matching ] */ 1760 if (*endp == CTLESC) 1761 endp++; 1762 if (*++endp == ']') 1763 break; 1764 } 1765 invert = 0; 1766 savep = p, saveq = q; 1767 invert = 0; 1768 if (*p == '!' || *p == '^') { 1769 invert++; 1770 p++; 1771 } 1772 found = 0; 1773 if (*q == '\0') 1774 return 0; 1775 chr = (unsigned char)*q++; 1776 c = *p++; 1777 do { 1778 if (c == CTLQUOTEMARK || c == CTLNONL) 1779 continue; 1780 if (c == '\0') { 1781 p = savep, q = saveq; 1782 c = '['; 1783 goto dft; 1784 } 1785 if (c == '[' && *p == ':') { 1786 found |= match_charclass(p, chr, &end); 1787 if (end != NULL) { 1788 p = end; 1789 continue; 1790 } 1791 } 1792 if (c == CTLESC) 1793 c = *p++; 1794 wc = (unsigned char)c; 1795 if (*p == '-' && p[1] != ']') { 1796 p++; 1797 if (*p == CTLESC) 1798 p++; 1799 wc2 = (unsigned char)*p++; 1800 if ( collate_range_cmp(chr, wc) >= 0 1801 && collate_range_cmp(chr, wc2) <= 0 1802 ) 1803 found = 1; 1804 } else { 1805 if (chr == wc) 1806 found = 1; 1807 } 1808 } while ((c = *p++) != ']'); 1809 if (found == invert) 1810 goto backtrack; 1811 break; 1812 } 1813 dft: default: 1814 if (squoted && *q == CTLESC) 1815 q++; 1816 if (*q++ == c) 1817 break; 1818 backtrack: 1819 /* 1820 * If we have a mismatch (other than hitting the end 1821 * of the string), go back to the last '*' seen and 1822 * have it match one additional character. 1823 */ 1824 if (bt_p == NULL) 1825 return 0; 1826 if (*bt_q == '\0') 1827 return 0; 1828 bt_q++; 1829 p = bt_p; 1830 q = bt_q; 1831 break; 1832 } 1833 } 1834 } 1835 1836 1837 1838 /* 1839 * Remove any CTLESC or CTLNONL characters from a string. 1840 */ 1841 1842 void 1843 rmescapes(char *str) 1844 { 1845 char *p, *q; 1846 1847 p = str; 1848 while (*p != CTLESC && *p != CTLQUOTEMARK && *p != CTLNONL) { 1849 if (*p++ == '\0') 1850 return; 1851 } 1852 q = p; 1853 while (*p) { 1854 if (*p == CTLQUOTEMARK || *p == CTLNONL) { 1855 p++; 1856 continue; 1857 } 1858 if (*p == CTLCNL) { 1859 p++; 1860 *q++ = '\n'; 1861 continue; 1862 } 1863 if (*p == CTLESC) 1864 p++; 1865 *q++ = *p++; 1866 } 1867 *q = '\0'; 1868 } 1869 1870 /* 1871 * and a special version for dealing with expressions to be parsed 1872 * by the arithmetic evaluator. That needs to be able to count \n's 1873 * even ones that were \newline elided \n's, so we have to put the 1874 * latter back into the string - just being careful to put them only 1875 * at a place where white space can reasonably occur in the string 1876 * -- then the \n we insert will just be white space, and ignored 1877 * for all purposes except line counting. 1878 */ 1879 1880 void 1881 rmescapes_nl(char *str) 1882 { 1883 char *p, *q; 1884 int nls = 0, holdnl = 0, holdlast; 1885 1886 p = str; 1887 while (*p != CTLESC && *p != CTLQUOTEMARK && *p != CTLNONL) { 1888 if (*p++ == '\0') 1889 return; 1890 } 1891 if (p > str) /* must reprocess char before stopper (if any) */ 1892 --p; /* so we do not place a \n badly */ 1893 q = p; 1894 while (*p) { 1895 if (*p == CTLQUOTEMARK) { 1896 p++; 1897 continue; 1898 } 1899 if (*p == CTLNONL) { 1900 p++; 1901 nls++; 1902 continue; 1903 } 1904 if (*p == CTLCNL) { 1905 p++; 1906 *q++ = '\n'; 1907 continue; 1908 } 1909 if (*p == CTLESC) 1910 p++; 1911 1912 holdlast = holdnl; 1913 holdnl = is_in_name(*p); /* letters, digits, _ */ 1914 if (q == str || is_space(q[-1]) || (*p != '=' && q[-1] != *p)) { 1915 if (nls > 0 && holdnl != holdlast) { 1916 while (nls > 0) 1917 *q++ = '\n', nls--; 1918 } 1919 } 1920 *q++ = *p++; 1921 } 1922 while (--nls >= 0) 1923 *q++ = '\n'; 1924 *q = '\0'; 1925 } 1926 1927 1928 1929 /* 1930 * See if a pattern matches in a case statement. 1931 */ 1932 1933 int 1934 casematch(union node *pattern, char *val) 1935 { 1936 struct stackmark smark; 1937 int result; 1938 char *p; 1939 1940 setstackmark(&smark); 1941 argbackq = pattern->narg.backquote; 1942 STARTSTACKSTR(expdest); 1943 ifslastp = NULL; 1944 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); 1945 STPUTC('\0', expdest); 1946 p = grabstackstr(expdest); 1947 result = patmatch(p, val, 0); 1948 popstackmark(&smark); 1949 return result; 1950 } 1951 1952 /* 1953 * Our own itoa(). Assumes result buffer is on the stack 1954 */ 1955 1956 STATIC char * 1957 cvtnum(int num, char *buf) 1958 { 1959 char temp[32]; 1960 int neg = num < 0; 1961 char *p = temp + sizeof temp - 1; 1962 1963 if (neg) 1964 num = -num; 1965 1966 *p = '\0'; 1967 do { 1968 *--p = num % 10 + '0'; 1969 } while ((num /= 10) != 0 && p > temp + 1); 1970 1971 if (neg) 1972 *--p = '-'; 1973 1974 while (*p) 1975 STPUTC(*p++, buf); 1976 return buf; 1977 } 1978 1979 /* 1980 * Do most of the work for wordexp(3). 1981 */ 1982 1983 int 1984 wordexpcmd(int argc, char **argv) 1985 { 1986 size_t len; 1987 int i; 1988 1989 out1fmt("%d", argc - 1); 1990 out1c('\0'); 1991 for (i = 1, len = 0; i < argc; i++) 1992 len += strlen(argv[i]); 1993 out1fmt("%zu", len); 1994 out1c('\0'); 1995 for (i = 1; i < argc; i++) { 1996 out1str(argv[i]); 1997 out1c('\0'); 1998 } 1999 return (0); 2000 } 2001