unix.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
unix.c (5290B) | |
--- | |
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 i; | |
57 char **p; | |
58 static char buf[16384]; | |
59 | |
60 p = 0; | |
61 for(i = 0; e->name; e++, i++) { | |
62 p = (char**) Realloc(p, (i+2)*sizeof(char*)); | |
63 if(e->values) | |
64 snprint(buf, sizeof buf, "%s=%s", e->name, wtos… | |
65 else | |
66 snprint(buf, sizeof buf, "%s=", e->name); | |
67 p[i] = strdup(buf); | |
68 } | |
69 p[i] = 0; | |
70 environ = p; | |
71 } | |
72 | |
73 int | |
74 waitfor(char *msg) | |
75 { | |
76 int status; | |
77 int pid; | |
78 | |
79 *msg = 0; | |
80 pid = wait(&status); | |
81 if(pid > 0) { | |
82 if(status&0x7f) { | |
83 if(status&0x80) | |
84 snprint(msg, ERRMAX, "signal %d, core du… | |
85 else | |
86 snprint(msg, ERRMAX, "signal %d", status… | |
87 } else if(status&0xff00) | |
88 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xf… | |
89 } | |
90 return pid; | |
91 } | |
92 | |
93 void | |
94 expunge(int pid, char *msg) | |
95 { | |
96 if(strcmp(msg, "interrupt")) | |
97 kill(pid, SIGINT); | |
98 else | |
99 kill(pid, SIGHUP); | |
100 } | |
101 | |
102 int mypid; | |
103 | |
104 int | |
105 shargv(Word *cmd, int extra, char ***pargv) | |
106 { | |
107 char **argv; | |
108 int i, n; | |
109 Word *w; | |
110 | |
111 n = 0; | |
112 for(w=cmd; w; w=w->next) | |
113 n++; | |
114 | |
115 argv = Malloc((n+extra+1)*sizeof(argv[0])); | |
116 i = 0; | |
117 for(w=cmd; w; w=w->next) | |
118 argv[i++] = w->s; | |
119 argv[n] = 0; | |
120 *pargv = argv; | |
121 return n; | |
122 } | |
123 | |
124 int | |
125 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *s… | |
126 { | |
127 char *p, **argv; | |
128 int tot, n, pid, in[2], out[2]; | |
129 | |
130 if(buf && pipe(out) < 0){ | |
131 mkperror("pipe"); | |
132 Exit(); | |
133 } | |
134 pid = fork(); | |
135 mypid = getpid(); | |
136 if(pid < 0){ | |
137 mkperror("mk fork"); | |
138 Exit(); | |
139 } | |
140 if(pid == 0){ | |
141 if(buf) | |
142 close(out[0]); | |
143 if(pipe(in) < 0){ | |
144 mkperror("pipe"); | |
145 Exit(); | |
146 } | |
147 pid = fork(); | |
148 if(pid < 0){ | |
149 mkperror("mk fork"); | |
150 Exit(); | |
151 } | |
152 if(pid != 0){ | |
153 dup2(in[0], 0); | |
154 if(buf){ | |
155 dup2(out[1], 1); | |
156 close(out[1]); | |
157 } | |
158 close(in[0]); | |
159 close(in[1]); | |
160 if (e) | |
161 exportenv(e, sh); | |
162 n = shargv(shellcmd, 1, &argv); | |
163 argv[n++] = args; | |
164 argv[n] = 0; | |
165 execvp(argv[0], argv); | |
166 mkperror(shell); | |
167 _exit(1); | |
168 } | |
169 close(out[1]); | |
170 close(in[0]); | |
171 if(DEBUG(D_EXEC)) | |
172 fprint(1, "starting: %s\n", cmd); | |
173 p = cmd+strlen(cmd); | |
174 while(cmd < p){ | |
175 n = write(in[1], cmd, p-cmd); | |
176 if(n < 0) | |
177 break; | |
178 cmd += n; | |
179 } | |
180 close(in[1]); | |
181 _exit(0); | |
182 } | |
183 if(buf){ | |
184 close(out[1]); | |
185 tot = 0; | |
186 for(;;){ | |
187 if (buf->current >= buf->end) | |
188 growbuf(buf); | |
189 n = read(out[0], buf->current, buf->end-buf->cur… | |
190 if(n <= 0) | |
191 break; | |
192 buf->current += n; | |
193 tot += n; | |
194 } | |
195 if (tot && buf->current[-1] == '\n') | |
196 buf->current--; | |
197 close(out[0]); | |
198 } | |
199 return pid; | |
200 } | |
201 | |
202 int | |
203 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd) | |
204 { | |
205 int pid, pfd[2]; | |
206 int n; | |
207 char **argv; | |
208 | |
209 if(DEBUG(D_EXEC)) | |
210 fprint(1, "pipecmd='%s'\n", cmd);/**/ | |
211 | |
212 if(fd && pipe(pfd) < 0){ | |
213 mkperror("pipe"); | |
214 Exit(); | |
215 } | |
216 pid = fork(); | |
217 if(pid < 0){ | |
218 mkperror("mk fork"); | |
219 Exit(); | |
220 } | |
221 if(pid == 0){ | |
222 if(fd){ | |
223 close(pfd[0]); | |
224 dup2(pfd[1], 1); | |
225 close(pfd[1]); | |
226 } | |
227 if(e) | |
228 exportenv(e, sh); | |
229 n = shargv(shellcmd, 2, &argv); | |
230 argv[n++] = "-c"; | |
231 argv[n++] = cmd; | |
232 argv[n] = 0; | |
233 execvp(argv[0], argv); | |
234 mkperror(shell); | |
235 _exit(1); | |
236 } | |
237 if(fd){ | |
238 close(pfd[1]); | |
239 *fd = pfd[0]; | |
240 } | |
241 return pid; | |
242 } | |
243 | |
244 void | |
245 Exit(void) | |
246 { | |
247 while(wait(0) >= 0) | |
248 ; | |
249 exits("error"); | |
250 } | |
251 | |
252 static struct | |
253 { | |
254 int sig; | |
255 char *msg; | |
256 } sigmsgs[] = | |
257 { | |
258 SIGALRM, "alarm", | |
259 SIGFPE, "sys: fp: fptrap", | |
260 SIGPIPE, "sys: write on closed pipe", | |
261 SIGILL, "sys: trap: illegal instruction", | |
262 /* SIGSEGV, "sys: segmentation violation", */ | |
263 0, 0 | |
264 }; | |
265 | |
266 static void | |
267 notifyf(int sig) | |
268 { | |
269 int i; | |
270 | |
271 for(i = 0; sigmsgs[i].msg; i++) | |
272 if(sigmsgs[i].sig == sig) | |
273 killchildren(sigmsgs[i].msg); | |
274 | |
275 /* should never happen */ | |
276 signal(sig, SIG_DFL); | |
277 kill(getpid(), sig); | |
278 } | |
279 | |
280 void | |
281 catchnotes(void) | |
282 { | |
283 int i; | |
284 | |
285 for(i = 0; sigmsgs[i].msg; i++) | |
286 signal(sigmsgs[i].sig, notifyf); | |
287 } | |
288 | |
289 char* | |
290 maketmp(int *pfd) | |
291 { | |
292 static char temp[] = "/tmp/mkargXXXXXX"; | |
293 static char buf[100]; | |
294 int fd; | |
295 | |
296 strcpy(buf, temp); | |
297 fd = mkstemp(buf); | |
298 if(fd < 0) | |
299 return 0; | |
300 *pfd = fd; | |
301 return buf; | |
302 } | |
303 | |
304 int | |
305 chgtime(char *name) | |
306 { | |
307 if(access(name, 0) >= 0) | |
308 return utimes(name, 0); | |
309 return close(creat(name, 0666)); | |
310 } | |
311 | |
312 void | |
313 rcopy(char **to, Resub *match, int n) | |
314 { | |
315 int c; | |
316 char *p; | |
317 | |
318 *to = match->s.sp; /* stem0 matches complete targ… | |
319 for(to++, match++; --n > 0; to++, match++){ | |
320 if(match->s.sp && match->e.ep){ | |
321 p = match->e.ep; | |
322 c = *p; | |
323 *p = 0; | |
324 *to = strdup(match->s.sp); | |
325 *p = c; | |
326 } | |
327 else | |
328 *to = 0; | |
329 } | |
330 } | |
331 | |
332 unsigned long | |
333 mkmtime(char *name) | |
334 { | |
335 struct stat st; | |
336 | |
337 if(stat(name, &st) < 0) | |
338 return 0; | |
339 | |
340 return st.st_mtime; | |
341 } |