tunix.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tunix.c (5469B) | |
--- | |
1 #define NOPLAN9DEFINES | |
2 #include "mk.h" | |
3 #include <sys/wait.h> | |
4 #include <signal.h> | |
5 #include <sys/stat.h> | |
6 #include <sys/time.h> | |
7 | |
8 char *shell = "/bin/sh"; | |
9 char *shellname = "sh"; | |
10 | |
11 extern char **environ; | |
12 | |
13 static void | |
14 mkperror(char *s) | |
15 { | |
16 fprint(2, "%s: %r\n", s); | |
17 } | |
18 | |
19 void | |
20 readenv(void) | |
21 { | |
22 char **p, *s; | |
23 Word *w; | |
24 | |
25 for(p = environ; *p; p++){ | |
26 /* rsc 5/5/2004 -- This misparses fn#cd={whatever} | |
27 s = shname(*p); | |
28 if(*s == '=') { | |
29 *s = 0; | |
30 w = newword(s+1); | |
31 } else | |
32 w = newword(""); | |
33 */ | |
34 s = strchr(*p, '='); | |
35 if(s){ | |
36 *s = 0; | |
37 w = newword(s+1); | |
38 } else | |
39 w = newword(""); | |
40 if (symlook(*p, S_INTERNAL, 0)) | |
41 continue; | |
42 s = strdup(*p); | |
43 setvar(s, (void *)w); | |
44 symlook(s, S_EXPORTED, (void*)"")->u.ptr = ""; | |
45 } | |
46 } | |
47 | |
48 /* | |
49 * done on child side of fork, so parent's env is not affected | |
50 * and we don't care about freeing memory because we're going | |
51 * to exec immediately after this. | |
52 */ | |
53 void | |
54 exportenv(Envy *e, Shell *sh) | |
55 { | |
56 int w, n; | |
57 char **p; | |
58 Envy *e1; | |
59 static char buf[16384]; | |
60 | |
61 n = 0; | |
62 for(e1 = e; e1->name; e1++) | |
63 n++; | |
64 p = Malloc((n+1)*sizeof(char*)); | |
65 w = 0; | |
66 for(; e->name; e++) { | |
67 if(sh == &rcshell && (e->values == 0 || e->values->s == … | |
68 continue; /* do not write empty string for empty… | |
69 if(e->values) | |
70 snprint(buf, sizeof buf, "%s=%s", e->name, wtos… | |
71 else | |
72 snprint(buf, sizeof buf, "%s=", e->name); | |
73 p[w++] = strdup(buf); | |
74 } | |
75 p[w] = 0; | |
76 environ = p; | |
77 } | |
78 | |
79 int | |
80 waitfor(char *msg) | |
81 { | |
82 int status; | |
83 int pid; | |
84 | |
85 *msg = 0; | |
86 pid = wait(&status); | |
87 if(pid > 0) { | |
88 if(status&0x7f) { | |
89 if(status&0x80) | |
90 snprint(msg, ERRMAX, "signal %d, core du… | |
91 else | |
92 snprint(msg, ERRMAX, "signal %d", status… | |
93 } else if(status&0xff00) | |
94 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xf… | |
95 } | |
96 return pid; | |
97 } | |
98 | |
99 void | |
100 expunge(int pid, char *msg) | |
101 { | |
102 if(strcmp(msg, "interrupt")) | |
103 kill(pid, SIGINT); | |
104 else | |
105 kill(pid, SIGHUP); | |
106 } | |
107 | |
108 int mypid; | |
109 | |
110 int | |
111 shargv(Word *cmd, int extra, char ***pargv) | |
112 { | |
113 char **argv; | |
114 int i, n; | |
115 Word *w; | |
116 | |
117 n = 0; | |
118 for(w=cmd; w; w=w->next) | |
119 n++; | |
120 | |
121 argv = Malloc((n+extra+1)*sizeof(argv[0])); | |
122 i = 0; | |
123 for(w=cmd; w; w=w->next) | |
124 argv[i++] = w->s; | |
125 argv[n] = 0; | |
126 *pargv = argv; | |
127 return n; | |
128 } | |
129 | |
130 int | |
131 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *s… | |
132 { | |
133 char *p, **argv; | |
134 int tot, n, pid, in[2], out[2]; | |
135 | |
136 if(buf && pipe(out) < 0){ | |
137 mkperror("pipe"); | |
138 Exit(); | |
139 } | |
140 pid = fork(); | |
141 mypid = getpid(); | |
142 if(pid < 0){ | |
143 mkperror("mk fork"); | |
144 Exit(); | |
145 } | |
146 if(pid == 0){ | |
147 if(buf) | |
148 close(out[0]); | |
149 if(pipe(in) < 0){ | |
150 mkperror("pipe"); | |
151 Exit(); | |
152 } | |
153 pid = fork(); | |
154 if(pid < 0){ | |
155 mkperror("mk fork"); | |
156 Exit(); | |
157 } | |
158 if(pid != 0){ | |
159 dup2(in[0], 0); | |
160 if(buf){ | |
161 dup2(out[1], 1); | |
162 close(out[1]); | |
163 } | |
164 close(in[0]); | |
165 close(in[1]); | |
166 if (e) | |
167 exportenv(e, sh); | |
168 n = shargv(shellcmd, 1, &argv); | |
169 argv[n++] = args; | |
170 argv[n] = 0; | |
171 execvp(argv[0], argv); | |
172 mkperror(shell); | |
173 _exit(1); | |
174 } | |
175 close(out[1]); | |
176 close(in[0]); | |
177 if(DEBUG(D_EXEC)) | |
178 fprint(1, "starting: %s\n", cmd); | |
179 p = cmd+strlen(cmd); | |
180 while(cmd < p){ | |
181 n = write(in[1], cmd, p-cmd); | |
182 if(n < 0) | |
183 break; | |
184 cmd += n; | |
185 } | |
186 close(in[1]); | |
187 _exit(0); | |
188 } | |
189 if(buf){ | |
190 close(out[1]); | |
191 tot = 0; | |
192 for(;;){ | |
193 if (buf->current >= buf->end) | |
194 growbuf(buf); | |
195 n = read(out[0], buf->current, buf->end-buf->cur… | |
196 if(n <= 0) | |
197 break; | |
198 buf->current += n; | |
199 tot += n; | |
200 } | |
201 if (tot && buf->current[-1] == '\n') | |
202 buf->current--; | |
203 close(out[0]); | |
204 } | |
205 return pid; | |
206 } | |
207 | |
208 int | |
209 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd) | |
210 { | |
211 int pid, pfd[2]; | |
212 int n; | |
213 char **argv; | |
214 | |
215 if(DEBUG(D_EXEC)) | |
216 fprint(1, "pipecmd='%s'\n", cmd);/**/ | |
217 | |
218 if(fd && pipe(pfd) < 0){ | |
219 mkperror("pipe"); | |
220 Exit(); | |
221 } | |
222 pid = fork(); | |
223 if(pid < 0){ | |
224 mkperror("mk fork"); | |
225 Exit(); | |
226 } | |
227 if(pid == 0){ | |
228 if(fd){ | |
229 close(pfd[0]); | |
230 dup2(pfd[1], 1); | |
231 close(pfd[1]); | |
232 } | |
233 if(e) | |
234 exportenv(e, sh); | |
235 n = shargv(shellcmd, 2, &argv); | |
236 argv[n++] = "-c"; | |
237 argv[n++] = cmd; | |
238 argv[n] = 0; | |
239 execvp(argv[0], argv); | |
240 mkperror(shell); | |
241 _exit(1); | |
242 } | |
243 if(fd){ | |
244 close(pfd[1]); | |
245 *fd = pfd[0]; | |
246 } | |
247 return pid; | |
248 } | |
249 | |
250 void | |
251 Exit(void) | |
252 { | |
253 while(wait(0) >= 0) | |
254 ; | |
255 exits("error"); | |
256 } | |
257 | |
258 static struct | |
259 { | |
260 int sig; | |
261 char *msg; | |
262 } sigmsgs[] = | |
263 { | |
264 SIGALRM, "alarm", | |
265 SIGFPE, "sys: fp: fptrap", | |
266 SIGPIPE, "sys: write on closed pipe", | |
267 SIGILL, "sys: trap: illegal instruction", | |
268 /* SIGSEGV, "sys: segmentation violation", */ | |
269 0, 0 | |
270 }; | |
271 | |
272 static void | |
273 notifyf(int sig) | |
274 { | |
275 int i; | |
276 | |
277 for(i = 0; sigmsgs[i].msg; i++) | |
278 if(sigmsgs[i].sig == sig) | |
279 killchildren(sigmsgs[i].msg); | |
280 | |
281 /* should never happen */ | |
282 signal(sig, SIG_DFL); | |
283 kill(getpid(), sig); | |
284 } | |
285 | |
286 void | |
287 catchnotes(void) | |
288 { | |
289 int i; | |
290 | |
291 for(i = 0; sigmsgs[i].msg; i++) | |
292 signal(sigmsgs[i].sig, notifyf); | |
293 } | |
294 | |
295 char* | |
296 maketmp(int *pfd) | |
297 { | |
298 static char temp[] = "/tmp/mkargXXXXXX"; | |
299 static char buf[100]; | |
300 int fd; | |
301 | |
302 strcpy(buf, temp); | |
303 fd = mkstemp(buf); | |
304 if(fd < 0) | |
305 return 0; | |
306 *pfd = fd; | |
307 return buf; | |
308 } | |
309 | |
310 int | |
311 chgtime(char *name) | |
312 { | |
313 if(access(name, 0) >= 0) | |
314 return utimes(name, 0); | |
315 return close(creat(name, 0666)); | |
316 } | |
317 | |
318 void | |
319 rcopy(char **to, Resub *match, int n) | |
320 { | |
321 int c; | |
322 char *p; | |
323 | |
324 *to = match->s.sp; /* stem0 matches complete targ… | |
325 for(to++, match++; --n > 0; to++, match++){ | |
326 if(match->s.sp && match->e.ep){ | |
327 p = match->e.ep; | |
328 c = *p; | |
329 *p = 0; | |
330 *to = strdup(match->s.sp); | |
331 *p = c; | |
332 } | |
333 else | |
334 *to = 0; | |
335 } | |
336 } | |
337 | |
338 unsigned long | |
339 mkmtime(char *name) | |
340 { | |
341 struct stat st; | |
342 | |
343 if(stat(name, &st) < 0) | |
344 return 0; | |
345 | |
346 return st.st_mtime; | |
347 } |