diff options
author | rsc <devnull@localhost> | 2003-09-30 17:47:42 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-09-30 17:47:42 +0000 |
commit | 76193d7cb0457807b2f0b95f909ab5de19480cd7 (patch) | |
tree | 97e538c7e38181431e90289a0fe8b6b7ce1f8f3c /src/libthread/exec.c | |
parent | ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad (diff) | |
download | plan9port-76193d7cb0457807b2f0b95f909ab5de19480cd7.tar.gz plan9port-76193d7cb0457807b2f0b95f909ab5de19480cd7.tar.bz2 plan9port-76193d7cb0457807b2f0b95f909ab5de19480cd7.zip |
Initial revision
Diffstat (limited to 'src/libthread/exec.c')
-rw-r--r-- | src/libthread/exec.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/libthread/exec.c b/src/libthread/exec.c new file mode 100644 index 00000000..bcf20802 --- /dev/null +++ b/src/libthread/exec.c @@ -0,0 +1,77 @@ +#include "threadimpl.h" + +#define PIPEMNT "/mnt/temp" + +void +procexec(Channel *pidc, char *prog, char *args[]) +{ + int n; + Proc *p; + Thread *t; + + _threaddebug(DBGEXEC, "procexec %s", prog); + /* must be only thread in proc */ + p = _threadgetproc(); + t = p->thread; + if(p->threads.head != t || p->threads.head->nextt != nil){ + werrstr("not only thread in proc"); + Bad: + if(pidc) + sendul(pidc, ~0); + return; + } + + /* + * We want procexec to behave like exec; if exec succeeds, + * never return, and if it fails, return with errstr set. + * Unfortunately, the exec happens in another proc since + * we have to wait for the exec'ed process to finish. + * To provide the semantics, we open a pipe with the + * write end close-on-exec and hand it to the proc that + * is doing the exec. If the exec succeeds, the pipe will + * close so that our read below fails. If the exec fails, + * then the proc doing the exec sends the errstr down the + * pipe to us. + */ + if(bind("#|", PIPEMNT, MREPL) < 0) + goto Bad; + if((p->exec.fd[0] = open(PIPEMNT "/data", OREAD)) < 0){ + unmount(nil, PIPEMNT); + goto Bad; + } + if((p->exec.fd[1] = open(PIPEMNT "/data1", OWRITE|OCEXEC)) < 0){ + close(p->exec.fd[0]); + unmount(nil, PIPEMNT); + goto Bad; + } + unmount(nil, PIPEMNT); + + /* exec in parallel via the scheduler */ + assert(p->needexec==0); + p->exec.prog = prog; + p->exec.args = args; + p->needexec = 1; + _sched(); + + close(p->exec.fd[1]); + if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */ + p->exitstr[n] = '\0'; + errstr(p->exitstr, ERRMAX); + close(p->exec.fd[0]); + goto Bad; + } + close(p->exec.fd[0]); + + if(pidc) + sendul(pidc, t->ret); + + /* wait for exec'ed program, then exit */ + _schedexecwait(); +} + +void +procexecl(Channel *pidc, char *f, ...) +{ + procexec(pidc, f, &f+1); +} + |