xref: /plan9/sys/src/cmd/upas/common/process.c (revision 3b86f2f88bade1f00206c7aa750b7add255f5724)
13e12c5d1SDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier /* make a stream to a child process */
43e12c5d1SDavid du Colombier extern stream *
instream(void)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;
127dd7cddfSDavid du Colombier 	memset(rv, 0, sizeof(stream));
133e12c5d1SDavid du Colombier 	if (pipe(pfd) < 0)
143e12c5d1SDavid du Colombier 		return 0;
153e12c5d1SDavid du Colombier 	if(Binit(&rv->bb, pfd[1], OWRITE) < 0){
163e12c5d1SDavid du Colombier 		close(pfd[0]);
173e12c5d1SDavid du Colombier 		close(pfd[1]);
183e12c5d1SDavid du Colombier 		return 0;
193e12c5d1SDavid du Colombier 	}
203e12c5d1SDavid du Colombier 	rv->fp = &rv->bb;
213e12c5d1SDavid du Colombier 	rv->fd = pfd[0];
223e12c5d1SDavid du Colombier 	return rv;
233e12c5d1SDavid du Colombier }
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier /* make a stream from a child process */
263e12c5d1SDavid du Colombier extern stream *
outstream(void)273e12c5d1SDavid du Colombier outstream(void)
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier 	stream *rv;
303e12c5d1SDavid du Colombier 	int pfd[2];
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier 	if ((rv = (stream *)malloc(sizeof(stream))) == 0)
333e12c5d1SDavid du Colombier 		return 0;
347dd7cddfSDavid du Colombier 	memset(rv, 0, sizeof(stream));
353e12c5d1SDavid du Colombier 	if (pipe(pfd) < 0)
363e12c5d1SDavid du Colombier 		return 0;
373e12c5d1SDavid du Colombier 	if (Binit(&rv->bb, pfd[0], OREAD) < 0){
383e12c5d1SDavid du Colombier 		close(pfd[0]);
393e12c5d1SDavid du Colombier 		close(pfd[1]);
403e12c5d1SDavid du Colombier 		return 0;
413e12c5d1SDavid du Colombier 	}
423e12c5d1SDavid du Colombier 	rv->fp = &rv->bb;
433e12c5d1SDavid du Colombier 	rv->fd = pfd[1];
443e12c5d1SDavid du Colombier 	return rv;
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier extern void
stream_free(stream * sp)483e12c5d1SDavid du Colombier stream_free(stream *sp)
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	int fd;
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 	close(sp->fd);
533e12c5d1SDavid du Colombier 	fd = Bfildes(sp->fp);
54219b2ee8SDavid du Colombier 	Bterm(sp->fp);
553e12c5d1SDavid du Colombier 	close(fd);
563e12c5d1SDavid du Colombier 	free((char *)sp);
573e12c5d1SDavid du Colombier }
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier /* start a new process */
603e12c5d1SDavid du Colombier extern process *
noshell_proc_start(char ** av,stream * inp,stream * outp,stream * errp,int newpg,char * who)617dd7cddfSDavid du Colombier noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who)
623e12c5d1SDavid du Colombier {
633e12c5d1SDavid du Colombier 	process *pp;
647dd7cddfSDavid du Colombier 	int i, n;
653e12c5d1SDavid du Colombier 
663e12c5d1SDavid du Colombier 	if ((pp = (process *)malloc(sizeof(process))) == 0) {
673e12c5d1SDavid du Colombier 		if (inp != 0)
683e12c5d1SDavid du Colombier 			stream_free(inp);
693e12c5d1SDavid du Colombier 		if (outp != 0)
703e12c5d1SDavid du Colombier 			stream_free(outp);
713e12c5d1SDavid du Colombier 		if (errp != 0)
723e12c5d1SDavid du Colombier 			stream_free(errp);
733e12c5d1SDavid du Colombier 		return 0;
743e12c5d1SDavid du Colombier 	}
753e12c5d1SDavid du Colombier 	pp->std[0] = inp;
763e12c5d1SDavid du Colombier 	pp->std[1] = outp;
773e12c5d1SDavid du Colombier 	pp->std[2] = errp;
783e12c5d1SDavid du Colombier 	switch (pp->pid = fork()) {
793e12c5d1SDavid du Colombier 	case -1:
803e12c5d1SDavid du Colombier 		proc_free(pp);
813e12c5d1SDavid du Colombier 		return 0;
823e12c5d1SDavid du Colombier 	case 0:
833e12c5d1SDavid du Colombier 		if(newpg)
847dd7cddfSDavid du Colombier 			sysdetach();
853e12c5d1SDavid du Colombier 		for (i=0; i<3; i++)
867dd7cddfSDavid du Colombier 			if (pp->std[i] != 0){
873e12c5d1SDavid du Colombier 				close(Bfildes(pp->std[i]->fp));
887dd7cddfSDavid du Colombier 				while(pp->std[i]->fd < 3)
897dd7cddfSDavid du Colombier 					pp->std[i]->fd = dup(pp->std[i]->fd, -1);
907dd7cddfSDavid du Colombier 			}
913e12c5d1SDavid du Colombier 		for (i=0; i<3; i++)
923e12c5d1SDavid du Colombier 			if (pp->std[i] != 0)
933e12c5d1SDavid du Colombier 				dup(pp->std[i]->fd, i);
947dd7cddfSDavid du Colombier 		for (n = sysfiles(); i < n; i++)
953e12c5d1SDavid du Colombier 			close(i);
967dd7cddfSDavid du Colombier 		if(who)
977dd7cddfSDavid du Colombier 			become(av, who);
987dd7cddfSDavid du Colombier 		exec(av[0], av);
993e12c5d1SDavid du Colombier 		perror("proc_start");
1003e12c5d1SDavid du Colombier 		exits("proc_start");
1013e12c5d1SDavid du Colombier 	default:
1027dd7cddfSDavid du Colombier 		for (i=0; i<3; i++)
1033e12c5d1SDavid du Colombier 			if (pp->std[i] != 0) {
1043e12c5d1SDavid du Colombier 				close(pp->std[i]->fd);
1053e12c5d1SDavid du Colombier 				pp->std[i]->fd = -1;
1063e12c5d1SDavid du Colombier 			}
1073e12c5d1SDavid du Colombier 		return pp;
1083e12c5d1SDavid du Colombier 	}
1093e12c5d1SDavid du Colombier }
1103e12c5d1SDavid du Colombier 
1117dd7cddfSDavid du Colombier /* start a new process under a shell */
1127dd7cddfSDavid du Colombier extern process *
proc_start(char * cmd,stream * inp,stream * outp,stream * errp,int newpg,char * who)1137dd7cddfSDavid du Colombier proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier 	char *av[4];
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier 	av[0] = SHELL;
1187dd7cddfSDavid du Colombier 	av[1] = "-c";
1197dd7cddfSDavid du Colombier 	av[2] = cmd;
1207dd7cddfSDavid du Colombier 	av[3] = 0;
1217dd7cddfSDavid du Colombier 	return noshell_proc_start(av, inp, outp, errp, newpg, who);
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier 
1243e12c5d1SDavid du Colombier /* wait for a process to stop */
1253e12c5d1SDavid du Colombier extern int
proc_wait(process * pp)1263e12c5d1SDavid du Colombier proc_wait(process *pp)
1273e12c5d1SDavid du Colombier {
1289a747e4fSDavid du Colombier 	Waitmsg *status;
1299a747e4fSDavid du Colombier 	char err[Errlen];
1303e12c5d1SDavid du Colombier 
131219b2ee8SDavid du Colombier 	for(;;){
1329a747e4fSDavid du Colombier 		status = wait();
1339a747e4fSDavid du Colombier 		if(status == nil){
134*3b86f2f8SDavid du Colombier 			rerrstr(err, sizeof(err));
135219b2ee8SDavid du Colombier 			if(strstr(err, "interrupt") == 0)
136219b2ee8SDavid du Colombier 				break;
137219b2ee8SDavid du Colombier 		}
1389a747e4fSDavid du Colombier 		if (status->pid==pp->pid)
1393e12c5d1SDavid du Colombier 			break;
1403e12c5d1SDavid du Colombier 	}
1413e12c5d1SDavid du Colombier 	pp->pid = -1;
1429a747e4fSDavid du Colombier 	if(status == nil)
1439a747e4fSDavid du Colombier 		pp->status = -1;
1449a747e4fSDavid du Colombier 	else
1459a747e4fSDavid du Colombier 		pp->status = status->msg[0];
1462b7fd5adSDavid du Colombier 	pp->waitmsg = status;
1473e12c5d1SDavid du Colombier 	return pp->status;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier /* free a process */
1513e12c5d1SDavid du Colombier extern int
proc_free(process * pp)1523e12c5d1SDavid du Colombier proc_free(process *pp)
1533e12c5d1SDavid du Colombier {
1543e12c5d1SDavid du Colombier 	int i;
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 	if(pp->std[1] == pp->std[2])
1573e12c5d1SDavid du Colombier 		pp->std[2] = 0;		/* avoid freeing it twice */
1583e12c5d1SDavid du Colombier 	for (i = 0; i < 3; i++)
1593e12c5d1SDavid du Colombier 		if (pp->std[i])
1603e12c5d1SDavid du Colombier 			stream_free(pp->std[i]);
1619a747e4fSDavid du Colombier 	if (pp->pid >= 0)
1629a747e4fSDavid du Colombier 		proc_wait(pp);
1632b7fd5adSDavid du Colombier 	free(pp->waitmsg);
1643e12c5d1SDavid du Colombier 	free((char *)pp);
1653e12c5d1SDavid du Colombier 	return 0;
1663e12c5d1SDavid du Colombier }
1673e12c5d1SDavid du Colombier 
1683e12c5d1SDavid du Colombier /* kill a process */
1693e12c5d1SDavid du Colombier extern int
proc_kill(process * pp)1703e12c5d1SDavid du Colombier proc_kill(process *pp)
1713e12c5d1SDavid du Colombier {
1723e12c5d1SDavid du Colombier 	return syskill(pp->pid);
1733e12c5d1SDavid du Colombier }
174