Index: fusl/src/misc/wordexp.c |
diff --git a/fusl/src/misc/wordexp.c b/fusl/src/misc/wordexp.c |
index db39b5b8a3e3dee78bf6a54c1af3a1e23013c72b..87a1ba223058e4e97403279ec0d2b7d06e9abef8 100644 |
--- a/fusl/src/misc/wordexp.c |
+++ b/fusl/src/misc/wordexp.c |
@@ -11,183 +11,198 @@ |
#include <fcntl.h> |
#include "pthread_impl.h" |
-static void reap(pid_t pid) |
-{ |
- int status; |
- for (;;) { |
- if (waitpid(pid, &status, 0) < 0) { |
- if (errno != EINTR) return; |
- } else { |
- if (WIFEXITED(status)) return; |
- } |
- } |
+static void reap(pid_t pid) { |
+ int status; |
+ for (;;) { |
+ if (waitpid(pid, &status, 0) < 0) { |
+ if (errno != EINTR) |
+ return; |
+ } else { |
+ if (WIFEXITED(status)) |
+ return; |
+ } |
+ } |
} |
-static char *getword(FILE *f) |
-{ |
- char *s = 0; |
- return getdelim(&s, (size_t [1]){0}, 0, f) < 0 ? 0 : s; |
+static char* getword(FILE* f) { |
+ char* s = 0; |
+ return getdelim(&s, (size_t[1]){0}, 0, f) < 0 ? 0 : s; |
} |
-static int do_wordexp(const char *s, wordexp_t *we, int flags) |
-{ |
- size_t i, l; |
- int sq=0, dq=0; |
- size_t np=0; |
- char *w, **tmp; |
- char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null"; |
- int err = 0; |
- FILE *f; |
- size_t wc = 0; |
- char **wv = 0; |
- int p[2]; |
- pid_t pid; |
- sigset_t set; |
- |
- if (flags & WRDE_REUSE) wordfree(we); |
- |
- if (flags & WRDE_NOCMD) for (i=0; s[i]; i++) switch (s[i]) { |
- case '\\': |
- if (!sq) i++; |
- break; |
- case '\'': |
- if (!dq) sq^=1; |
- break; |
- case '"': |
- if (!sq) dq^=1; |
- break; |
- case '(': |
- if (np) { |
- np++; |
- break; |
- } |
- case ')': |
- if (np) { |
- np--; |
- break; |
- } |
- case '\n': |
- case '|': |
- case '&': |
- case ';': |
- case '<': |
- case '>': |
- case '{': |
- case '}': |
- if (!(sq|dq|np)) return WRDE_BADCHAR; |
- break; |
- case '$': |
- if (sq) break; |
- if (s[i+1]=='(' && s[i+2]=='(') { |
- i += 2; |
- np += 2; |
- break; |
- } else if (s[i+1] != '(') break; |
- case '`': |
- if (sq) break; |
- return WRDE_CMDSUB; |
- } |
- |
- if (flags & WRDE_APPEND) { |
- wc = we->we_wordc; |
- wv = we->we_wordv; |
- } |
- |
- i = wc; |
- if (flags & WRDE_DOOFFS) { |
- if (we->we_offs > SIZE_MAX/sizeof(void *)/4) |
- goto nospace; |
- i += we->we_offs; |
- } else { |
- we->we_offs = 0; |
- } |
- |
- if (pipe2(p, O_CLOEXEC) < 0) goto nospace; |
- __block_all_sigs(&set); |
- pid = fork(); |
- __restore_sigs(&set); |
- if (pid < 0) { |
- close(p[0]); |
- close(p[1]); |
- goto nospace; |
- } |
- if (!pid) { |
- if (p[1] == 1) fcntl(1, F_SETFD, 0); |
- else dup2(p[1], 1); |
- execl("/bin/sh", "sh", "-c", |
- "eval \"printf %s\\\\\\\\0 x $1 $2\"", |
- "sh", s, redir, (char *)0); |
- _exit(1); |
- } |
- close(p[1]); |
- |
- f = fdopen(p[0], "r"); |
- if (!f) { |
- close(p[0]); |
- kill(pid, SIGKILL); |
- reap(pid); |
- goto nospace; |
- } |
- |
- l = wv ? i+1 : 0; |
- |
- free(getword(f)); |
- if (feof(f)) { |
- fclose(f); |
- reap(pid); |
- return WRDE_SYNTAX; |
- } |
- |
- while ((w = getword(f))) { |
- if (i+1 >= l) { |
- l += l/2+10; |
- tmp = realloc(wv, l*sizeof(char *)); |
- if (!tmp) break; |
- wv = tmp; |
- } |
- wv[i++] = w; |
- wv[i] = 0; |
- } |
- if (!feof(f)) err = WRDE_NOSPACE; |
- |
- fclose(f); |
- reap(pid); |
- |
- if (!wv) wv = calloc(i+1, sizeof *wv); |
- |
- we->we_wordv = wv; |
- we->we_wordc = i; |
- |
- if (flags & WRDE_DOOFFS) { |
- if (wv) for (i=we->we_offs; i; i--) |
- we->we_wordv[i-1] = 0; |
- we->we_wordc -= we->we_offs; |
- } |
- return err; |
+static int do_wordexp(const char* s, wordexp_t* we, int flags) { |
+ size_t i, l; |
+ int sq = 0, dq = 0; |
+ size_t np = 0; |
+ char *w, **tmp; |
+ char* redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null"; |
+ int err = 0; |
+ FILE* f; |
+ size_t wc = 0; |
+ char** wv = 0; |
+ int p[2]; |
+ pid_t pid; |
+ sigset_t set; |
+ |
+ if (flags & WRDE_REUSE) |
+ wordfree(we); |
+ |
+ if (flags & WRDE_NOCMD) |
+ for (i = 0; s[i]; i++) |
+ switch (s[i]) { |
+ case '\\': |
+ if (!sq) |
+ i++; |
+ break; |
+ case '\'': |
+ if (!dq) |
+ sq ^= 1; |
+ break; |
+ case '"': |
+ if (!sq) |
+ dq ^= 1; |
+ break; |
+ case '(': |
+ if (np) { |
+ np++; |
+ break; |
+ } |
+ case ')': |
+ if (np) { |
+ np--; |
+ break; |
+ } |
+ case '\n': |
+ case '|': |
+ case '&': |
+ case ';': |
+ case '<': |
+ case '>': |
+ case '{': |
+ case '}': |
+ if (!(sq | dq | np)) |
+ return WRDE_BADCHAR; |
+ break; |
+ case '$': |
+ if (sq) |
+ break; |
+ if (s[i + 1] == '(' && s[i + 2] == '(') { |
+ i += 2; |
+ np += 2; |
+ break; |
+ } else if (s[i + 1] != '(') |
+ break; |
+ case '`': |
+ if (sq) |
+ break; |
+ return WRDE_CMDSUB; |
+ } |
+ |
+ if (flags & WRDE_APPEND) { |
+ wc = we->we_wordc; |
+ wv = we->we_wordv; |
+ } |
+ |
+ i = wc; |
+ if (flags & WRDE_DOOFFS) { |
+ if (we->we_offs > SIZE_MAX / sizeof(void*) / 4) |
+ goto nospace; |
+ i += we->we_offs; |
+ } else { |
+ we->we_offs = 0; |
+ } |
+ |
+ if (pipe2(p, O_CLOEXEC) < 0) |
+ goto nospace; |
+ __block_all_sigs(&set); |
+ pid = fork(); |
+ __restore_sigs(&set); |
+ if (pid < 0) { |
+ close(p[0]); |
+ close(p[1]); |
+ goto nospace; |
+ } |
+ if (!pid) { |
+ if (p[1] == 1) |
+ fcntl(1, F_SETFD, 0); |
+ else |
+ dup2(p[1], 1); |
+ execl("/bin/sh", "sh", "-c", "eval \"printf %s\\\\\\\\0 x $1 $2\"", "sh", s, |
+ redir, (char*)0); |
+ _exit(1); |
+ } |
+ close(p[1]); |
+ |
+ f = fdopen(p[0], "r"); |
+ if (!f) { |
+ close(p[0]); |
+ kill(pid, SIGKILL); |
+ reap(pid); |
+ goto nospace; |
+ } |
+ |
+ l = wv ? i + 1 : 0; |
+ |
+ free(getword(f)); |
+ if (feof(f)) { |
+ fclose(f); |
+ reap(pid); |
+ return WRDE_SYNTAX; |
+ } |
+ |
+ while ((w = getword(f))) { |
+ if (i + 1 >= l) { |
+ l += l / 2 + 10; |
+ tmp = realloc(wv, l * sizeof(char*)); |
+ if (!tmp) |
+ break; |
+ wv = tmp; |
+ } |
+ wv[i++] = w; |
+ wv[i] = 0; |
+ } |
+ if (!feof(f)) |
+ err = WRDE_NOSPACE; |
+ |
+ fclose(f); |
+ reap(pid); |
+ |
+ if (!wv) |
+ wv = calloc(i + 1, sizeof *wv); |
+ |
+ we->we_wordv = wv; |
+ we->we_wordc = i; |
+ |
+ if (flags & WRDE_DOOFFS) { |
+ if (wv) |
+ for (i = we->we_offs; i; i--) |
+ we->we_wordv[i - 1] = 0; |
+ we->we_wordc -= we->we_offs; |
+ } |
+ return err; |
nospace: |
- if (!(flags & WRDE_APPEND)) { |
- we->we_wordc = 0; |
- we->we_wordv = 0; |
- } |
- return WRDE_NOSPACE; |
+ if (!(flags & WRDE_APPEND)) { |
+ we->we_wordc = 0; |
+ we->we_wordv = 0; |
+ } |
+ return WRDE_NOSPACE; |
} |
-int wordexp(const char *restrict s, wordexp_t *restrict we, int flags) |
-{ |
- int r, cs; |
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
- r = do_wordexp(s, we, flags); |
- pthread_setcancelstate(cs, 0); |
- return r; |
+int wordexp(const char* restrict s, wordexp_t* restrict we, int flags) { |
+ int r, cs; |
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
+ r = do_wordexp(s, we, flags); |
+ pthread_setcancelstate(cs, 0); |
+ return r; |
} |
-void wordfree(wordexp_t *we) |
-{ |
- size_t i; |
- if (!we->we_wordv) return; |
- for (i=0; i<we->we_wordc; i++) free(we->we_wordv[we->we_offs+i]); |
- free(we->we_wordv); |
- we->we_wordv = 0; |
- we->we_wordc = 0; |
+void wordfree(wordexp_t* we) { |
+ size_t i; |
+ if (!we->we_wordv) |
+ return; |
+ for (i = 0; i < we->we_wordc; i++) |
+ free(we->we_wordv[we->we_offs + i]); |
+ free(we->we_wordv); |
+ we->we_wordv = 0; |
+ we->we_wordc = 0; |
} |