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*)"")->value = (void*)"";
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 i;
57 char **p;
58 static char buf[16384];
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(e->values, sh->iws));
65 else
66 snprint(buf, sizeof buf, "%s=", e->name);
67 p[i] = strdup(buf);
68 }
69 p[i] = 0;
70 environ = p;
71 }
73 int
74 waitfor(char *msg)
75 {
76 int status;
77 int pid;
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 dumped", status&0x7f);
85 else
86 snprint(msg, ERRMAX, "signal %d", status&0x7f);
87 } else if(status&0xff00)
88 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
89 }
90 return pid;
91 }
93 void
94 expunge(int pid, char *msg)
95 {
96 if(strcmp(msg, "interrupt"))
97 kill(pid, SIGINT);
98 else
99 kill(pid, SIGHUP);
102 int mypid;
104 int
105 shargv(Word *cmd, int extra, char ***pargv)
107 char **argv;
108 int i, n;
109 Word *w;
111 n = 0;
112 for(w=cmd; w; w=w->next)
113 n++;
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;
124 int
125 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
127 char *p, **argv;
128 int tot, n, pid, in[2], out[2];
130 if(buf && pipe(out) < 0){
131 mkperror("pipe");
132 Exit();
134 pid = fork();
135 mypid = getpid();
136 if(pid < 0){
137 mkperror("mk fork");
138 Exit();
140 if(pid == 0){
141 if(buf)
142 close(out[0]);
143 if(pipe(in) < 0){
144 mkperror("pipe");
145 Exit();
147 pid = fork();
148 if(pid < 0){
149 mkperror("mk fork");
150 Exit();
152 if(pid != 0){
153 dup2(in[0], 0);
154 if(buf){
155 dup2(out[1], 1);
156 close(out[1]);
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);
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;
180 close(in[1]);
181 _exit(0);
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->current);
190 if(n <= 0)
191 break;
192 buf->current += n;
193 tot += n;
195 if (tot && buf->current[-1] == '\n')
196 buf->current--;
197 close(out[0]);
199 return pid;
202 int
203 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)
205 int pid, pfd[2];
206 int n;
207 char **argv;
209 if(DEBUG(D_EXEC))
210 fprint(1, "pipecmd='%s'\n", cmd);/**/
212 if(fd && pipe(pfd) < 0){
213 mkperror("pipe");
214 Exit();
216 pid = fork();
217 if(pid < 0){
218 mkperror("mk fork");
219 Exit();
221 if(pid == 0){
222 if(fd){
223 close(pfd[0]);
224 dup2(pfd[1], 1);
225 close(pfd[1]);
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);
237 if(fd){
238 close(pfd[1]);
239 *fd = pfd[0];
241 return pid;
244 void
245 Exit(void)
247 while(wait(0) >= 0)
249 exits("error");
252 static struct
254 int sig;
255 char *msg;
256 } sigmsgs[] =
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 };
266 static void
267 notifyf(int sig)
269 int i;
271 for(i = 0; sigmsgs[i].msg; i++)
272 if(sigmsgs[i].sig == sig)
273 killchildren(sigmsgs[i].msg);
275 /* should never happen */
276 signal(sig, SIG_DFL);
277 kill(getpid(), sig);
280 void
281 catchnotes(void)
283 int i;
285 for(i = 0; sigmsgs[i].msg; i++)
286 signal(sigmsgs[i].sig, notifyf);
289 char*
290 maketmp(int *pfd)
292 static char temp[] = "/tmp/mkargXXXXXX";
293 static char buf[100];
294 int fd;
296 strcpy(buf, temp);
297 fd = mkstemp(buf);
298 if(fd < 0)
299 return 0;
300 *pfd = fd;
301 return buf;
304 int
305 chgtime(char *name)
307 if(access(name, 0) >= 0)
308 return utimes(name, 0);
309 return close(creat(name, 0666));
312 void
313 rcopy(char **to, Resub *match, int n)
315 int c;
316 char *p;
318 *to = match->s.sp; /* stem0 matches complete target */
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;
327 else
328 *to = 0;
332 unsigned long
333 mkmtime(char *name)
335 struct stat st;
337 if(stat(name, &st) < 0)
338 return 0;
340 return st.st_mtime;