source: asp3_tinet_ecnl_rx/trunk/musl-1.1.18/src/misc/wordexp.c@ 337

Last change on this file since 337 was 337, checked in by coas-nagasima, 6 years ago

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 3.2 KB
Line 
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
14static 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
26static char *getword(FILE *f)
27{
28 char *s = 0;
29 return getdelim(&s, (size_t [1]){0}, 0, f) < 0 ? 0 : s;
30}
31
32static 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
168nospace:
169 if (!(flags & WRDE_APPEND)) {
170 we->we_wordc = 0;
171 we->we_wordv = 0;
172 }
173 return WRDE_NOSPACE;
174}
175
176int 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
185void 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}
Note: See TracBrowser for help on using the repository browser.