xref: /plan9/sys/src/cmd/upas/common/process.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier /* make a stream to a child process */
43e12c5d1SDavid du Colombier extern stream *
53e12c5d1SDavid du Colombier instream(void)
63e12c5d1SDavid du Colombier {
73e12c5d1SDavid du Colombier 	stream *rv;
83e12c5d1SDavid du Colombier 	int pfd[2];
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier 	if ((rv = (stream *)malloc(sizeof(stream))) == 0)
113e12c5d1SDavid du Colombier 		return 0;
123e12c5d1SDavid du Colombier 	if (pipe(pfd) < 0)
133e12c5d1SDavid du Colombier 		return 0;
143e12c5d1SDavid du Colombier 	if(Binit(&rv->bb, pfd[1], OWRITE) < 0){
153e12c5d1SDavid du Colombier 		close(pfd[0]);
163e12c5d1SDavid du Colombier 		close(pfd[1]);
173e12c5d1SDavid du Colombier 		return 0;
183e12c5d1SDavid du Colombier 	}
193e12c5d1SDavid du Colombier 	rv->fp = &rv->bb;
203e12c5d1SDavid du Colombier 	rv->fd = pfd[0];
213e12c5d1SDavid du Colombier 	return rv;
223e12c5d1SDavid du Colombier }
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier /* make a stream from a child process */
253e12c5d1SDavid du Colombier extern stream *
263e12c5d1SDavid du Colombier outstream(void)
273e12c5d1SDavid du Colombier {
283e12c5d1SDavid du Colombier 	stream *rv;
293e12c5d1SDavid du Colombier 	int pfd[2];
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier 	if ((rv = (stream *)malloc(sizeof(stream))) == 0)
323e12c5d1SDavid du Colombier 		return 0;
333e12c5d1SDavid du Colombier 	if (pipe(pfd) < 0)
343e12c5d1SDavid du Colombier 		return 0;
353e12c5d1SDavid du Colombier 	if (Binit(&rv->bb, pfd[0], OREAD) < 0){
363e12c5d1SDavid du Colombier 		close(pfd[0]);
373e12c5d1SDavid du Colombier 		close(pfd[1]);
383e12c5d1SDavid du Colombier 		return 0;
393e12c5d1SDavid du Colombier 	}
403e12c5d1SDavid du Colombier 	rv->fp = &rv->bb;
413e12c5d1SDavid du Colombier 	rv->fd = pfd[1];
423e12c5d1SDavid du Colombier 	return rv;
433e12c5d1SDavid du Colombier }
443e12c5d1SDavid du Colombier 
453e12c5d1SDavid du Colombier extern void
463e12c5d1SDavid du Colombier stream_free(stream *sp)
473e12c5d1SDavid du Colombier {
483e12c5d1SDavid du Colombier 	int fd;
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier 	close(sp->fd);
513e12c5d1SDavid du Colombier 	fd = Bfildes(sp->fp);
52*219b2ee8SDavid du Colombier 	Bterm(sp->fp);
533e12c5d1SDavid du Colombier 	close(fd);
543e12c5d1SDavid du Colombier 	free((char *)sp);
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier /* start a new process */
583e12c5d1SDavid du Colombier extern process *
59bd389b36SDavid du Colombier proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, int none)
603e12c5d1SDavid du Colombier {
613e12c5d1SDavid du Colombier 	process *pp;
623e12c5d1SDavid du Colombier 	int i;
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier 	if ((pp = (process *)malloc(sizeof(process))) == 0) {
653e12c5d1SDavid du Colombier 		if (inp != 0)
663e12c5d1SDavid du Colombier 			stream_free(inp);
673e12c5d1SDavid du Colombier 		if (outp != 0)
683e12c5d1SDavid du Colombier 			stream_free(outp);
693e12c5d1SDavid du Colombier 		if (errp != 0)
703e12c5d1SDavid du Colombier 			stream_free(errp);
713e12c5d1SDavid du Colombier 		return 0;
723e12c5d1SDavid du Colombier 	}
733e12c5d1SDavid du Colombier 	pp->std[0] = inp;
743e12c5d1SDavid du Colombier 	pp->std[1] = outp;
753e12c5d1SDavid du Colombier 	pp->std[2] = errp;
763e12c5d1SDavid du Colombier 	switch (pp->pid = fork()) {
773e12c5d1SDavid du Colombier 	case -1:
783e12c5d1SDavid du Colombier 		proc_free(pp);
793e12c5d1SDavid du Colombier 		return 0;
803e12c5d1SDavid du Colombier 	case 0:
813e12c5d1SDavid du Colombier 		if(newpg)
823e12c5d1SDavid du Colombier 			newprocgroup();
83bd389b36SDavid du Colombier 		if(none)
84bd389b36SDavid du Colombier 			becomenone();
853e12c5d1SDavid du Colombier 		for (i=0; i<3; i++)
863e12c5d1SDavid du Colombier 			if (pp->std[i] != 0)
873e12c5d1SDavid du Colombier 				close(Bfildes(pp->std[i]->fp));
883e12c5d1SDavid du Colombier 		for (i=0; i<3; i++)
893e12c5d1SDavid du Colombier 			if (pp->std[i] != 0)
903e12c5d1SDavid du Colombier 				dup(pp->std[i]->fd, i);
913e12c5d1SDavid du Colombier 
923e12c5d1SDavid du Colombier 		for (i = 3; i < nofile; i++)
933e12c5d1SDavid du Colombier 			close(i);
943e12c5d1SDavid du Colombier 		execl("/bin/rc", "rc", "-c", cmd, 0);
953e12c5d1SDavid du Colombier 		perror("proc_start");
963e12c5d1SDavid du Colombier 		exits("proc_start");
973e12c5d1SDavid du Colombier 	default:
983e12c5d1SDavid du Colombier 		for (i=0; i<nsysfile; i++)
993e12c5d1SDavid du Colombier 			if (pp->std[i] != 0) {
1003e12c5d1SDavid du Colombier 				close(pp->std[i]->fd);
1013e12c5d1SDavid du Colombier 				pp->std[i]->fd = -1;
1023e12c5d1SDavid du Colombier 			}
1033e12c5d1SDavid du Colombier 		return pp;
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier /* wait for a process to stop */
1083e12c5d1SDavid du Colombier extern int
1093e12c5d1SDavid du Colombier proc_wait(process *pp)
1103e12c5d1SDavid du Colombier {
1113e12c5d1SDavid du Colombier 	Waitmsg status;
1123e12c5d1SDavid du Colombier 	int pid;
113*219b2ee8SDavid du Colombier 	char err[ERRLEN];
1143e12c5d1SDavid du Colombier 
115*219b2ee8SDavid du Colombier 	for(;;){
116*219b2ee8SDavid du Colombier 		pid = wait(&status);
117*219b2ee8SDavid du Colombier 		if(pid < 0){
118*219b2ee8SDavid du Colombier 			errstr(err);
119*219b2ee8SDavid du Colombier 			if(strstr(err, "interrupt") == 0)
120*219b2ee8SDavid du Colombier 				break;
121*219b2ee8SDavid du Colombier 		}
1223e12c5d1SDavid du Colombier 		if (pid==pp->pid)
1233e12c5d1SDavid du Colombier 			break;
1243e12c5d1SDavid du Colombier 	}
1253e12c5d1SDavid du Colombier 	pp->pid = -1;
1263e12c5d1SDavid du Colombier 	pp->status = status.msg[0];
1273e12c5d1SDavid du Colombier 	return pp->status;
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier static int junk;
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier /* free a process */
1333e12c5d1SDavid du Colombier extern int
1343e12c5d1SDavid du Colombier proc_free(process *pp)
1353e12c5d1SDavid du Colombier {
1363e12c5d1SDavid du Colombier 	int i;
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier 	if(pp->std[1] == pp->std[2])
1393e12c5d1SDavid du Colombier 		pp->std[2] = 0;		/* avoid freeing it twice */
1403e12c5d1SDavid du Colombier 	for (i = 0; i < 3; i++)
1413e12c5d1SDavid du Colombier 		if (pp->std[i])
1423e12c5d1SDavid du Colombier 			stream_free(pp->std[i]);
1433e12c5d1SDavid du Colombier 	if (pp->pid >= 0){
1443e12c5d1SDavid du Colombier 		USE(proc_wait(pp));
1453e12c5d1SDavid du Colombier 	}
1463e12c5d1SDavid du Colombier 	free((char *)pp);
1473e12c5d1SDavid du Colombier 	return 0;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier /* kill a process */
1513e12c5d1SDavid du Colombier extern int
1523e12c5d1SDavid du Colombier proc_kill(process *pp)
1533e12c5d1SDavid du Colombier {
1543e12c5d1SDavid du Colombier 	return syskill(pp->pid);
1553e12c5d1SDavid du Colombier }
156