diff options
| author | rsc <devnull@localhost> | 2005-10-29 16:26:44 +0000 |
|---|---|---|
| committer | rsc <devnull@localhost> | 2005-10-29 16:26:44 +0000 |
| commit | 5cdb17983ae6e6367ad7a940cb219eab247a9304 (patch) | |
| tree | 8ca1ef49af2a96e7daebe624d91fdf679814a057 /src/cmd/upas/common/process.c | |
| parent | cd3745196389579fb78b9b01ef1daefb5a57aa71 (diff) | |
| download | plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.tar.gz plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.zip | |
Thanks to John Cummings.
Diffstat (limited to 'src/cmd/upas/common/process.c')
| -rw-r--r-- | src/cmd/upas/common/process.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/cmd/upas/common/process.c b/src/cmd/upas/common/process.c new file mode 100644 index 00000000..16b21aef --- /dev/null +++ b/src/cmd/upas/common/process.c @@ -0,0 +1,175 @@ +#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,"process.c: trying to become(%s,%s)\n",av,who); + // jpc 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] = unsharp(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); +} |
