/contrib/tcsh/sh.glob.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1037 lines · 804 code · 95 blank · 138 comment · 322 complexity · f913745ac510fa5e429c5d4adb1567bf MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.glob.c,v 3.82 2011/02/27 00:15:17 christos Exp $ */
  2. /*
  3. * sh.glob.c: Regular expression expansion
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "sh.h"
  34. RCSID("$tcsh: sh.glob.c,v 3.82 2011/02/27 00:15:17 christos Exp $")
  35. #include "tc.h"
  36. #include "tw.h"
  37. #include "glob.h"
  38. /*
  39. * Values for gflag
  40. */
  41. #define G_NONE 0 /* No globbing needed */
  42. #define G_GLOB 1 /* string contains *?[] characters */
  43. #define G_CSH 2 /* string contains ~`{ characters */
  44. #define GLOBSPACE 100 /* Alloc increment */
  45. #define LBRC '{'
  46. #define RBRC '}'
  47. #define LBRK '['
  48. #define RBRK ']'
  49. #define EOS '\0'
  50. /*
  51. * globbing is now done in two stages. In the first pass we expand
  52. * csh globbing idioms ~`{ and then we proceed doing the normal
  53. * globbing if needed ?*[
  54. *
  55. * Csh type globbing is handled in globexpand() and the rest is
  56. * handled in glob() which is part of the 4.4BSD libc.
  57. *
  58. */
  59. static Char *globtilde (Char *);
  60. static Char *handleone (Char *, Char **, int);
  61. static Char **libglob (Char **);
  62. static Char **globexpand (Char **, int);
  63. static int globbrace (const Char *, Char ***);
  64. static void expbrace (Char ***, Char ***, int);
  65. static void pword (struct blk_buf *, struct Strbuf *);
  66. static void backeval (struct blk_buf *, struct Strbuf *, Char *,
  67. int);
  68. static Char *
  69. globtilde(Char *s)
  70. {
  71. Char *name, *u, *home, *res;
  72. u = s;
  73. for (s++; *s && *s != '/' && *s != ':'; s++)
  74. continue;
  75. name = Strnsave(u + 1, s - (u + 1));
  76. cleanup_push(name, xfree);
  77. home = gethdir(name);
  78. if (home == NULL) {
  79. if (adrof(STRnonomatch)) {
  80. cleanup_until(name);
  81. return u;
  82. }
  83. if (*name)
  84. stderror(ERR_UNKUSER, short2str(name));
  85. else
  86. stderror(ERR_NOHOME);
  87. }
  88. cleanup_until(name);
  89. if (home[0] == '/' && home[1] == '\0' && s[0] == '/')
  90. res = Strsave(s);
  91. else
  92. res = Strspl(home, s);
  93. xfree(home);
  94. xfree(u);
  95. return res;
  96. }
  97. /* Returns a newly allocated string, old or NULL */
  98. Char *
  99. globequal(Char *old)
  100. {
  101. int dig;
  102. const Char *dir;
  103. Char *b;
  104. /*
  105. * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
  106. * in stack. PWP: let =foobar pass through (for X windows)
  107. */
  108. if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
  109. /* =- */
  110. const Char *olddir = varval (STRowd);
  111. if (olddir && *olddir &&
  112. !dcwd->di_next->di_name && !dcwd->di_prev->di_name)
  113. return Strspl(olddir, &old[2]);
  114. dig = -1;
  115. b = &old[2];
  116. }
  117. else if (Isdigit(old[1])) {
  118. /* =<number> */
  119. dig = old[1] - '0';
  120. for (b = &old[2]; Isdigit(*b); b++)
  121. dig = dig * 10 + (*b - '0');
  122. if (*b != '\0' && *b != '/')
  123. /* =<number>foobar */
  124. return old;
  125. }
  126. else
  127. /* =foobar */
  128. return old;
  129. dir = getstakd(dig);
  130. if (dir == NULL)
  131. return NULL;
  132. return Strspl(dir, b);
  133. }
  134. static int
  135. globbrace(const Char *s, Char ***bl)
  136. {
  137. struct Strbuf gbuf = Strbuf_INIT;
  138. struct blk_buf bb = BLK_BUF_INIT;
  139. int i;
  140. const Char *p, *pm, *pe, *pl;
  141. size_t prefix_len;
  142. /* copy part up to the brace */
  143. for (p = s; *p != LBRC; p++)
  144. ;
  145. prefix_len = p - s;
  146. /* check for balanced braces */
  147. for (i = 0, pe = ++p; *pe; pe++)
  148. if (*pe == LBRK) {
  149. /* Ignore everything between [] */
  150. for (++pe; *pe != RBRK && *pe != EOS; pe++)
  151. continue;
  152. if (*pe == EOS)
  153. return (-RBRK);
  154. }
  155. else if (*pe == LBRC)
  156. i++;
  157. else if (*pe == RBRC) {
  158. if (i == 0)
  159. break;
  160. i--;
  161. }
  162. if (i != 0 || *pe == '\0')
  163. return (-RBRC);
  164. Strbuf_appendn(&gbuf, s, prefix_len);
  165. for (i = 0, pl = pm = p; pm <= pe; pm++)
  166. switch (*pm) {
  167. case LBRK:
  168. for (++pm; *pm != RBRK && *pm != EOS; pm++)
  169. continue;
  170. if (*pm == EOS) {
  171. bb_cleanup(&bb);
  172. xfree(gbuf.s);
  173. return (-RBRK);
  174. }
  175. break;
  176. case LBRC:
  177. i++;
  178. break;
  179. case RBRC:
  180. if (i) {
  181. i--;
  182. break;
  183. }
  184. /* FALLTHROUGH */
  185. case ',':
  186. if (i && *pm == ',')
  187. break;
  188. else {
  189. gbuf.len = prefix_len;
  190. Strbuf_appendn(&gbuf, pl, pm - pl);
  191. Strbuf_append(&gbuf, pe + 1);
  192. Strbuf_terminate(&gbuf);
  193. bb_append(&bb, Strsave(gbuf.s));
  194. pl = pm + 1;
  195. }
  196. break;
  197. default:
  198. break;
  199. }
  200. *bl = bb_finish(&bb);
  201. xfree(gbuf.s);
  202. return bb.len;
  203. }
  204. static void
  205. expbrace(Char ***nvp, Char ***elp, int size)
  206. {
  207. Char **vl, **el, **nv, *s;
  208. vl = nv = *nvp;
  209. if (elp != NULL)
  210. el = *elp;
  211. else
  212. el = vl + blklen(vl);
  213. for (s = *vl; s; s = *++vl) {
  214. Char **vp, **bp;
  215. /* leave {} untouched for find */
  216. if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
  217. continue;
  218. if (Strchr(s, '{') != NULL) {
  219. Char **bl = NULL;
  220. int len;
  221. if ((len = globbrace(s, &bl)) < 0)
  222. stderror(ERR_MISSING, -len);
  223. xfree(s);
  224. if (len == 1) {
  225. *vl-- = *bl;
  226. xfree(bl);
  227. continue;
  228. }
  229. if (&el[len] >= &nv[size]) {
  230. size_t l, e;
  231. l = &el[len] - &nv[size];
  232. size += GLOBSPACE > l ? GLOBSPACE : l;
  233. l = vl - nv;
  234. e = el - nv;
  235. nv = xrealloc(nv, size * sizeof(Char *));
  236. *nvp = nv; /* To keep cleanups working */
  237. vl = nv + l;
  238. el = nv + e;
  239. }
  240. /* nv vl el bl
  241. * | | | |
  242. * -.--..-- x--
  243. * | len
  244. * vp
  245. */
  246. vp = vl--;
  247. *vp = *bl;
  248. len--;
  249. for (bp = el; bp != vp; bp--)
  250. bp[len] = *bp;
  251. el += len;
  252. /* nv vl el bl
  253. * | | | |
  254. * -.-x --- --
  255. * |len
  256. * vp
  257. */
  258. vp++;
  259. for (bp = bl + 1; *bp; *vp++ = *bp++)
  260. continue;
  261. xfree(bl);
  262. }
  263. }
  264. if (elp != NULL)
  265. *elp = el;
  266. }
  267. static Char **
  268. globexpand(Char **v, int noglob)
  269. {
  270. Char *s;
  271. Char ***fnv, **vl, **el;
  272. int size = GLOBSPACE;
  273. fnv = xmalloc(sizeof(Char ***));
  274. *fnv = vl = xmalloc(sizeof(Char *) * size);
  275. *vl = NULL;
  276. cleanup_push(fnv, blk_indirect_cleanup);
  277. /*
  278. * Step 1: expand backquotes.
  279. */
  280. while ((s = *v++) != '\0') {
  281. if (Strchr(s, '`')) {
  282. int i;
  283. Char **expanded;
  284. expanded = dobackp(s, 0);
  285. for (i = 0; expanded[i] != NULL; i++) {
  286. *vl++ = expanded[i];
  287. if (vl == &(*fnv)[size]) {
  288. size += GLOBSPACE;
  289. *fnv = xrealloc(*fnv, size * sizeof(Char *));
  290. vl = &(*fnv)[size - GLOBSPACE];
  291. }
  292. }
  293. xfree(expanded);
  294. }
  295. else {
  296. *vl++ = Strsave(s);
  297. if (vl == &(*fnv)[size]) {
  298. size += GLOBSPACE;
  299. *fnv = xrealloc(*fnv, size * sizeof(Char *));
  300. vl = &(*fnv)[size - GLOBSPACE];
  301. }
  302. }
  303. *vl = NULL;
  304. }
  305. if (noglob)
  306. goto done;
  307. /*
  308. * Step 2: expand braces
  309. */
  310. el = vl;
  311. expbrace(fnv, &el, size);
  312. /*
  313. * Step 3: expand ~ =
  314. */
  315. vl = *fnv;
  316. for (s = *vl; s; s = *++vl)
  317. switch (*s) {
  318. Char *ns;
  319. case '~':
  320. *vl = globtilde(s);
  321. break;
  322. case '=':
  323. if ((ns = globequal(s)) == NULL) {
  324. if (!adrof(STRnonomatch))
  325. stderror(ERR_DEEP); /* Error */
  326. }
  327. if (ns && ns != s) {
  328. /* Expansion succeeded */
  329. xfree(s);
  330. *vl = ns;
  331. }
  332. break;
  333. default:
  334. break;
  335. }
  336. vl = *fnv;
  337. /*
  338. * Step 4: expand .. if the variable symlinks==expand is set
  339. */
  340. if (symlinks == SYM_EXPAND) {
  341. for (s = *vl; s; s = *++vl) {
  342. *vl = dnormalize(s, 1);
  343. xfree(s);
  344. }
  345. }
  346. done:
  347. cleanup_ignore(fnv);
  348. cleanup_until(fnv);
  349. vl = *fnv;
  350. xfree(fnv);
  351. return vl;
  352. }
  353. static Char *
  354. handleone(Char *str, Char **vl, int action)
  355. {
  356. size_t chars;
  357. Char **t, *p, *strp;
  358. switch (action) {
  359. case G_ERROR:
  360. setname(short2str(str));
  361. blkfree(vl);
  362. stderror(ERR_NAME | ERR_AMBIG);
  363. break;
  364. case G_APPEND:
  365. chars = 0;
  366. for (t = vl; (p = *t++) != NULL; chars++)
  367. chars += Strlen(p);
  368. str = xmalloc(chars * sizeof(Char));
  369. for (t = vl, strp = str; (p = *t++) != '\0'; chars++) {
  370. while (*p)
  371. *strp++ = *p++ & TRIM;
  372. *strp++ = ' ';
  373. }
  374. *--strp = '\0';
  375. blkfree(vl);
  376. break;
  377. case G_IGNORE:
  378. str = Strsave(strip(*vl));
  379. blkfree(vl);
  380. break;
  381. default:
  382. break;
  383. }
  384. return (str);
  385. }
  386. static Char **
  387. libglob(Char **vl)
  388. {
  389. int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
  390. glob_t globv;
  391. char *ptr;
  392. int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
  393. if (adrof(STRglobdot))
  394. gflgs |= GLOB_DOT;
  395. if (adrof(STRglobstar))
  396. gflgs |= GLOB_STAR;
  397. if (!vl || !vl[0])
  398. return(vl);
  399. globv.gl_offs = 0;
  400. globv.gl_pathv = 0;
  401. globv.gl_pathc = 0;
  402. if (nonomatch)
  403. gflgs |= GLOB_NOCHECK;
  404. do {
  405. ptr = short2qstr(*vl);
  406. switch (glob(ptr, gflgs, 0, &globv)) {
  407. case GLOB_ABEND:
  408. globfree(&globv);
  409. setname(ptr);
  410. stderror(ERR_NAME | ERR_GLOB);
  411. /* NOTREACHED */
  412. case GLOB_NOSPACE:
  413. globfree(&globv);
  414. stderror(ERR_NOMEM);
  415. /* NOTREACHED */
  416. default:
  417. break;
  418. }
  419. if (globv.gl_flags & GLOB_MAGCHAR) {
  420. match |= (globv.gl_matchc != 0);
  421. magic = 1;
  422. }
  423. gflgs |= GLOB_APPEND;
  424. }
  425. while (*++vl);
  426. vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
  427. NULL : blk2short(globv.gl_pathv);
  428. globfree(&globv);
  429. return (vl);
  430. }
  431. Char *
  432. globone(Char *str, int action)
  433. {
  434. Char *v[2], **vl, **vo;
  435. int gflg, noglob;
  436. noglob = adrof(STRnoglob) != 0;
  437. v[0] = str;
  438. v[1] = 0;
  439. gflg = tglob(v);
  440. if (gflg == G_NONE)
  441. return (strip(Strsave(str)));
  442. if (gflg & G_CSH) {
  443. /*
  444. * Expand back-quote, tilde and brace
  445. */
  446. vo = globexpand(v, noglob);
  447. if (noglob || (gflg & G_GLOB) == 0) {
  448. vl = vo;
  449. goto result;
  450. }
  451. cleanup_push(vo, blk_cleanup);
  452. }
  453. else if (noglob || (gflg & G_GLOB) == 0)
  454. return (strip(Strsave(str)));
  455. else
  456. vo = v;
  457. vl = libglob(vo);
  458. if (gflg & G_CSH) {
  459. if (vl != vo)
  460. cleanup_until(vo);
  461. else
  462. cleanup_ignore(vo);
  463. }
  464. if (vl == NULL) {
  465. setname(short2str(str));
  466. stderror(ERR_NAME | ERR_NOMATCH);
  467. }
  468. result:
  469. if (vl && vl[0] == NULL) {
  470. xfree(vl);
  471. return (Strsave(STRNULL));
  472. }
  473. if (vl && vl[1])
  474. return (handleone(str, vl, action));
  475. else {
  476. str = strip(*vl);
  477. xfree(vl);
  478. return (str);
  479. }
  480. }
  481. Char **
  482. globall(Char **v, int gflg)
  483. {
  484. Char **vl, **vo;
  485. int noglob;
  486. if (!v || !v[0])
  487. return saveblk(v);
  488. noglob = adrof(STRnoglob) != 0;
  489. if (gflg & G_CSH)
  490. /*
  491. * Expand back-quote, tilde and brace
  492. */
  493. vl = vo = globexpand(v, noglob);
  494. else
  495. vl = vo = saveblk(v);
  496. if (!noglob && (gflg & G_GLOB)) {
  497. cleanup_push(vo, blk_cleanup);
  498. vl = libglob(vo);
  499. if (vl == vo)
  500. cleanup_ignore(vo);
  501. cleanup_until(vo);
  502. }
  503. else
  504. trim(vl);
  505. return vl;
  506. }
  507. Char **
  508. glob_all_or_error(Char **v)
  509. {
  510. int gflag;
  511. gflag = tglob(v);
  512. if (gflag) {
  513. v = globall(v, gflag);
  514. if (v == NULL)
  515. stderror(ERR_NAME | ERR_NOMATCH);
  516. } else {
  517. v = saveblk(v);
  518. trim(v);
  519. }
  520. return v;
  521. }
  522. void
  523. rscan(Char **t, void (*f) (Char))
  524. {
  525. Char *p;
  526. while ((p = *t++) != '\0')
  527. while (*p)
  528. (*f) (*p++);
  529. }
  530. void
  531. trim(Char **t)
  532. {
  533. Char *p;
  534. while ((p = *t++) != '\0')
  535. while (*p)
  536. *p++ &= TRIM;
  537. }
  538. int
  539. tglob(Char **t)
  540. {
  541. int gflag;
  542. const Char *p;
  543. gflag = 0;
  544. while ((p = *t++) != '\0') {
  545. if (*p == '~' || *p == '=')
  546. gflag |= G_CSH;
  547. else if (*p == '{' &&
  548. (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
  549. continue;
  550. while (*p != '\0') {
  551. if (*p == '`') {
  552. gflag |= G_CSH;
  553. #ifdef notdef
  554. /*
  555. * We do want to expand echo `echo '*'`, so we don't\
  556. * use this piece of code anymore.
  557. */
  558. p++;
  559. while (*p && *p != '`')
  560. if (*p++ == '\\') {
  561. if (*p) /* Quoted chars */
  562. p++;
  563. else
  564. break;
  565. }
  566. if (!*p) /* The matching ` */
  567. break;
  568. #endif
  569. }
  570. else if (*p == '{')
  571. gflag |= G_CSH;
  572. else if (isglob(*p))
  573. gflag |= G_GLOB;
  574. else if (symlinks == SYM_EXPAND &&
  575. p[1] && ISDOTDOT(p) && (p == *(t-1) || *(p-1) == '/') )
  576. gflag |= G_CSH;
  577. p++;
  578. }
  579. }
  580. return gflag;
  581. }
  582. /*
  583. * Command substitute cp. If literal, then this is a substitution from a
  584. * << redirection, and so we should not crunch blanks and tabs, separating
  585. * words only at newlines.
  586. */
  587. Char **
  588. dobackp(Char *cp, int literal)
  589. {
  590. struct Strbuf word = Strbuf_INIT;
  591. struct blk_buf bb = BLK_BUF_INIT;
  592. Char *lp, *rp, *ep;
  593. cleanup_push(&bb, bb_cleanup);
  594. cleanup_push(&word, Strbuf_cleanup);
  595. for (;;) {
  596. for (lp = cp; *lp != '\0' && *lp != '`'; lp++)
  597. ;
  598. Strbuf_appendn(&word, cp, lp - cp);
  599. if (*lp == 0)
  600. break;
  601. lp++;
  602. for (rp = lp; *rp && *rp != '`'; rp++)
  603. if (*rp == '\\') {
  604. rp++;
  605. if (!*rp)
  606. goto oops;
  607. }
  608. if (!*rp) {
  609. oops:
  610. cleanup_until(&bb);
  611. stderror(ERR_UNMATCHED, '`');
  612. }
  613. ep = Strnsave(lp, rp - lp);
  614. cleanup_push(ep, xfree);
  615. backeval(&bb, &word, ep, literal);
  616. cleanup_until(ep);
  617. cp = rp + 1;
  618. }
  619. if (word.len != 0)
  620. pword(&bb, &word);
  621. cleanup_ignore(&bb);
  622. cleanup_until(&bb);
  623. return bb_finish(&bb);
  624. }
  625. static void
  626. backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal)
  627. {
  628. ssize_t icnt;
  629. Char c, *ip;
  630. struct command faket;
  631. int hadnl;
  632. int pvec[2], quoted;
  633. Char *fakecom[2], ibuf[BUFSIZE];
  634. char tibuf[BUFSIZE];
  635. hadnl = 0;
  636. icnt = 0;
  637. quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
  638. faket.t_dtyp = NODE_COMMAND;
  639. faket.t_dflg = F_BACKQ;
  640. faket.t_dlef = 0;
  641. faket.t_drit = 0;
  642. faket.t_dspr = 0;
  643. faket.t_dcom = fakecom;
  644. fakecom[0] = STRfakecom1;
  645. fakecom[1] = 0;
  646. /*
  647. * We do the psave job to temporarily change the current job so that the
  648. * following fork is considered a separate job. This is so that when
  649. * backquotes are used in a builtin function that calls glob the "current
  650. * job" is not corrupted. We only need one level of pushed jobs as long as
  651. * we are sure to fork here.
  652. */
  653. psavejob();
  654. cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */
  655. /*
  656. * It would be nicer if we could integrate this redirection more with the
  657. * routines in sh.sem.c by doing a fake execute on a builtin function that
  658. * was piped out.
  659. */
  660. mypipe(pvec);
  661. cleanup_push(&pvec[0], open_cleanup);
  662. cleanup_push(&pvec[1], open_cleanup);
  663. if (pfork(&faket, -1) == 0) {
  664. jmp_buf_t osetexit;
  665. struct command *t;
  666. size_t omark;
  667. xclose(pvec[0]);
  668. (void) dmove(pvec[1], 1);
  669. (void) dmove(SHDIAG, 2);
  670. initdesc();
  671. closem();
  672. arginp = cp;
  673. for (arginp = cp; *cp; cp++) {
  674. *cp &= TRIM;
  675. if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r'))
  676. *cp = ' ';
  677. }
  678. /*
  679. * In the child ``forget'' everything about current aliases or
  680. * eval vectors.
  681. */
  682. alvec = NULL;
  683. evalvec = NULL;
  684. alvecp = NULL;
  685. evalp = NULL;
  686. omark = cleanup_push_mark();
  687. getexit(osetexit);
  688. for (;;) {
  689. (void) setexit();
  690. justpr = 0;
  691. if (haderr) {
  692. /* unwind */
  693. doneinp = 0;
  694. cleanup_pop_mark(omark);
  695. resexit(osetexit);
  696. reset();
  697. }
  698. if (seterr) {
  699. xfree(seterr);
  700. seterr = NULL;
  701. }
  702. (void) lex(&paraml);
  703. cleanup_push(&paraml, lex_cleanup);
  704. if (seterr)
  705. stderror(ERR_OLD);
  706. alias(&paraml);
  707. t = syntax(paraml.next, &paraml, 0);
  708. if (t == NULL)
  709. return;
  710. cleanup_push(t, syntax_cleanup);
  711. /* The F_BACKQ flag must set so the job output is correct if
  712. * printexitvalue is set. If it's not set, the job output
  713. * will have "Exit N" appended where N is the exit status. */
  714. t->t_dflg = F_BACKQ|F_NOFORK;
  715. if (seterr)
  716. stderror(ERR_OLD);
  717. #ifdef SIGTSTP
  718. signal(SIGTSTP, SIG_IGN);
  719. #endif
  720. #ifdef SIGTTIN
  721. signal(SIGTTIN, SIG_IGN);
  722. #endif
  723. #ifdef SIGTTOU
  724. signal(SIGTTOU, SIG_IGN);
  725. #endif
  726. execute(t, -1, NULL, NULL, TRUE);
  727. cleanup_until(&paraml);
  728. }
  729. }
  730. cleanup_until(&pvec[1]);
  731. c = 0;
  732. ip = NULL;
  733. do {
  734. ssize_t cnt = 0;
  735. char *tmp;
  736. tmp = tibuf;
  737. for (;;) {
  738. while (icnt == 0) {
  739. int i, eof;
  740. ip = ibuf;
  741. icnt = xread(pvec[0], tmp, tibuf + BUFSIZE - tmp);
  742. eof = 0;
  743. if (icnt <= 0) {
  744. if (tmp == tibuf)
  745. goto eof;
  746. icnt = 0;
  747. eof = 1;
  748. }
  749. icnt += tmp - tibuf;
  750. i = 0;
  751. tmp = tibuf;
  752. while (tmp < tibuf + icnt) {
  753. int len;
  754. len = normal_mbtowc(&ip[i], tmp, tibuf + icnt - tmp);
  755. if (len == -1) {
  756. reset_mbtowc();
  757. if (!eof && (size_t)(tibuf + icnt - tmp) < MB_CUR_MAX) {
  758. break; /* Maybe a partial character */
  759. }
  760. ip[i] = (unsigned char) *tmp | INVALID_BYTE; /* Error */
  761. }
  762. if (len <= 0)
  763. len = 1;
  764. i++;
  765. tmp += len;
  766. }
  767. if (tmp != tibuf)
  768. memmove (tibuf, tmp, tibuf + icnt - tmp);
  769. tmp = tibuf + (tibuf + icnt - tmp);
  770. icnt = i;
  771. }
  772. if (hadnl)
  773. break;
  774. --icnt;
  775. c = (*ip++ & TRIM);
  776. if (c == 0)
  777. break;
  778. #if defined(WINNT_NATIVE) || defined(__CYGWIN__)
  779. if (c == '\r')
  780. c = ' ';
  781. #endif /* WINNT_NATIVE || __CYGWIN__ */
  782. if (c == '\n') {
  783. /*
  784. * Continue around the loop one more time, so that we can eat
  785. * the last newline without terminating this word.
  786. */
  787. hadnl = 1;
  788. continue;
  789. }
  790. if (!quoted && (c == ' ' || c == '\t'))
  791. break;
  792. cnt++;
  793. Strbuf_append1(word, c | quoted);
  794. }
  795. /*
  796. * Unless at end-of-file, we will form a new word here if there were
  797. * characters in the word, or in any case when we take text literally.
  798. * If we didn't make empty words here when literal was set then we
  799. * would lose blank lines.
  800. */
  801. if (c != 0 && (cnt || literal))
  802. pword(bb, word);
  803. hadnl = 0;
  804. } while (c > 0);
  805. eof:
  806. cleanup_until(&pvec[0]);
  807. pwait();
  808. cleanup_until(&faket); /* psavejob_cleanup(); */
  809. }
  810. static void
  811. pword(struct blk_buf *bb, struct Strbuf *word)
  812. {
  813. Char *s;
  814. s = Strbuf_finish(word);
  815. bb_append(bb, s);
  816. *word = Strbuf_init;
  817. }
  818. int
  819. Gmatch(const Char *string, const Char *pattern)
  820. {
  821. return Gnmatch(string, pattern, NULL);
  822. }
  823. int
  824. Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
  825. {
  826. Char ***fblk, **p;
  827. const Char *tstring = string;
  828. int gpol = 1, gres = 0;
  829. if (*pattern == '^') {
  830. gpol = 0;
  831. pattern++;
  832. }
  833. fblk = xmalloc(sizeof(Char ***));
  834. *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
  835. (*fblk)[0] = Strsave(pattern);
  836. (*fblk)[1] = NULL;
  837. cleanup_push(fblk, blk_indirect_cleanup);
  838. expbrace(fblk, NULL, GLOBSPACE);
  839. if (endstr == NULL)
  840. /* Exact matches only */
  841. for (p = *fblk; *p; p++)
  842. gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
  843. else {
  844. const Char *end;
  845. /* partial matches */
  846. end = Strend(string);
  847. for (p = *fblk; *p; p++)
  848. if (t_pmatch(string, *p, &tstring, 1) != 0) {
  849. gres |= 1;
  850. if (end > tstring)
  851. end = tstring;
  852. }
  853. *endstr = end;
  854. }
  855. cleanup_until(fblk);
  856. return(gres == gpol);
  857. }
  858. /* t_pmatch():
  859. * Return 2 on exact match,
  860. * Return 1 on substring match.
  861. * Return 0 on no match.
  862. * *estr will point to the end of the longest exact or substring match.
  863. */
  864. int
  865. t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs)
  866. {
  867. Char stringc, patternc, rangec;
  868. int match, negate_range;
  869. const Char *pestr, *nstring;
  870. for (nstring = string;; string = nstring) {
  871. stringc = *nstring++ & TRIM;
  872. patternc = *pattern++ & TRIM;
  873. switch (patternc) {
  874. case '\0':
  875. *estr = string;
  876. return (stringc == '\0' ? 2 : 1);
  877. case '?':
  878. if (stringc == 0)
  879. return (0);
  880. break;
  881. case '*':
  882. if (!*pattern) {
  883. *estr = Strend(string);
  884. return (2);
  885. }
  886. pestr = NULL;
  887. for (;;) {
  888. switch(t_pmatch(string, pattern, estr, cs)) {
  889. case 0:
  890. break;
  891. case 1:
  892. pestr = *estr;/*FIXME: does not guarantee longest match */
  893. break;
  894. case 2:
  895. return 2;
  896. default:
  897. abort(); /* Cannot happen */
  898. }
  899. stringc = *string++ & TRIM;
  900. if (!stringc)
  901. break;
  902. }
  903. if (pestr) {
  904. *estr = pestr;
  905. return 1;
  906. }
  907. else
  908. return 0;
  909. case '[':
  910. match = 0;
  911. if ((negate_range = (*pattern == '^')) != 0)
  912. pattern++;
  913. while ((rangec = *pattern++ & TRIM) != '\0') {
  914. if (rangec == ']')
  915. break;
  916. if (match)
  917. continue;
  918. if (*pattern == '-' && pattern[1] != ']') {
  919. Char rangec2;
  920. pattern++;
  921. rangec2 = *pattern++ & TRIM;
  922. match = (globcharcoll(stringc, rangec2, 0) <= 0 &&
  923. globcharcoll(rangec, stringc, 0) <= 0);
  924. }
  925. else
  926. match = (stringc == rangec);
  927. }
  928. if (rangec == '\0')
  929. stderror(ERR_NAME | ERR_MISSING, ']');
  930. if ((!match) && (stringc == '\0'))
  931. return (0);
  932. if (match == negate_range)
  933. return (0);
  934. break;
  935. default:
  936. if (cs ? patternc != stringc
  937. : Tolower(patternc) != Tolower(stringc))
  938. return (0);
  939. break;
  940. }
  941. }
  942. }