#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 void
stream_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 int
proc_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 int
proc_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 int
proc_kill(process *pp)
{
return syskill(pp->pid);
}
|