#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); }