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 5a8e63b2 2004-02-29 devnull static void efork(int[3], int[2], char*, char**);
6 76193d7c 2003-09-30 devnull void
7 5a8e63b2 2004-02-29 devnull threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
8 76193d7c 2003-09-30 devnull {
9 5a8e63b2 2004-02-29 devnull int pfd[2];
10 5a8e63b2 2004-02-29 devnull int n, pid;
11 5a8e63b2 2004-02-29 devnull char exitstr[ERRMAX];
12 76193d7c 2003-09-30 devnull
13 5a8e63b2 2004-02-29 devnull _threaddebug(DBGEXEC, "threadexec %s", prog);
14 5a8e63b2 2004-02-29 devnull
15 76193d7c 2003-09-30 devnull /*
16 5a8e63b2 2004-02-29 devnull * We want threadexec to behave like exec; if exec succeeds,
17 76193d7c 2003-09-30 devnull * never return, and if it fails, return with errstr set.
18 76193d7c 2003-09-30 devnull * Unfortunately, the exec happens in another proc since
19 76193d7c 2003-09-30 devnull * we have to wait for the exec'ed process to finish.
20 76193d7c 2003-09-30 devnull * To provide the semantics, we open a pipe with the
21 76193d7c 2003-09-30 devnull * write end close-on-exec and hand it to the proc that
22 76193d7c 2003-09-30 devnull * is doing the exec. If the exec succeeds, the pipe will
23 76193d7c 2003-09-30 devnull * close so that our read below fails. If the exec fails,
24 76193d7c 2003-09-30 devnull * then the proc doing the exec sends the errstr down the
25 76193d7c 2003-09-30 devnull * pipe to us.
26 76193d7c 2003-09-30 devnull */
27 5a8e63b2 2004-02-29 devnull if(pipe(pfd) < 0)
28 76193d7c 2003-09-30 devnull goto Bad;
29 5a8e63b2 2004-02-29 devnull if(fcntl(pfd[0], F_SETFD, 1) < 0)
30 912fba95 2003-11-24 devnull goto Bad;
31 5a8e63b2 2004-02-29 devnull if(fcntl(pfd[1], F_SETFD, 1) < 0)
32 76193d7c 2003-09-30 devnull goto Bad;
33 76193d7c 2003-09-30 devnull
34 5a8e63b2 2004-02-29 devnull switch(pid = fork()){
35 5a8e63b2 2004-02-29 devnull case -1:
36 5a8e63b2 2004-02-29 devnull close(pfd[0]);
37 5a8e63b2 2004-02-29 devnull close(pfd[1]);
38 5a8e63b2 2004-02-29 devnull goto Bad;
39 5a8e63b2 2004-02-29 devnull case 0:
40 5a8e63b2 2004-02-29 devnull efork(fd, pfd, prog, args);
41 5a8e63b2 2004-02-29 devnull _exit(0);
42 5a8e63b2 2004-02-29 devnull default:
43 5a8e63b2 2004-02-29 devnull break;
44 5a8e63b2 2004-02-29 devnull }
45 76193d7c 2003-09-30 devnull
46 5a8e63b2 2004-02-29 devnull close(pfd[1]);
47 5a8e63b2 2004-02-29 devnull if((n = read(pfd[0], exitstr, ERRMAX-1)) > 0){ /* exec failed */
48 5a8e63b2 2004-02-29 devnull exitstr[n] = '\0';
49 5a8e63b2 2004-02-29 devnull errstr(exitstr, ERRMAX);
50 5a8e63b2 2004-02-29 devnull close(pfd[0]);
51 76193d7c 2003-09-30 devnull goto Bad;
52 76193d7c 2003-09-30 devnull }
53 5a8e63b2 2004-02-29 devnull close(pfd[0]);
54 32f69c36 2003-12-11 devnull close(fd[0]);
55 32f69c36 2003-12-11 devnull if(fd[1] != fd[0])
56 32f69c36 2003-12-11 devnull close(fd[1]);
57 32f69c36 2003-12-11 devnull if(fd[2] != fd[1] && fd[2] != fd[0])
58 32f69c36 2003-12-11 devnull close(fd[2]);
59 76193d7c 2003-09-30 devnull if(pidc)
60 5a8e63b2 2004-02-29 devnull sendul(pidc, pid);
61 76193d7c 2003-09-30 devnull
62 5a8e63b2 2004-02-29 devnull _threaddebug(DBGEXEC, "threadexec schedexecwait");
63 5a8e63b2 2004-02-29 devnull threadexits(0);
64 76193d7c 2003-09-30 devnull
65 5a8e63b2 2004-02-29 devnull Bad:
66 5a8e63b2 2004-02-29 devnull _threaddebug(DBGEXEC, "threadexec bad %r");
67 5a8e63b2 2004-02-29 devnull if(pidc)
68 5a8e63b2 2004-02-29 devnull sendul(pidc, ~0);
69 76193d7c 2003-09-30 devnull }
70 76193d7c 2003-09-30 devnull
71 76193d7c 2003-09-30 devnull void
72 5a8e63b2 2004-02-29 devnull threadexecl(Channel *pidc, int fd[3], char *f, ...)
73 76193d7c 2003-09-30 devnull {
74 5a8e63b2 2004-02-29 devnull threadexec(pidc, fd, f, &f+1);
75 76193d7c 2003-09-30 devnull }
76 76193d7c 2003-09-30 devnull
77 76193d7c 2003-09-30 devnull static void
78 5a8e63b2 2004-02-29 devnull efork(int stdfd[3], int fd[2], char *prog, char **args)
79 76193d7c 2003-09-30 devnull {
80 76193d7c 2003-09-30 devnull char buf[ERRMAX];
81 32f69c36 2003-12-11 devnull int i;
82 76193d7c 2003-09-30 devnull
83 5a8e63b2 2004-02-29 devnull _threaddebug(DBGEXEC, "_schedexec %s -- calling execv", prog);
84 5a8e63b2 2004-02-29 devnull dup(stdfd[0], 0);
85 5a8e63b2 2004-02-29 devnull dup(stdfd[1], 1);
86 5a8e63b2 2004-02-29 devnull dup(stdfd[2], 2);
87 32f69c36 2003-12-11 devnull for(i=3; i<40; i++)
88 5a8e63b2 2004-02-29 devnull if(i != fd[1])
89 32f69c36 2003-12-11 devnull close(i);
90 49588d5d 2003-12-17 devnull rfork(RFNOTEG);
91 5a8e63b2 2004-02-29 devnull execvp(prog, args);
92 76193d7c 2003-09-30 devnull _threaddebug(DBGEXEC, "_schedexec failed: %r");
93 76193d7c 2003-09-30 devnull rerrstr(buf, sizeof buf);
94 76193d7c 2003-09-30 devnull if(buf[0]=='\0')
95 76193d7c 2003-09-30 devnull strcpy(buf, "exec failed");
96 5a8e63b2 2004-02-29 devnull write(fd[1], buf, strlen(buf));
97 5a8e63b2 2004-02-29 devnull close(fd[1]);
98 76193d7c 2003-09-30 devnull _exits(buf);
99 76193d7c 2003-09-30 devnull }
100 76193d7c 2003-09-30 devnull