xref: /inferno-os/utils/mk/Posix.c (revision d3641b487cf5cdc46e9b537d30eb37736e5c7b1a)
1 #include	"mk.h"
2 #include	<dirent.h>
3 #include	<signal.h>
4 #include	<sys/wait.h>
5 #include	<utime.h>
6 #include	<stdio.h>
7 
8 char 	*shell =	"/bin/sh";
9 char 	*shellname =	"sh";
10 
11 extern char **environ;
12 
13 void
14 readenv(void)
15 {
16 	char **p, *s;
17 	Word *w;
18 
19 	for(p = environ; *p; p++){
20 		s = shname(*p);
21 		if(*s == '=') {
22 			*s = 0;
23 			w = newword(s+1);
24 		} else
25 			w = newword("");
26 		if (symlook(*p, S_INTERNAL, 0))
27 			continue;
28 		s = strdup(*p);
29 		setvar(s, (void *)w);
30 		symlook(s, S_EXPORTED, (void*)"")->value = (void*)"";
31 	}
32 }
33 
34 /*
35  *	done on child side of fork, so parent's env is not affected
36  *	and we don't care about freeing memory because we're going
37  *	to exec immediately after this.
38  */
39 void
40 exportenv(Envy *e)
41 {
42 	int i;
43 	char **p;
44 	char *values;
45 
46 	p = 0;
47 	for(i = 0; e->name; e++, i++) {
48 		p = (char**) Realloc(p, (i+2)*sizeof(char*));
49 		if (e->values)
50 			values = wtos(e->values, IWS);
51 		else
52 			values = "";
53 		p[i] = malloc(strlen(e->name) + strlen(values) + 2);
54 		sprint(p[i], "%s=%s", e->name,  values);
55 	}
56 	p[i] = 0;
57 	environ = p;
58 }
59 
60 int
61 waitfor(char *msg)
62 {
63 	int status;
64 	int pid;
65 
66 	*msg = 0;
67 	pid = wait(&status);
68 	if(pid > 0) {
69 		if(status&0x7f) {
70 			if(status&0x80)
71 				snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);
72 			else
73 				snprint(msg, ERRMAX, "signal %d", status&0x7f);
74 		} else if(status&0xff00)
75 			snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
76 	}
77 	return pid;
78 }
79 
80 void
81 expunge(int pid, char *msg)
82 {
83 	if(strcmp(msg, "interrupt"))
84 		kill(pid, SIGINT);
85 	else
86 		kill(pid, SIGHUP);
87 }
88 
89 int
90 execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
91 {
92 	char *p;
93 	int tot, n, pid, in[2], out[2];
94 
95 	if(buf && pipe(out) < 0){
96 		perror("pipe");
97 		Exit();
98 	}
99 	pid = fork();
100 	if(pid < 0){
101 		perror("mk fork");
102 		Exit();
103 	}
104 	if(pid == 0){
105 		if(buf)
106 			close(out[0]);
107 		if(pipe(in) < 0){
108 			perror("pipe");
109 			Exit();
110 		}
111 		pid = fork();
112 		if(pid < 0){
113 			perror("mk fork");
114 			Exit();
115 		}
116 		if(pid != 0){
117 			dup2(in[0], 0);
118 			if(buf){
119 				dup2(out[1], 1);
120 				close(out[1]);
121 			}
122 			close(in[0]);
123 			close(in[1]);
124 			if (e)
125 				exportenv(e);
126 			if(shflags)
127 				execl(shell, shellname, shflags, args, nil);
128 			else
129 				execl(shell, shellname, args, nil);
130 			perror(shell);
131 			_exits("exec");
132 		}
133 		close(out[1]);
134 		close(in[0]);
135 		if(DEBUG(D_EXEC))
136 			fprint(1, "starting: %s\n", cmd);
137 		p = cmd+strlen(cmd);
138 		while(cmd < p){
139 			n = write(in[1], cmd, p-cmd);
140 			if(n < 0)
141 				break;
142 			cmd += n;
143 		}
144 		close(in[1]);
145 		_exits(0);
146 	}
147 	if(buf){
148 		close(out[1]);
149 		tot = 0;
150 		for(;;){
151 			if (buf->current >= buf->end)
152 				growbuf(buf);
153 			n = read(out[0], buf->current, buf->end-buf->current);
154 			if(n <= 0)
155 				break;
156 			buf->current += n;
157 			tot += n;
158 		}
159 		if (tot && buf->current[-1] == '\n')
160 			buf->current--;
161 		close(out[0]);
162 	}
163 	return pid;
164 }
165 
166 int
167 pipecmd(char *cmd, Envy *e, int *fd)
168 {
169 	int pid, pfd[2];
170 
171 	if(DEBUG(D_EXEC))
172 		fprint(1, "pipecmd='%s'\n", cmd);/**/
173 
174 	if(fd && pipe(pfd) < 0){
175 		perror("pipe");
176 		Exit();
177 	}
178 	pid = fork();
179 	if(pid < 0){
180 		perror("mk fork");
181 		Exit();
182 	}
183 	if(pid == 0){
184 		if(fd){
185 			close(pfd[0]);
186 			dup2(pfd[1], 1);
187 			close(pfd[1]);
188 		}
189 		if(e)
190 			exportenv(e);
191 		if(shflags)
192 			execl(shell, shellname, shflags, "-c", cmd, nil);
193 		else
194 			execl(shell, shellname, "-c", cmd, nil);
195 		perror(shell);
196 		_exits("exec");
197 	}
198 	if(fd){
199 		close(pfd[1]);
200 		*fd = pfd[0];
201 	}
202 	return pid;
203 }
204 
205 void
206 Exit(void)
207 {
208 	while(wait(0) >= 0)
209 		;
210 	exits("error");
211 }
212 
213 static	struct
214 {
215 	int	sig;
216 	char	*msg;
217 }	sigmsgs[] =
218 {
219 	SIGALRM,	"alarm",
220 	SIGFPE,		"sys: fp: fptrap",
221 	SIGPIPE,	"sys: write on closed pipe",
222 	SIGILL,		"sys: trap: illegal instruction",
223 	SIGSEGV,	"sys: segmentation violation",
224 	0,		0
225 };
226 
227 static void
228 notifyf(int sig)
229 {
230 	int i;
231 
232 	for(i = 0; sigmsgs[i].msg; i++)
233 		if(sigmsgs[i].sig == sig)
234 			killchildren(sigmsgs[i].msg);
235 
236 	/* should never happen */
237 	signal(sig, SIG_DFL);
238 	kill(getpid(), sig);
239 }
240 
241 void
242 catchnotes()
243 {
244 	int i;
245 
246 	for(i = 0; sigmsgs[i].msg; i++)
247 		signal(sigmsgs[i].sig, notifyf);
248 }
249 
250 char*
251 maketmp(void)
252 {
253 	static char temp[L_tmpnam];
254 
255 	return tmpnam(temp);
256 }
257 
258 int
259 chgtime(char *name)
260 {
261 	Dir *sbuf;
262 	struct utimbuf u;
263 
264 	if((sbuf = dirstat(name)) != nil) {
265 		u.actime = sbuf->atime;
266 		free(sbuf);
267 		u.modtime = time(0);
268 		return utime(name, &u);
269 	}
270 	return close(create(name, OWRITE, 0666));
271 }
272 
273 void
274 rcopy(char **to, Resub *match, int n)
275 {
276 	int c;
277 	char *p;
278 
279 	*to = match->s.sp;		/* stem0 matches complete target */
280 	for(to++, match++; --n > 0; to++, match++){
281 		if(match->s.sp && match->e.ep){
282 			p = match->e.ep;
283 			c = *p;
284 			*p = 0;
285 			*to = strdup(match->s.sp);
286 			*p = c;
287 		}
288 		else
289 			*to = 0;
290 	}
291 }
292 
293 ulong
294 mkmtime(char *name)
295 {
296 	Dir *buf;
297 	ulong t;
298 
299 	buf = dirstat(name);
300 	if(buf == nil)
301 		return 0;
302 	t = buf->mtime;
303 	free(buf);
304 	return t;
305 }
306 
307 
308 char *stab;
309 
310 char *
311 membername(char *s, int fd, char *sz)
312 {
313 	long t;
314 	char *p, *q;
315 
316 	if(s[0] == '/' && s[1] == '\0'){	/* long file name string table */
317 		t = atol(sz);
318 		if(t&01) t++;
319 		stab = malloc(t);
320 		if(read(fd, stab, t) != t)
321 			{}
322 		return nil;
323 	}
324 	else if(s[0] == '/' && stab != nil)	{	/* index into string table */
325 		p = stab+atol(s+1);
326 		q = strchr(p, '/');
327 		if (q)
328 			*q = 0;				/* terminate string here */
329 		return p;
330 	}else
331 		return s;
332 }
333