182 lines · 3.3 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "common.h" /* make a stream to a child process */extern stream *instream(void){	stream *rv;	int pfd[2]; 	if ((rv = (stream *)malloc(sizeof(stream))) == 0)		return 0;	memset(rv, 0, sizeof(stream));	if (pipe(pfd) < 0)		return 0;	if(Binit(&rv->bb, pfd[1], OWRITE) < 0){		close(pfd[0]);		close(pfd[1]);		return 0;	}	rv->fp = &rv->bb;	rv->fd = pfd[0];		return rv;} /* make a stream from a child process */extern stream *outstream(void){	stream *rv;	int pfd[2]; 	if ((rv = (stream *)malloc(sizeof(stream))) == 0)		return 0;	memset(rv, 0, sizeof(stream));	if (pipe(pfd) < 0)		return 0;	if (Binit(&rv->bb, pfd[0], OREAD) < 0){		close(pfd[0]);		close(pfd[1]);		return 0;	}	rv->fp = &rv->bb;	rv->fd = pfd[1];	return rv;} extern voidstream_free(stream *sp){	int fd; 	close(sp->fd);	fd = Bfildes(sp->fp);	Bterm(sp->fp);	close(fd);	free((char *)sp);} /* start a new process */extern process *noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who){	process *pp;	int i, n; 	if ((pp = (process *)malloc(sizeof(process))) == 0) {		if (inp != 0)			stream_free(inp);		if (outp != 0)			stream_free(outp);		if (errp != 0)			stream_free(errp);		return 0;	}	pp->std[0] = inp;	pp->std[1] = outp;	pp->std[2] = errp;	switch (pp->pid = fork()) {	case -1:		proc_free(pp);		return 0;	case 0:		if(newpg)			sysdetach();		for (i=0; i<3; i++)			if (pp->std[i] != 0){				close(Bfildes(pp->std[i]->fp));				while(pp->std[i]->fd < 3)					pp->std[i]->fd = dup(pp->std[i]->fd, -1);			}		for (i=0; i<3; i++)			if (pp->std[i] != 0)				dup(pp->std[i]->fd, i);		for (n = sysfiles(); i < n; i++)			close(i);		if(who)			become(av, who);		exec(av[0], av);		perror("proc_start");		exits("proc_start");	default:		for (i=0; i<3; i++)			if (pp->std[i] != 0) {				close(pp->std[i]->fd);				pp->std[i]->fd = -1;			}		return pp;	}} /* start a new process under a shell */extern process *proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who){	char *av[4]; 	av[0] = SHELL;	av[1] = "-c";	av[2] = cmd;	av[3] = 0;	return noshell_proc_start(av, inp, outp, errp, newpg, who);} /* wait for a process to stop */extern intproc_wait(process *pp){	Waitmsg *status;	char err[Errlen]; 	for(;;){		status = wait();		if(status == nil){			rerrstr(err, sizeof(err));			if(strstr(err, "interrupt") == 0)				break;		}		if (status->pid==pp->pid)			break;	}	pp->pid = -1;	if(status == nil)		pp->status = -1;	else		pp->status = status->msg[0];	pp->waitmsg = status;	return pp->status;} /* free a process */extern intproc_free(process *pp){	int i; 	if(pp->std[1] == pp->std[2])		pp->std[2] = 0;		/* avoid freeing it twice */	for (i = 0; i < 3; i++)		if (pp->std[i])			stream_free(pp->std[i]);	if (pp->pid >= 0)		proc_wait(pp);	free(pp->waitmsg);	free((char *)pp);	return 0;} /* kill a process */extern intproc_kill(process *pp){	return syskill(pp->pid);}