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