173 lines
2.9 KiB
C
173 lines
2.9 KiB
C
#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);
|
|
sysfatal("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[ERRMAX];
|
|
|
|
for(;;){
|
|
status = wait();
|
|
if(status == nil){
|
|
errstr(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(pp);
|
|
return 0;
|
|
}
|
|
|
|
/* kill a process */
|
|
//extern int
|
|
//proc_kill(process *pp)
|
|
//{
|
|
// return syskill(pp->pid);
|
|
//}
|