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