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