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 s = shname(*p);
27 if(*s == '=') {
28 *s = 0;
29 w = newword(s+1);
30 } else
31 w = newword("");
32 if (symlook(*p, S_INTERNAL, 0))
33 continue;
34 s = strdup(*p);
35 setvar(s, (void *)w);
36 symlook(s, S_EXPORTED, (void*)"")->value = (void*)"";
37 }
38 }
40 /*
41 * done on child side of fork, so parent's env is not affected
42 * and we don't care about freeing memory because we're going
43 * to exec immediately after this.
44 */
45 void
46 exportenv(Envy *e)
47 {
48 int i;
49 char **p;
50 char buf[4096];
52 p = 0;
53 for(i = 0; e->name; e++, i++) {
54 p = (char**) Realloc(p, (i+2)*sizeof(char*));
55 if(e->values)
56 sprint(buf, "%s=%s", e->name, wtos(e->values, IWS));
57 else
58 sprint(buf, "%s=", e->name);
59 p[i] = strdup(buf);
60 }
61 p[i] = 0;
62 environ = p;
63 }
65 int
66 waitfor(char *msg)
67 {
68 int status;
69 int pid;
71 *msg = 0;
72 pid = wait(&status);
73 if(pid > 0) {
74 if(status&0x7f) {
75 if(status&0x80)
76 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);
77 else
78 snprint(msg, ERRMAX, "signal %d", status&0x7f);
79 } else if(status&0xff00)
80 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
81 }
82 return pid;
83 }
85 void
86 expunge(int pid, char *msg)
87 {
88 if(strcmp(msg, "interrupt"))
89 kill(pid, SIGINT);
90 else
91 kill(pid, SIGHUP);
92 }
94 int
95 execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
96 {
97 char *p;
98 int tot, n, pid, in[2], out[2];
100 if(buf && pipe(out) < 0){
101 mkperror("pipe");
102 Exit();
104 pid = fork();
105 if(pid < 0){
106 mkperror("mk fork");
107 Exit();
109 if(pid == 0){
110 if(buf)
111 close(out[0]);
112 if(pipe(in) < 0){
113 mkperror("pipe");
114 Exit();
116 pid = fork();
117 if(pid < 0){
118 mkperror("mk fork");
119 Exit();
121 if(pid != 0){
122 dup2(in[0], 0);
123 if(buf){
124 dup2(out[1], 1);
125 close(out[1]);
127 close(in[0]);
128 close(in[1]);
129 if (e)
130 exportenv(e);
131 if(shflags)
132 execl(shell, shellname, shflags, args, 0);
133 else
134 execl(shell, shellname, args, 0);
135 mkperror(shell);
136 _exit(1);
138 close(out[1]);
139 close(in[0]);
140 if(DEBUG(D_EXEC))
141 fprint(1, "starting: %s\n", cmd);
142 p = cmd+strlen(cmd);
143 while(cmd < p){
144 n = write(in[1], cmd, p-cmd);
145 if(n < 0)
146 break;
147 cmd += n;
149 close(in[1]);
150 _exit(0);
152 if(buf){
153 close(out[1]);
154 tot = 0;
155 for(;;){
156 if (buf->current >= buf->end)
157 growbuf(buf);
158 n = read(out[0], buf->current, buf->end-buf->current);
159 if(n <= 0)
160 break;
161 buf->current += n;
162 tot += n;
164 if (tot && buf->current[-1] == '\n')
165 buf->current--;
166 close(out[0]);
168 return pid;
171 int
172 pipecmd(char *cmd, Envy *e, int *fd)
174 int pid, pfd[2];
176 if(DEBUG(D_EXEC))
177 fprint(1, "pipecmd='%s'\n", cmd);/**/
179 if(fd && pipe(pfd) < 0){
180 mkperror("pipe");
181 Exit();
183 pid = fork();
184 if(pid < 0){
185 mkperror("mk fork");
186 Exit();
188 if(pid == 0){
189 if(fd){
190 close(pfd[0]);
191 dup2(pfd[1], 1);
192 close(pfd[1]);
194 if(e)
195 exportenv(e);
196 if(shflags)
197 execl(shell, shellname, shflags, "-c", cmd, 0);
198 else
199 execl(shell, shellname, "-c", cmd, 0);
200 mkperror(shell);
201 _exit(1);
203 if(fd){
204 close(pfd[1]);
205 *fd = pfd[0];
207 return pid;
210 void
211 Exit(void)
213 while(wait(0) >= 0)
215 exits("error");
218 static struct
220 int sig;
221 char *msg;
222 } sigmsgs[] =
224 SIGALRM, "alarm",
225 SIGFPE, "sys: fp: fptrap",
226 SIGPIPE, "sys: write on closed pipe",
227 SIGILL, "sys: trap: illegal instruction",
228 SIGSEGV, "sys: segmentation violation",
229 0, 0
230 };
232 static void
233 notifyf(int sig)
235 int i;
237 for(i = 0; sigmsgs[i].msg; i++)
238 if(sigmsgs[i].sig == sig)
239 killchildren(sigmsgs[i].msg);
241 /* should never happen */
242 signal(sig, SIG_DFL);
243 kill(getpid(), sig);
246 void
247 catchnotes()
249 int i;
251 for(i = 0; sigmsgs[i].msg; i++)
252 signal(sigmsgs[i].sig, notifyf);
255 char*
256 maketmp(int *pfd)
258 static char temp[] = "/tmp/mkargXXXXXX";
259 static char buf[100];
260 int fd;
262 strcpy(buf, temp);
263 fd = mkstemp(buf);
264 if(fd < 0)
265 return 0;
266 *pfd = fd;
267 return buf;
270 int
271 chgtime(char *name)
273 if(access(name, 0) >= 0)
274 return utimes(name, 0);
275 return close(creat(name, 0666));
278 void
279 rcopy(char **to, Resub *match, int n)
281 int c;
282 char *p;
284 *to = match->s.sp; /* stem0 matches complete target */
285 for(to++, match++; --n > 0; to++, match++){
286 if(match->s.sp && match->e.ep){
287 p = match->e.ep;
288 c = *p;
289 *p = 0;
290 *to = strdup(match->s.sp);
291 *p = c;
293 else
294 *to = 0;
298 ulong
299 mkmtime(char *name)
301 struct stat st;
303 if(stat(name, &st) < 0)
304 return 0;
306 return st.st_mtime;