Blob


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