xref: /inferno-os/utils/mk/Plan9.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include	"mk.h"
2 
3 char 	*shell =	"/bin/rc";
4 char 	*shellname =	"rc";
5 
6 static	Word	*encodenulls(char*, int);
7 
8 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 			sprint(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*)"")->value = (void*)"";
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 *
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
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 		sprint(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
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
153 expunge(int pid, char *msg)
154 {
155 	postnote(PNPROC, pid, msg);
156 }
157 
158 int
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
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
273 Exit(void)
274 {
275 	while(waitpid() >= 0)
276 		;
277 	exits("error");
278 }
279 
280 int
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
298 catchnotes()
299 {
300 	atnotify(notifyf, 1);
301 }
302 
303 char*
304 maketmp(void)
305 {
306 	static char temp[] = "/tmp/mkargXXXXXXXXXXX";
307 
308 	mktemp(temp);
309 	return temp;
310 }
311 
312 int
313 chgtime(char *name)
314 {
315 	Dir sbuf;
316 
317 	if(access(name, AEXIST) >= 0) {
318 		nulldir(&sbuf);
319 		sbuf.mtime = time(0);
320 		return dirwstat(name, &sbuf);
321 	}
322 	return close(create(name, OWRITE, 0666));
323 }
324 
325 void
326 rcopy(char **to, Resub *match, int n)
327 {
328 	int c;
329 	char *p;
330 
331 	*to = match->s.sp;		/* stem0 matches complete target */
332 	for(to++, match++; --n > 0; to++, match++){
333 		if(match->s.sp && match->e.ep){
334 			p = match->e.ep;
335 			c = *p;
336 			*p = 0;
337 			*to = strdup(match->s.sp);
338 			*p = c;
339 		}
340 		else
341 			*to = 0;
342 	}
343 }
344 
345 ulong
346 mkmtime(char *name)
347 {
348 	Dir *buf;
349 	ulong t;
350 
351 	buf = dirstat(name);
352 	if(buf == nil)
353 		return 0;
354 	t = buf->mtime;
355 	free(buf);
356 	return t;
357 }
358 
359 char *
360 membername(char *s, int, char*)
361 {
362 	return s;
363 }
364