Blame


1 76193d7c 2003-09-30 devnull #include <fcntl.h>
2 76193d7c 2003-09-30 devnull #include <unistd.h>
3 76193d7c 2003-09-30 devnull #include "threadimpl.h"
4 76193d7c 2003-09-30 devnull
5 76193d7c 2003-09-30 devnull void
6 32f69c36 2003-12-11 devnull procexec(Channel *pidc, int fd[3], char *prog, char *args[])
7 76193d7c 2003-09-30 devnull {
8 76193d7c 2003-09-30 devnull int n;
9 76193d7c 2003-09-30 devnull Proc *p;
10 76193d7c 2003-09-30 devnull Thread *t;
11 76193d7c 2003-09-30 devnull
12 76193d7c 2003-09-30 devnull _threaddebug(DBGEXEC, "procexec %s", prog);
13 76193d7c 2003-09-30 devnull /* must be only thread in proc */
14 76193d7c 2003-09-30 devnull p = _threadgetproc();
15 76193d7c 2003-09-30 devnull t = p->thread;
16 76193d7c 2003-09-30 devnull if(p->threads.head != t || p->threads.head->nextt != nil){
17 76193d7c 2003-09-30 devnull werrstr("not only thread in proc");
18 76193d7c 2003-09-30 devnull Bad:
19 912fba95 2003-11-24 devnull _threaddebug(DBGEXEC, "procexec bad %r");
20 76193d7c 2003-09-30 devnull if(pidc)
21 76193d7c 2003-09-30 devnull sendul(pidc, ~0);
22 76193d7c 2003-09-30 devnull return;
23 76193d7c 2003-09-30 devnull }
24 76193d7c 2003-09-30 devnull
25 76193d7c 2003-09-30 devnull /*
26 76193d7c 2003-09-30 devnull * We want procexec to behave like exec; if exec succeeds,
27 76193d7c 2003-09-30 devnull * never return, and if it fails, return with errstr set.
28 76193d7c 2003-09-30 devnull * Unfortunately, the exec happens in another proc since
29 76193d7c 2003-09-30 devnull * we have to wait for the exec'ed process to finish.
30 76193d7c 2003-09-30 devnull * To provide the semantics, we open a pipe with the
31 76193d7c 2003-09-30 devnull * write end close-on-exec and hand it to the proc that
32 76193d7c 2003-09-30 devnull * is doing the exec. If the exec succeeds, the pipe will
33 76193d7c 2003-09-30 devnull * close so that our read below fails. If the exec fails,
34 76193d7c 2003-09-30 devnull * then the proc doing the exec sends the errstr down the
35 76193d7c 2003-09-30 devnull * pipe to us.
36 76193d7c 2003-09-30 devnull */
37 76193d7c 2003-09-30 devnull if(pipe(p->exec.fd) < 0)
38 76193d7c 2003-09-30 devnull goto Bad;
39 912fba95 2003-11-24 devnull if(fcntl(p->exec.fd[0], F_SETFD, 1) < 0)
40 912fba95 2003-11-24 devnull goto Bad;
41 76193d7c 2003-09-30 devnull if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0)
42 76193d7c 2003-09-30 devnull goto Bad;
43 76193d7c 2003-09-30 devnull
44 76193d7c 2003-09-30 devnull /* exec in parallel via the scheduler */
45 76193d7c 2003-09-30 devnull assert(p->needexec==0);
46 76193d7c 2003-09-30 devnull p->exec.prog = prog;
47 76193d7c 2003-09-30 devnull p->exec.args = args;
48 32f69c36 2003-12-11 devnull p->exec.stdfd = fd;
49 76193d7c 2003-09-30 devnull p->needexec = 1;
50 76193d7c 2003-09-30 devnull _sched();
51 76193d7c 2003-09-30 devnull
52 76193d7c 2003-09-30 devnull close(p->exec.fd[1]);
53 76193d7c 2003-09-30 devnull if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */
54 76193d7c 2003-09-30 devnull p->exitstr[n] = '\0';
55 76193d7c 2003-09-30 devnull errstr(p->exitstr, ERRMAX);
56 76193d7c 2003-09-30 devnull close(p->exec.fd[0]);
57 76193d7c 2003-09-30 devnull goto Bad;
58 76193d7c 2003-09-30 devnull }
59 76193d7c 2003-09-30 devnull close(p->exec.fd[0]);
60 32f69c36 2003-12-11 devnull close(fd[0]);
61 32f69c36 2003-12-11 devnull if(fd[1] != fd[0])
62 32f69c36 2003-12-11 devnull close(fd[1]);
63 32f69c36 2003-12-11 devnull if(fd[2] != fd[1] && fd[2] != fd[0])
64 32f69c36 2003-12-11 devnull close(fd[2]);
65 76193d7c 2003-09-30 devnull if(pidc)
66 76193d7c 2003-09-30 devnull sendul(pidc, t->ret);
67 76193d7c 2003-09-30 devnull
68 912fba95 2003-11-24 devnull _threaddebug(DBGEXEC, "procexec schedexecwait");
69 76193d7c 2003-09-30 devnull /* wait for exec'ed program, then exit */
70 76193d7c 2003-09-30 devnull _schedexecwait();
71 76193d7c 2003-09-30 devnull }
72 76193d7c 2003-09-30 devnull
73 76193d7c 2003-09-30 devnull void
74 32f69c36 2003-12-11 devnull procexecl(Channel *pidc, int fd[3], char *f, ...)
75 76193d7c 2003-09-30 devnull {
76 32f69c36 2003-12-11 devnull procexec(pidc, fd, f, &f+1);
77 76193d7c 2003-09-30 devnull }
78 76193d7c 2003-09-30 devnull
79 76193d7c 2003-09-30 devnull void
80 76193d7c 2003-09-30 devnull _schedexecwait(void)
81 76193d7c 2003-09-30 devnull {
82 76193d7c 2003-09-30 devnull int pid;
83 76193d7c 2003-09-30 devnull Channel *c;
84 76193d7c 2003-09-30 devnull Proc *p;
85 76193d7c 2003-09-30 devnull Thread *t;
86 76193d7c 2003-09-30 devnull Waitmsg *w;
87 76193d7c 2003-09-30 devnull
88 76193d7c 2003-09-30 devnull p = _threadgetproc();
89 76193d7c 2003-09-30 devnull t = p->thread;
90 76193d7c 2003-09-30 devnull pid = t->ret;
91 76193d7c 2003-09-30 devnull _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret);
92 76193d7c 2003-09-30 devnull
93 76193d7c 2003-09-30 devnull for(;;){
94 76193d7c 2003-09-30 devnull w = wait();
95 76193d7c 2003-09-30 devnull if(w == nil)
96 76193d7c 2003-09-30 devnull break;
97 76193d7c 2003-09-30 devnull if(w->pid == pid)
98 76193d7c 2003-09-30 devnull break;
99 76193d7c 2003-09-30 devnull free(w);
100 76193d7c 2003-09-30 devnull }
101 76193d7c 2003-09-30 devnull if(w != nil){
102 76193d7c 2003-09-30 devnull if((c = _threadwaitchan) != nil)
103 76193d7c 2003-09-30 devnull sendp(c, w);
104 76193d7c 2003-09-30 devnull else
105 76193d7c 2003-09-30 devnull free(w);
106 76193d7c 2003-09-30 devnull }
107 76193d7c 2003-09-30 devnull threadexits("procexec");
108 76193d7c 2003-09-30 devnull }
109 76193d7c 2003-09-30 devnull
110 76193d7c 2003-09-30 devnull static void
111 76193d7c 2003-09-30 devnull efork(void *ve)
112 76193d7c 2003-09-30 devnull {
113 76193d7c 2003-09-30 devnull char buf[ERRMAX];
114 76193d7c 2003-09-30 devnull Execargs *e;
115 32f69c36 2003-12-11 devnull int i;
116 76193d7c 2003-09-30 devnull
117 76193d7c 2003-09-30 devnull e = ve;
118 912fba95 2003-11-24 devnull _threaddebug(DBGEXEC, "_schedexec %s -- calling execv", e->prog);
119 32f69c36 2003-12-11 devnull dup(e->stdfd[0], 0);
120 32f69c36 2003-12-11 devnull dup(e->stdfd[1], 1);
121 32f69c36 2003-12-11 devnull dup(e->stdfd[2], 2);
122 32f69c36 2003-12-11 devnull for(i=3; i<40; i++)
123 32f69c36 2003-12-11 devnull if(i != e->fd[1])
124 32f69c36 2003-12-11 devnull close(i);
125 32f69c36 2003-12-11 devnull execvp(e->prog, e->args);
126 76193d7c 2003-09-30 devnull _threaddebug(DBGEXEC, "_schedexec failed: %r");
127 76193d7c 2003-09-30 devnull rerrstr(buf, sizeof buf);
128 76193d7c 2003-09-30 devnull if(buf[0]=='\0')
129 76193d7c 2003-09-30 devnull strcpy(buf, "exec failed");
130 76193d7c 2003-09-30 devnull write(e->fd[1], buf, strlen(buf));
131 76193d7c 2003-09-30 devnull close(e->fd[1]);
132 76193d7c 2003-09-30 devnull _exits(buf);
133 76193d7c 2003-09-30 devnull }
134 76193d7c 2003-09-30 devnull
135 76193d7c 2003-09-30 devnull int
136 76193d7c 2003-09-30 devnull _schedexec(Execargs *e)
137 76193d7c 2003-09-30 devnull {
138 912fba95 2003-11-24 devnull int pid;
139 912fba95 2003-11-24 devnull
140 912fba95 2003-11-24 devnull pid = fork();
141 912fba95 2003-11-24 devnull if(pid == 0){
142 912fba95 2003-11-24 devnull efork(e);
143 912fba95 2003-11-24 devnull _exit(1);
144 912fba95 2003-11-24 devnull }
145 912fba95 2003-11-24 devnull return pid;
146 76193d7c 2003-09-30 devnull }