1 #include "mk.h"
2
3 char *shell = "/bin/rc";
4 char *shellname = "rc";
5
6 static Word *encodenulls(char*, int);
7
8 void
readenv(void)9 readenv(void)
10 {
11 char *p;
12 int envf, f;
13 Dir *e;
14 char nam[1024];
15 int i, n, len;
16 Word *w;
17
18 rfork(RFENVG); /* use copy of the current environment variables */
19
20 envf = open("/env", OREAD);
21 if(envf < 0)
22 return;
23 while((n = dirread(envf, &e)) > 0){
24 for(i = 0; i < n; i++){
25 len = e[i].length;
26 /* don't import funny names, NULL values,
27 * or internal mk variables
28 */
29 if(len <= 0 || *shname(e[i].name) != '\0')
30 continue;
31 if (symlook(e[i].name, S_INTERNAL, 0))
32 continue;
33 snprint(nam, sizeof nam, "/env/%s", e[i].name);
34 f = open(nam, OREAD);
35 if(f < 0)
36 continue;
37 p = Malloc(len+1);
38 if(read(f, p, len) != len){
39 perror(nam);
40 close(f);
41 continue;
42 }
43 close(f);
44 if (p[len-1] == 0)
45 len--;
46 else
47 p[len] = 0;
48 w = encodenulls(p, len);
49 free(p);
50 p = strdup(e[i].name);
51 setvar(p, (void *) w);
52 symlook(p, S_EXPORTED, (void*)"")->u.ptr = "";
53 }
54 free(e);
55 }
56 close(envf);
57 }
58
59 /* break string of values into words at 01's or nulls*/
60 static Word *
encodenulls(char * s,int n)61 encodenulls(char *s, int n)
62 {
63 Word *w, *head;
64 char *cp;
65
66 head = w = 0;
67 while (n-- > 0) {
68 for (cp = s; *cp && *cp != '\0'; cp++)
69 n--;
70 *cp = 0;
71 if (w) {
72 w->next = newword(s);
73 w = w->next;
74 } else
75 head = w = newword(s);
76 s = cp+1;
77 }
78 if (!head)
79 head = newword("");
80 return head;
81 }
82
83 /* as well as 01's, change blanks to nulls, so that rc will
84 * treat the words as separate arguments
85 */
86 void
exportenv(Envy * e)87 exportenv(Envy *e)
88 {
89 int f, n, hasvalue, first;
90 Word *w;
91 Symtab *sy;
92 char nam[256];
93
94 for(;e->name; e++){
95 sy = symlook(e->name, S_VAR, 0);
96 if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0)
97 hasvalue = 0;
98 else
99 hasvalue = 1;
100 if(sy == 0 && !hasvalue) /* non-existant null symbol */
101 continue;
102 snprint(nam, sizeof nam, "/env/%s", e->name);
103 if (sy != 0 && !hasvalue) { /* Remove from environment */
104 /* we could remove it from the symbol table
105 * too, but we're in the child copy, and it
106 * would still remain in the parent's table.
107 */
108 remove(nam);
109 delword(e->values);
110 e->values = 0; /* memory leak */
111 continue;
112 }
113
114 f = create(nam, OWRITE, 0666L);
115 if(f < 0) {
116 fprint(2, "can't create %s, f=%d\n", nam, f);
117 perror(nam);
118 continue;
119 }
120 first = 1;
121 for (w = e->values; w; w = w->next) {
122 n = strlen(w->s);
123 if (n) {
124 if(first)
125 first = 0;
126 else{
127 if (write (f, "\0", 1) != 1)
128 perror(nam);
129 }
130 if (write(f, w->s, n) != n)
131 perror(nam);
132 }
133 }
134 close(f);
135 }
136 }
137
138 int
waitfor(char * msg)139 waitfor(char *msg)
140 {
141 Waitmsg *w;
142 int pid;
143
144 if((w=wait()) == nil)
145 return -1;
146 strecpy(msg, msg+ERRMAX, w->msg);
147 pid = w->pid;
148 free(w);
149 return pid;
150 }
151
152 void
expunge(int pid,char * msg)153 expunge(int pid, char *msg)
154 {
155 postnote(PNPROC, pid, msg);
156 }
157
158 int
execsh(char * args,char * cmd,Bufblock * buf,Envy * e)159 execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
160 {
161 char *p;
162 int tot, n, pid, in[2], out[2];
163
164 if(buf && pipe(out) < 0){
165 perror("pipe");
166 Exit();
167 }
168 pid = rfork(RFPROC|RFFDG|RFENVG);
169 if(pid < 0){
170 perror("mk rfork");
171 Exit();
172 }
173 if(pid == 0){
174 if(buf)
175 close(out[0]);
176 if(pipe(in) < 0){
177 perror("pipe");
178 Exit();
179 }
180 pid = fork();
181 if(pid < 0){
182 perror("mk fork");
183 Exit();
184 }
185 if(pid != 0){
186 dup(in[0], 0);
187 if(buf){
188 dup(out[1], 1);
189 close(out[1]);
190 }
191 close(in[0]);
192 close(in[1]);
193 if (e)
194 exportenv(e);
195 if(shflags)
196 execl(shell, shellname, shflags, args, nil);
197 else
198 execl(shell, shellname, args, nil);
199 perror(shell);
200 _exits("exec");
201 }
202 close(out[1]);
203 close(in[0]);
204 p = cmd+strlen(cmd);
205 while(cmd < p){
206 n = write(in[1], cmd, p-cmd);
207 if(n < 0)
208 break;
209 cmd += n;
210 }
211 close(in[1]);
212 _exits(0);
213 }
214 if(buf){
215 close(out[1]);
216 tot = 0;
217 for(;;){
218 if (buf->current >= buf->end)
219 growbuf(buf);
220 n = read(out[0], buf->current, buf->end-buf->current);
221 if(n <= 0)
222 break;
223 buf->current += n;
224 tot += n;
225 }
226 if (tot && buf->current[-1] == '\n')
227 buf->current--;
228 close(out[0]);
229 }
230 return pid;
231 }
232
233 int
pipecmd(char * cmd,Envy * e,int * fd)234 pipecmd(char *cmd, Envy *e, int *fd)
235 {
236 int pid, pfd[2];
237
238 if(DEBUG(D_EXEC))
239 fprint(1, "pipecmd='%s'\n", cmd);/**/
240
241 if(fd && pipe(pfd) < 0){
242 perror("pipe");
243 Exit();
244 }
245 pid = rfork(RFPROC|RFFDG|RFENVG);
246 if(pid < 0){
247 perror("mk fork");
248 Exit();
249 }
250 if(pid == 0){
251 if(fd){
252 close(pfd[0]);
253 dup(pfd[1], 1);
254 close(pfd[1]);
255 }
256 if(e)
257 exportenv(e);
258 if(shflags)
259 execl(shell, shellname, shflags, "-c", cmd, nil);
260 else
261 execl(shell, shellname, "-c", cmd, nil);
262 perror(shell);
263 _exits("exec");
264 }
265 if(fd){
266 close(pfd[1]);
267 *fd = pfd[0];
268 }
269 return pid;
270 }
271
272 void
Exit(void)273 Exit(void)
274 {
275 while(waitpid() >= 0)
276 ;
277 exits("error");
278 }
279
280 int
notifyf(void * a,char * msg)281 notifyf(void *a, char *msg)
282 {
283 static int nnote;
284
285 USED(a);
286 if(++nnote > 100){ /* until andrew fixes his program */
287 fprint(2, "mk: too many notes\n");
288 notify(0);
289 abort();
290 }
291 if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0)
292 return 0;
293 killchildren(msg);
294 return -1;
295 }
296
297 void
catchnotes()298 catchnotes()
299 {
300 atnotify(notifyf, 1);
301 }
302
303 char*
maketmp(void)304 maketmp(void)
305 {
306 static char temp[] = "/tmp/mkargXXXXXX";
307
308 mktemp(temp);
309 return temp;
310 }
311
312 int
chgtime(char * name)313 chgtime(char *name)
314 {
315 Dir sbuf;
316
317 if(access(name, AEXIST) >= 0) {
318 nulldir(&sbuf);
319 sbuf.mtime = time((long *)0);
320 return dirwstat(name, &sbuf);
321 }
322 return close(create(name, OWRITE, 0666));
323 }
324
325 void
rcopy(char ** to,Resub * match,int n)326 rcopy(char **to, Resub *match, int n)
327 {
328 int c;
329 char *p;
330
331 *to = match->sp; /* stem0 matches complete target */
332 for(to++, match++; --n > 0; to++, match++){
333 if(match->sp && match->ep){
334 p = match->ep;
335 c = *p;
336 *p = 0;
337 *to = strdup(match->sp);
338 *p = c;
339 }
340 else
341 *to = 0;
342 }
343 }
344
345 void
dirtime(char * dir,char * path)346 dirtime(char *dir, char *path)
347 {
348 int i, fd, n;
349 ulong mtime;
350 Dir *d;
351 char buf[4096];
352
353 fd = open(dir, OREAD);
354 if(fd >= 0){
355 while((n = dirread(fd, &d)) > 0){
356 for(i=0; i<n; i++){
357 mtime = d[i].mtime;
358 /* defensive driving: this does happen */
359 if(mtime == 0)
360 mtime = 1;
361 snprint(buf, sizeof buf, "%s%s", path,
362 d[i].name);
363 if(symlook(buf, S_TIME, 0) == nil)
364 symlook(strdup(buf), S_TIME,
365 (void*)mtime)->u.value = mtime;
366 }
367 free(d);
368 }
369 close(fd);
370 }
371 }
372
373 void
bulkmtime(char * dir)374 bulkmtime(char *dir)
375 {
376 char buf[4096];
377 char *ss, *s, *sym;
378
379 if(dir){
380 sym = dir;
381 s = dir;
382 if(strcmp(dir, "/") == 0)
383 strecpy(buf, buf + sizeof buf - 1, dir);
384 else
385 snprint(buf, sizeof buf, "%s/", dir);
386 }else{
387 s = ".";
388 sym = "";
389 buf[0] = 0;
390 }
391 if(symlook(sym, S_BULKED, 0))
392 return;
393 ss = strdup(sym);
394 symlook(ss, S_BULKED, (void*)ss);
395 dirtime(s, buf);
396 }
397
398 ulong
mkmtime(char * name,int force)399 mkmtime(char *name, int force)
400 {
401 Dir *d;
402 char *s, *ss, carry;
403 ulong t;
404 Symtab *sym;
405 char buf[4096];
406
407 strecpy(buf, buf + sizeof buf - 1, name);
408 cleanname(buf);
409 name = buf;
410
411 s = utfrrune(name, '/');
412 if(s == name)
413 s++;
414 if(s){
415 ss = name;
416 carry = *s;
417 *s = 0;
418 }else{
419 ss = 0;
420 carry = 0;
421 }
422 bulkmtime(ss);
423 if(carry)
424 *s = carry;
425 if(!force){
426 sym = symlook(name, S_TIME, 0);
427 if(sym)
428 return sym->u.value;
429 return 0;
430 }
431 if((d = dirstat(name)) == nil)
432 return 0;
433 t = d->mtime;
434 free(d);
435 return t;
436 }
437
438