1 1544f909 2004-12-25 devnull #include "u.h"
2 1544f909 2004-12-25 devnull #include <errno.h>
3 1544f909 2004-12-25 devnull #include "libc.h"
4 1544f909 2004-12-25 devnull #include "thread.h"
5 1544f909 2004-12-25 devnull #include "threadimpl.h"
7 1544f909 2004-12-25 devnull static Lock thewaitlock;
8 1544f909 2004-12-25 devnull static Channel *thewaitchan;
10 1544f909 2004-12-25 devnull static void
11 8cbd854a 2004-12-27 devnull execproc(void *v)
14 1544f909 2004-12-25 devnull Channel *c;
15 8cbd854a 2004-12-27 devnull Execjob *e;
16 1544f909 2004-12-25 devnull Waitmsg *w;
19 8cbd854a 2004-12-27 devnull pid = _threadspawn(e->fd, e->cmd, e->argv);
20 8cbd854a 2004-12-27 devnull sendul(e->c, pid);
21 8cbd854a 2004-12-27 devnull if(pid > 0){
22 8cbd854a 2004-12-27 devnull w = waitfor(pid);
23 1544f909 2004-12-25 devnull if((c = thewaitchan) != nil)
24 1544f909 2004-12-25 devnull sendp(c, w);
28 8cbd854a 2004-12-27 devnull threadexits(nil);
32 8cbd854a 2004-12-27 devnull _runthreadspawn(int *fd, char *cmd, char **argv)
35 8cbd854a 2004-12-27 devnull Execjob e;
37 8cbd854a 2004-12-27 devnull e.fd = fd;
38 8cbd854a 2004-12-27 devnull e.cmd = cmd;
39 8cbd854a 2004-12-27 devnull e.argv = argv;
40 8cbd854a 2004-12-27 devnull e.c = chancreate(sizeof(void*), 0);
41 8cbd854a 2004-12-27 devnull proccreate(execproc, &e, 65536);
42 8cbd854a 2004-12-27 devnull pid = recvul(e.c);
43 8cbd854a 2004-12-27 devnull chanfree(e.c);
44 8cbd854a 2004-12-27 devnull return pid;
48 1544f909 2004-12-25 devnull threadwaitchan(void)
50 1544f909 2004-12-25 devnull if(thewaitchan)
51 1544f909 2004-12-25 devnull return thewaitchan;
52 1544f909 2004-12-25 devnull lock(&thewaitlock);
53 1544f909 2004-12-25 devnull if(thewaitchan){
54 1544f909 2004-12-25 devnull unlock(&thewaitlock);
55 1544f909 2004-12-25 devnull return thewaitchan;
57 1544f909 2004-12-25 devnull thewaitchan = chancreate(sizeof(Waitmsg*), 4);
58 1544f909 2004-12-25 devnull chansetname(thewaitchan, "threadwaitchan");
59 1544f909 2004-12-25 devnull unlock(&thewaitlock);
60 1544f909 2004-12-25 devnull return thewaitchan;
64 e127e40b 2004-12-27 devnull _threadspawn(int fd[3], char *cmd, char *argv[])
66 1544f909 2004-12-25 devnull int i, n, p[2], pid;
67 1544f909 2004-12-25 devnull char exitstr[100];
69 1544f909 2004-12-25 devnull if(pipe(p) < 0)
70 1544f909 2004-12-25 devnull return -1;
71 1544f909 2004-12-25 devnull if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0){
72 1544f909 2004-12-25 devnull close(p[0]);
73 1544f909 2004-12-25 devnull close(p[1]);
74 1544f909 2004-12-25 devnull return -1;
76 1544f909 2004-12-25 devnull switch(pid = fork()){
78 1544f909 2004-12-25 devnull close(p[0]);
79 1544f909 2004-12-25 devnull close(p[1]);
80 1544f909 2004-12-25 devnull return -1;
82 1544f909 2004-12-25 devnull dup2(fd[0], 0);
83 1544f909 2004-12-25 devnull dup2(fd[1], 1);
84 1544f909 2004-12-25 devnull dup2(fd[2], 2);
85 1544f909 2004-12-25 devnull for(i=3; i<100; i++)
86 1544f909 2004-12-25 devnull if(i != p[1])
87 1544f909 2004-12-25 devnull close(i);
88 1544f909 2004-12-25 devnull execvp(cmd, argv);
89 1544f909 2004-12-25 devnull fprint(p[1], "%d", errno);
90 1544f909 2004-12-25 devnull close(p[1]);
91 1544f909 2004-12-25 devnull _exit(0);
94 1544f909 2004-12-25 devnull close(p[1]);
95 1544f909 2004-12-25 devnull n = read(p[0], exitstr, sizeof exitstr-1);
96 1544f909 2004-12-25 devnull close(p[0]);
97 1544f909 2004-12-25 devnull if(n > 0){ /* exec failed */
98 1544f909 2004-12-25 devnull exitstr[n] = 0;
99 1544f909 2004-12-25 devnull errno = atoi(exitstr);
100 1544f909 2004-12-25 devnull return -1;
103 1544f909 2004-12-25 devnull close(fd[0]);
104 1544f909 2004-12-25 devnull if(fd[1] != fd[0])
105 1544f909 2004-12-25 devnull close(fd[1]);
106 1544f909 2004-12-25 devnull if(fd[2] != fd[1] && fd[2] != fd[0])
107 1544f909 2004-12-25 devnull close(fd[2]);
108 1544f909 2004-12-25 devnull return pid;
112 e127e40b 2004-12-27 devnull threadspawn(int fd[3], char *cmd, char *argv[])
114 e127e40b 2004-12-27 devnull return _runthreadspawn(fd, cmd, argv);
118 1544f909 2004-12-25 devnull _threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
120 1544f909 2004-12-25 devnull int pid;
122 1544f909 2004-12-25 devnull pid = threadspawn(fd, cmd, argv);
123 1544f909 2004-12-25 devnull if(cpid){
124 1544f909 2004-12-25 devnull if(pid < 0)
125 1544f909 2004-12-25 devnull chansendul(cpid, ~0);
127 1544f909 2004-12-25 devnull chansendul(cpid, pid);
129 1544f909 2004-12-25 devnull return pid;
133 1544f909 2004-12-25 devnull threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
135 1544f909 2004-12-25 devnull if(_threadexec(cpid, fd, cmd, argv) >= 0)
136 1544f909 2004-12-25 devnull threadexits("threadexec");
140 1544f909 2004-12-25 devnull threadexecl(Channel *cpid, int fd[3], char *cmd, ...)
142 1544f909 2004-12-25 devnull char **argv, *s;
143 1544f909 2004-12-25 devnull int n, pid;
144 1544f909 2004-12-25 devnull va_list arg;
146 1544f909 2004-12-25 devnull va_start(arg, cmd);
147 1544f909 2004-12-25 devnull for(n=0; va_arg(arg, char*) != nil; n++)
150 1544f909 2004-12-25 devnull va_end(arg);
152 1544f909 2004-12-25 devnull argv = malloc(n*sizeof(argv[0]));
153 1544f909 2004-12-25 devnull if(argv == nil){
154 1544f909 2004-12-25 devnull if(cpid)
155 1544f909 2004-12-25 devnull chansendul(cpid, ~0);
159 1544f909 2004-12-25 devnull va_start(arg, cmd);
160 1544f909 2004-12-25 devnull for(n=0; (s=va_arg(arg, char*)) != nil; n++)
161 1544f909 2004-12-25 devnull argv[n] = s;
162 1544f909 2004-12-25 devnull argv[n] = 0;
163 1544f909 2004-12-25 devnull va_end(arg);
165 1544f909 2004-12-25 devnull pid = _threadexec(cpid, fd, cmd, argv);
166 1544f909 2004-12-25 devnull free(argv);
168 1544f909 2004-12-25 devnull if(pid >= 0)
169 1544f909 2004-12-25 devnull threadexits("threadexecl");