Blob


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>
8 char *shell = "/bin/sh";
9 char *shellname = "sh";
11 extern char **environ;
13 static void
14 mkperror(char *s)
15 {
16 fprint(2, "%s: %r\n", s);
17 }
19 void
20 readenv(void)
21 {
22 char **p, *s;
23 Word *w;
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 }
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];
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 == 0 || e->values->s[0] == 0))
68 continue; /* do not write empty string for empty list */
69 if(e->values)
70 snprint(buf, sizeof buf, "%s=%s", e->name, wtos(e->values, sh->iws));
71 else
72 snprint(buf, sizeof buf, "%s=", e->name);
73 p[w++] = strdup(buf);
74 }
75 p[w] = 0;
76 environ = p;
77 }
79 int
80 waitfor(char *msg)
81 {
82 int status;
83 int pid;
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 dumped", status&0x7f);
91 else
92 snprint(msg, ERRMAX, "signal %d", status&0x7f);
93 } else if(status&0xff00)
94 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
95 }
96 return pid;
97 }
99 void
100 expunge(int pid, char *msg)
102 if(strcmp(msg, "interrupt"))
103 kill(pid, SIGINT);
104 else
105 kill(pid, SIGHUP);
108 int mypid;
110 int
111 shargv(Word *cmd, int extra, char ***pargv)
113 char **argv;
114 int i, n;
115 Word *w;
117 n = 0;
118 for(w=cmd; w; w=w->next)
119 n++;
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;
130 int
131 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
133 char *p, **argv;
134 int tot, n, pid, in[2], out[2];
136 if(buf && pipe(out) < 0){
137 mkperror("pipe");
138 Exit();
140 pid = fork();
141 mypid = getpid();
142 if(pid < 0){
143 mkperror("mk fork");
144 Exit();
146 if(pid == 0){
147 if(buf)
148 close(out[0]);
149 if(pipe(in) < 0){
150 mkperror("pipe");
151 Exit();
153 pid = fork();
154 if(pid < 0){
155 mkperror("mk fork");
156 Exit();
158 if(pid != 0){
159 dup2(in[0], 0);
160 if(buf){
161 dup2(out[1], 1);
162 close(out[1]);
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);
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;
186 close(in[1]);
187 _exit(0);
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->current);
196 if(n <= 0)
197 break;
198 buf->current += n;
199 tot += n;
201 if (tot && buf->current[-1] == '\n')
202 buf->current--;
203 close(out[0]);
205 return pid;
208 int
209 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)
211 int pid, pfd[2];
212 int n;
213 char **argv;
215 if(DEBUG(D_EXEC))
216 fprint(1, "pipecmd='%s'\n", cmd);/**/
218 if(fd && pipe(pfd) < 0){
219 mkperror("pipe");
220 Exit();
222 pid = fork();
223 if(pid < 0){
224 mkperror("mk fork");
225 Exit();
227 if(pid == 0){
228 if(fd){
229 close(pfd[0]);
230 dup2(pfd[1], 1);
231 close(pfd[1]);
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);
243 if(fd){
244 close(pfd[1]);
245 *fd = pfd[0];
247 return pid;
250 void
251 Exit(void)
253 while(wait(0) >= 0)
255 exits("error");
258 static struct
260 int sig;
261 char *msg;
262 } sigmsgs[] =
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 };
272 static void
273 notifyf(int sig)
275 int i;
277 for(i = 0; sigmsgs[i].msg; i++)
278 if(sigmsgs[i].sig == sig)
279 killchildren(sigmsgs[i].msg);
281 /* should never happen */
282 signal(sig, SIG_DFL);
283 kill(getpid(), sig);
286 void
287 catchnotes(void)
289 int i;
291 for(i = 0; sigmsgs[i].msg; i++)
292 signal(sigmsgs[i].sig, notifyf);
295 char*
296 maketmp(int *pfd)
298 static char temp[] = "/tmp/mkargXXXXXX";
299 static char buf[100];
300 int fd;
302 strcpy(buf, temp);
303 fd = mkstemp(buf);
304 if(fd < 0)
305 return 0;
306 *pfd = fd;
307 return buf;
310 int
311 chgtime(char *name)
313 if(access(name, 0) >= 0)
314 return utimes(name, 0);
315 return close(creat(name, 0666));
318 void
319 rcopy(char **to, Resub *match, int n)
321 int c;
322 char *p;
324 *to = match->s.sp; /* stem0 matches complete target */
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;
333 else
334 *to = 0;
338 unsigned long
339 mkmtime(char *name)
341 struct stat st;
343 if(stat(name, &st) < 0)
344 return 0;
346 return st.st_mtime;