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