Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: fusl/src/misc/wordexp.c

Issue 1573973002: Add a "fork" of musl as //fusl. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « fusl/src/misc/uname.c ('k') | fusl/src/mman/madvise.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #include <wordexp.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <limits.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <sys/wait.h>
9 #include <signal.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include "pthread_impl.h"
13
14 static void reap(pid_t pid)
15 {
16 int status;
17 for (;;) {
18 if (waitpid(pid, &status, 0) < 0) {
19 if (errno != EINTR) return;
20 } else {
21 if (WIFEXITED(status)) return;
22 }
23 }
24 }
25
26 static char *getword(FILE *f)
27 {
28 char *s = 0;
29 return getdelim(&s, (size_t [1]){0}, 0, f) < 0 ? 0 : s;
30 }
31
32 static int do_wordexp(const char *s, wordexp_t *we, int flags)
33 {
34 size_t i, l;
35 int sq=0, dq=0;
36 size_t np=0;
37 char *w, **tmp;
38 char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
39 int err = 0;
40 FILE *f;
41 size_t wc = 0;
42 char **wv = 0;
43 int p[2];
44 pid_t pid;
45 sigset_t set;
46
47 if (flags & WRDE_REUSE) wordfree(we);
48
49 if (flags & WRDE_NOCMD) for (i=0; s[i]; i++) switch (s[i]) {
50 case '\\':
51 if (!sq) i++;
52 break;
53 case '\'':
54 if (!dq) sq^=1;
55 break;
56 case '"':
57 if (!sq) dq^=1;
58 break;
59 case '(':
60 if (np) {
61 np++;
62 break;
63 }
64 case ')':
65 if (np) {
66 np--;
67 break;
68 }
69 case '\n':
70 case '|':
71 case '&':
72 case ';':
73 case '<':
74 case '>':
75 case '{':
76 case '}':
77 if (!(sq|dq|np)) return WRDE_BADCHAR;
78 break;
79 case '$':
80 if (sq) break;
81 if (s[i+1]=='(' && s[i+2]=='(') {
82 i += 2;
83 np += 2;
84 break;
85 } else if (s[i+1] != '(') break;
86 case '`':
87 if (sq) break;
88 return WRDE_CMDSUB;
89 }
90
91 if (flags & WRDE_APPEND) {
92 wc = we->we_wordc;
93 wv = we->we_wordv;
94 }
95
96 i = wc;
97 if (flags & WRDE_DOOFFS) {
98 if (we->we_offs > SIZE_MAX/sizeof(void *)/4)
99 goto nospace;
100 i += we->we_offs;
101 } else {
102 we->we_offs = 0;
103 }
104
105 if (pipe2(p, O_CLOEXEC) < 0) goto nospace;
106 __block_all_sigs(&set);
107 pid = fork();
108 __restore_sigs(&set);
109 if (pid < 0) {
110 close(p[0]);
111 close(p[1]);
112 goto nospace;
113 }
114 if (!pid) {
115 if (p[1] == 1) fcntl(1, F_SETFD, 0);
116 else dup2(p[1], 1);
117 execl("/bin/sh", "sh", "-c",
118 "eval \"printf %s\\\\\\\\0 x $1 $2\"",
119 "sh", s, redir, (char *)0);
120 _exit(1);
121 }
122 close(p[1]);
123
124 f = fdopen(p[0], "r");
125 if (!f) {
126 close(p[0]);
127 kill(pid, SIGKILL);
128 reap(pid);
129 goto nospace;
130 }
131
132 l = wv ? i+1 : 0;
133
134 free(getword(f));
135 if (feof(f)) {
136 fclose(f);
137 reap(pid);
138 return WRDE_SYNTAX;
139 }
140
141 while ((w = getword(f))) {
142 if (i+1 >= l) {
143 l += l/2+10;
144 tmp = realloc(wv, l*sizeof(char *));
145 if (!tmp) break;
146 wv = tmp;
147 }
148 wv[i++] = w;
149 wv[i] = 0;
150 }
151 if (!feof(f)) err = WRDE_NOSPACE;
152
153 fclose(f);
154 reap(pid);
155
156 if (!wv) wv = calloc(i+1, sizeof *wv);
157
158 we->we_wordv = wv;
159 we->we_wordc = i;
160
161 if (flags & WRDE_DOOFFS) {
162 if (wv) for (i=we->we_offs; i; i--)
163 we->we_wordv[i-1] = 0;
164 we->we_wordc -= we->we_offs;
165 }
166 return err;
167
168 nospace:
169 if (!(flags & WRDE_APPEND)) {
170 we->we_wordc = 0;
171 we->we_wordv = 0;
172 }
173 return WRDE_NOSPACE;
174 }
175
176 int wordexp(const char *restrict s, wordexp_t *restrict we, int flags)
177 {
178 int r, cs;
179 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
180 r = do_wordexp(s, we, flags);
181 pthread_setcancelstate(cs, 0);
182 return r;
183 }
184
185 void wordfree(wordexp_t *we)
186 {
187 size_t i;
188 if (!we->we_wordv) return;
189 for (i=0; i<we->we_wordc; i++) free(we->we_wordv[we->we_offs+i]);
190 free(we->we_wordv);
191 we->we_wordv = 0;
192 we->we_wordc = 0;
193 }
OLDNEW
« no previous file with comments | « fusl/src/misc/uname.c ('k') | fusl/src/mman/madvise.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698