| #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) |
| fprint(2, "warning: cannot run %s as %s\n", av[0], 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]; |
| |
| upasconfig(); |
| 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){ |
| 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((char *)pp); |
| return 0; |
| } |
| |
| /* kill a process */ |
| extern int |
| proc_kill(process *pp) |
| { |
| return syskill(pp->pid); |
| } |