static void out_of_memory (void) { static const char msg[] = "Out of memory\n"; TCSH_IGNORE(write(didfds ? 2 : SHDIAG, msg, strlen(msg))); _exit(1); }
/* * The main glob() routine: compiles the pattern (optionally processing * quotes), calls glob1() to do the real pattern matching, and finally * sorts the list (unless unsorted operation is requested). Returns 0 * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */ int glob(const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob) { int err, oldpathc; Char *bufnext, m_not; const unsigned char *patnext; int c, not; Char *qpatnext, *patbuf; int no_match; patnext = (const unsigned char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; oldpathc = pglob->gl_pathc; pglob->gl_matchc = 0; if (pglob->gl_flags & GLOB_ALTNOT) { not = ALTNOT; m_not = M_ALTNOT; } else { not = NOT; m_not = M_NOT; } patbuf = xmalloc((strlen(pattern) + 1) * sizeof(*patbuf)); bufnext = patbuf; no_match = *patnext == not; if (no_match) patnext++; if (flags & GLOB_QUOTE) { /* Protect the quoted characters */ while ((c = *patnext++) != EOS) { #ifdef WIDE_STRINGS int len; len = mblen((const char *)(patnext - 1), MB_LEN_MAX); if (len == -1) TCSH_IGNORE(mblen(NULL, 0)); else if (len > 1) { *bufnext++ = (Char) c; while (--len != 0) *bufnext++ = (Char) (*patnext++ | M_PROTECT); } else #endif /* WIDE_STRINGS */ if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = (Char) (c | M_PROTECT); } else *bufnext++ = (Char) c; } } else while ((c = *patnext++) != EOS) *bufnext++ = (Char) c; *bufnext = EOS; bufnext = patbuf; qpatnext = patbuf; while ((c = *qpatnext++) != EOS) { switch (c) { case LBRACKET: c = *qpatnext; if (c == not) ++qpatnext; if (*qpatnext == EOS || Strchr(qpatnext + 1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == not) --qpatnext; break; } pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_SET; if (c == not) *bufnext++ = m_not; c = *qpatnext++; do { *bufnext++ = LCHAR(c); if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = LCHAR(c); qpatnext += 2; } } while ((c = *qpatnext++) != RBRACKET); *bufnext++ = M_END; break; case QUESTION: pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_ONE; break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; /* collapse adjacent stars to one [or three if globstar], * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL || ((flags & GLOB_STAR) != 0 && (bufnext - 1 == patbuf || bufnext[-2] != M_ALL || bufnext - 2 == patbuf || bufnext[-3] != M_ALL))) *bufnext++ = M_ALL; break; default: *bufnext++ = LCHAR(c); break; } } *bufnext = EOS; #ifdef DEBUG qprintf(patbuf); #endif if ((err = glob1(patbuf, pglob, no_match)) != 0) { xfree(patbuf); return (err); } /* * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ if (pglob->gl_pathc == oldpathc && ((flags & GLOB_NOCHECK) || ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) { if (!(flags & GLOB_QUOTE)) globextend(pattern, pglob); else { char *copy, *dest; const char *src; /* copy pattern, interpreting quotes */ copy = xmalloc(strlen(pattern) + 1); dest = copy; src = pattern; while (*src != EOS) { /* Don't interpret quotes. The spec does not say we should do */ if (*src == QUOTE) { if (*++src == EOS) --src; } *dest++ = *src++; } *dest = EOS; globextend(copy, pglob); xfree(copy); } xfree(patbuf); return 0; } else if (!(flags & GLOB_NOSORT) && (pglob->gl_pathc != oldpathc)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare); xfree(patbuf); return (0); }
/* * Perform io redirection. * We may or maynot be forked here. */ static void doio(struct command *t, int *pipein, int *pipeout) { int fd; Char *cp; unsigned long flags = t->t_dflg; if (didfds || (flags & F_REPEAT)) return; if ((flags & F_READ) == 0) {/* F_READ already done */ if (t->t_dlef) { char *tmp; /* * so < /dev/std{in,out,err} work */ (void) dcopy(SHIN, 0); (void) dcopy(SHOUT, 1); (void) dcopy(SHDIAG, 2); cp = splicepipe(t, t->t_dlef); tmp = strsave(short2str(cp)); xfree(cp); cleanup_push(tmp, xfree); if ((fd = xopen(tmp, O_RDONLY|O_LARGEFILE)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); cleanup_until(tmp); /* allow input files larger than 2Gb */ #ifndef WINNT_NATIVE (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); #endif /*!WINNT_NATIVE*/ (void) dmove(fd, 0); } else if (flags & F_PIPEIN) { xclose(0); TCSH_IGNORE(dup(pipein[0])); xclose(pipein[0]); xclose(pipein[1]); } else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { xclose(0); (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); } else { xclose(0); TCSH_IGNORE(dup(OLDSTD)); #if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) /* * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved * across dup()s, so we have to UNSET it here or else we get a * command with NO stdin, stdout, or stderr at all (a bad thing * indeed) */ (void) close_on_exec(0, 0); #endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } } if (t->t_drit) { char *tmp; cp = splicepipe(t, t->t_drit); tmp = strsave(short2str(cp)); xfree(cp); cleanup_push(tmp, xfree); /* * so > /dev/std{out,err} work */ (void) dcopy(SHOUT, 1); (void) dcopy(SHDIAG, 2); if ((flags & F_APPEND) != 0) { #ifdef O_APPEND fd = xopen(tmp, O_WRONLY|O_APPEND|O_LARGEFILE); #else /* !O_APPEND */ fd = xopen(tmp, O_WRONLY|O_LARGEFILE); (void) lseek(fd, (off_t) 0, L_XTND); #endif /* O_APPEND */ } else fd = 0; if ((flags & F_APPEND) == 0 || fd == -1) { if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { if (flags & F_APPEND) stderror(ERR_SYSTEM, tmp, strerror(errno)); chkclob(tmp); } if ((fd = xcreat(tmp, 0666)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); /* allow input files larger than 2Gb */ #ifndef WINNT_NATIVE (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); #endif /*!WINNT_NATIVE*/ } cleanup_until(tmp); (void) dmove(fd, 1); is1atty = isatty(1); } else if (flags & F_PIPEOUT) { xclose(1); TCSH_IGNORE(dup(pipeout[1])); is1atty = 0; } else { xclose(1); TCSH_IGNORE(dup(SHOUT)); is1atty = isoutatty; # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) (void) close_on_exec(1, 0); # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } xclose(2); if (flags & F_STDERR) { TCSH_IGNORE(dup(1)); is2atty = is1atty; } else { TCSH_IGNORE(dup(SHDIAG)); is2atty = isdiagatty; # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) (void) close_on_exec(2, 0); # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } didfds = 1; }