]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/exec.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / libthread / exec.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5
6 #define PIPEMNT "/mnt/temp"
7
8 void
9 procexec(Channel *pidc, char *prog, char *args[])
10 {
11         int n;
12         Proc *p;
13         Thread *t;
14
15         _threaddebug(DBGEXEC, "procexec %s", prog);
16         /* must be only thread in proc */
17         p = _threadgetproc();
18         t = p->thread;
19         if(p->threads.head != t || p->threads.head->nextt != nil){
20                 werrstr("not only thread in proc");
21         Bad:
22                 if(pidc)
23                         sendul(pidc, ~0);
24                 return;
25         }
26
27         /*
28          * We want procexec to behave like exec; if exec succeeds,
29          * never return, and if it fails, return with errstr set.
30          * Unfortunately, the exec happens in another proc since
31          * we have to wait for the exec'ed process to finish.
32          * To provide the semantics, we open a pipe with the 
33          * write end close-on-exec and hand it to the proc that
34          * is doing the exec.  If the exec succeeds, the pipe will
35          * close so that our read below fails.  If the exec fails,
36          * then the proc doing the exec sends the errstr down the
37          * pipe to us.
38          */
39         if(bind("#|", PIPEMNT, MREPL) < 0)
40                 goto Bad;
41         if((p->exec.fd[0] = open(PIPEMNT "/data", OREAD)) < 0){
42                 unmount(nil, PIPEMNT);
43                 goto Bad;
44         }
45         if((p->exec.fd[1] = open(PIPEMNT "/data1", OWRITE|OCEXEC)) < 0){
46                 close(p->exec.fd[0]);
47                 unmount(nil, PIPEMNT);
48                 goto Bad;
49         }
50         unmount(nil, PIPEMNT);
51
52         /* exec in parallel via the scheduler */
53         assert(p->needexec==0);
54         p->exec.prog = prog;
55         p->exec.args = args;
56         p->needexec = 1;
57         _sched();
58
59         close(p->exec.fd[1]);
60         if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){        /* exec failed */
61                 p->exitstr[n] = '\0';
62                 errstr(p->exitstr, ERRMAX);
63                 close(p->exec.fd[0]);
64                 goto Bad;
65         }
66         close(p->exec.fd[0]);
67
68         if(pidc)
69                 sendul(pidc, t->ret);
70
71         /* wait for exec'ed program, then exit */
72         _schedexecwait();
73 }
74
75 void
76 procexecl(Channel *pidc, char *f, ...)
77 {
78         procexec(pidc, f, &f+1);
79 }
80