Sun Jan 9 10:28:46 2011 UTC ()
dprintf to stderr.  stop doing it if stderr_fileno gets dup2()'d


(pooka)
diff -r1.4 -r1.5 src/lib/librumphijack/hijack.c

cvs diff -r1.4 -r1.5 src/lib/librumphijack/hijack.c (switch to unified diff)

--- src/lib/librumphijack/hijack.c 2011/01/08 21:30:24 1.4
+++ src/lib/librumphijack/hijack.c 2011/01/09 10:28:46 1.5
@@ -1,903 +1,916 @@ @@ -1,903 +1,916 @@
1/* $NetBSD: hijack.c,v 1.4 2011/01/08 21:30:24 pooka Exp $ */ 1/* $NetBSD: hijack.c,v 1.5 2011/01/09 10:28:46 pooka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2011 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__RCSID("$NetBSD: hijack.c,v 1.4 2011/01/08 21:30:24 pooka Exp $"); 29__RCSID("$NetBSD: hijack.c,v 1.5 2011/01/09 10:28:46 pooka Exp $");
30 30
31#include <sys/param.h> 31#include <sys/param.h>
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/ioctl.h> 33#include <sys/ioctl.h>
34#include <sys/socket.h> 34#include <sys/socket.h>
35#include <sys/poll.h> 35#include <sys/poll.h>
36 36
37#include <rump/rump.h> 37#include <rump/rump.h>
38#include <rump/rumpclient.h> 38#include <rump/rumpclient.h>
39#include <rump/rump_syscalls.h> 39#include <rump/rump_syscalls.h>
40 40
41#include <assert.h> 41#include <assert.h>
42#include <dlfcn.h> 42#include <dlfcn.h>
43#include <err.h> 43#include <err.h>
44#include <errno.h> 44#include <errno.h>
45#include <fcntl.h> 45#include <fcntl.h>
46#include <poll.h> 46#include <poll.h>
47#include <pthread.h> 47#include <pthread.h>
48#include <signal.h> 48#include <signal.h>
49#include <stdarg.h> 49#include <stdarg.h>
50#include <stdio.h> 50#include <stdio.h>
51#include <stdlib.h> 51#include <stdlib.h>
52#include <time.h> 52#include <time.h>
53#include <unistd.h> 53#include <unistd.h>
54 54
55enum { RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT, 55enum { RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT,
56 RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN, 56 RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN,
57 RUMPCALL_RECVFROM, RUMPCALL_RECVMSG, 57 RUMPCALL_RECVFROM, RUMPCALL_RECVMSG,
58 RUMPCALL_SENDTO, RUMPCALL_SENDMSG, 58 RUMPCALL_SENDTO, RUMPCALL_SENDMSG,
59 RUMPCALL_GETSOCKOPT, RUMPCALL_SETSOCKOPT, 59 RUMPCALL_GETSOCKOPT, RUMPCALL_SETSOCKOPT,
60 RUMPCALL_SHUTDOWN, 60 RUMPCALL_SHUTDOWN,
61 RUMPCALL_READ, RUMPCALL_READV, 61 RUMPCALL_READ, RUMPCALL_READV,
62 RUMPCALL_WRITE, RUMPCALL_WRITEV, 62 RUMPCALL_WRITE, RUMPCALL_WRITEV,
63 RUMPCALL_IOCTL, RUMPCALL_FCNTL, 63 RUMPCALL_IOCTL, RUMPCALL_FCNTL,
64 RUMPCALL_CLOSE, 64 RUMPCALL_CLOSE,
65 RUMPCALL_POLLTS, 65 RUMPCALL_POLLTS,
66 RUMPCALL__NUM 66 RUMPCALL__NUM
67}; 67};
68 68
69const char *sysnames[] = { 69const char *sysnames[] = {
70 "__socket30", 70 "__socket30",
71 "accept", 71 "accept",
72 "bind", 72 "bind",
73 "connect", 73 "connect",
74 "getpeername", 74 "getpeername",
75 "getsockname", 75 "getsockname",
76 "listen", 76 "listen",
77 "recvfrom", 77 "recvfrom",
78 "recvmsg", 78 "recvmsg",
79 "sendto", 79 "sendto",
80 "sendmsg", 80 "sendmsg",
81 "getsockopt", 81 "getsockopt",
82 "setsockopt", 82 "setsockopt",
83 "shutdown", 83 "shutdown",
84 "read", 84 "read",
85 "readv", 85 "readv",
86 "write", 86 "write",
87 "writev", 87 "writev",
88 "ioctl", 88 "ioctl",
89 "fcntl", 89 "fcntl",
90 "close", 90 "close",
91 "__pollts50", 91 "__pollts50",
92}; 92};
93 93
94static ssize_t (*host_read)(int, void *, size_t); 94static ssize_t (*host_read)(int, void *, size_t);
95static ssize_t (*host_readv)(int, const struct iovec *, int); 95static ssize_t (*host_readv)(int, const struct iovec *, int);
96static ssize_t (*host_write)(int, const void *, size_t); 96static ssize_t (*host_write)(int, const void *, size_t);
97static ssize_t (*host_writev)(int, const struct iovec *, int); 97static ssize_t (*host_writev)(int, const struct iovec *, int);
98static int (*host_ioctl)(int, unsigned long, ...); 98static int (*host_ioctl)(int, unsigned long, ...);
99static int (*host_fcntl)(int, int, ...); 99static int (*host_fcntl)(int, int, ...);
100static int (*host_close)(int); 100static int (*host_close)(int);
101static int (*host_pollts)(struct pollfd *, nfds_t, 101static int (*host_pollts)(struct pollfd *, nfds_t,
102 const struct timespec *, const sigset_t *); 102 const struct timespec *, const sigset_t *);
103static pid_t (*host_fork)(void); 103static pid_t (*host_fork)(void);
104static int (*host_dup2)(int, int); 104static int (*host_dup2)(int, int);
105 105
106static void *rumpcalls[RUMPCALL__NUM]; 106static void *rumpcalls[RUMPCALL__NUM];
107 107
108/* 108/*
109 * This is called from librumpclient in case of LD_PRELOAD. 109 * This is called from librumpclient in case of LD_PRELOAD.
110 * It ensures correct RTLD_NEXT. 110 * It ensures correct RTLD_NEXT.
111 */ 111 */
112static void * 112static void *
113hijackdlsym(void *handle, const char *symbol) 113hijackdlsym(void *handle, const char *symbol)
114{ 114{
115 115
116 return dlsym(handle, symbol); 116 return dlsym(handle, symbol);
117} 117}
118 118
119static void __attribute__((constructor)) 119static void __attribute__((constructor))
120rcinit(void) 120rcinit(void)
121{ 121{
122 int (*rumpcinit)(void); 122 int (*rumpcinit)(void);
123 void **rumpcdlsym; 123 void **rumpcdlsym;
124 void *hand; 124 void *hand;
125 int i; 125 int i;
126 126
127 hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL); 127 hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL);
128 if (!hand) 128 if (!hand)
129 err(1, "cannot open librumpclient.so"); 129 err(1, "cannot open librumpclient.so");
130 rumpcinit = dlsym(hand, "rumpclient_init"); 130 rumpcinit = dlsym(hand, "rumpclient_init");
131 _DIAGASSERT(rumpcinit); 131 _DIAGASSERT(rumpcinit);
132 132
133 rumpcdlsym = dlsym(hand, "rumpclient_dlsym"); 133 rumpcdlsym = dlsym(hand, "rumpclient_dlsym");
134 *rumpcdlsym = hijackdlsym; 134 *rumpcdlsym = hijackdlsym;
135 135
136 host_read = dlsym(RTLD_NEXT, "read"); 136 host_read = dlsym(RTLD_NEXT, "read");
137 host_readv = dlsym(RTLD_NEXT, "readv"); 137 host_readv = dlsym(RTLD_NEXT, "readv");
138 host_write = dlsym(RTLD_NEXT, "write"); 138 host_write = dlsym(RTLD_NEXT, "write");
139 host_writev = dlsym(RTLD_NEXT, "writev"); 139 host_writev = dlsym(RTLD_NEXT, "writev");
140 host_ioctl = dlsym(RTLD_NEXT, "ioctl"); 140 host_ioctl = dlsym(RTLD_NEXT, "ioctl");
141 host_fcntl = dlsym(RTLD_NEXT, "fcntl"); 141 host_fcntl = dlsym(RTLD_NEXT, "fcntl");
142 host_close = dlsym(RTLD_NEXT, "close"); 142 host_close = dlsym(RTLD_NEXT, "close");
143 host_pollts = dlsym(RTLD_NEXT, "pollts"); 143 host_pollts = dlsym(RTLD_NEXT, "pollts");
144 host_fork = dlsym(RTLD_NEXT, "fork"); 144 host_fork = dlsym(RTLD_NEXT, "fork");
145 host_dup2 = dlsym(RTLD_NEXT, "dup2"); 145 host_dup2 = dlsym(RTLD_NEXT, "dup2");
146 146
147 for (i = 0; i < RUMPCALL__NUM; i++) { 147 for (i = 0; i < RUMPCALL__NUM; i++) {
148 char sysname[128]; 148 char sysname[128];
149 149
150 snprintf(sysname, sizeof(sysname), "rump_sys_%s", sysnames[i]); 150 snprintf(sysname, sizeof(sysname), "rump_sys_%s", sysnames[i]);
151 rumpcalls[i] = dlsym(hand, sysname); 151 rumpcalls[i] = dlsym(hand, sysname);
152 if (!rumpcalls[i]) { 152 if (!rumpcalls[i]) {
153 fprintf(stderr, "cannot find symbol: %s\n", sysname); 153 fprintf(stderr, "cannot find symbol: %s\n", sysname);
154 exit(1); 154 exit(1);
155 } 155 }
156 } 156 }
157 157
158 if (rumpcinit() == -1) 158 if (rumpcinit() == -1)
159 err(1, "rumpclient init"); 159 err(1, "rumpclient init");
160} 160}
161 161
 162static unsigned dup2mask;
 163#define ISDUP2D(fd) (((fd+1) & dup2mask) == ((fd)+1))
 164
162//#define DEBUGJACK 165//#define DEBUGJACK
163#ifdef DEBUGJACK 166#ifdef DEBUGJACK
164#define DPRINTF(x) printf x 167#define DPRINTF(x) mydprintf x
 168static void
 169mydprintf(const char *fmt, ...)
 170{
 171 va_list ap;
 172
 173 if (ISDUP2D(STDERR_FILENO))
 174 return;
 175
 176 va_start(ap, fmt);
 177 vfprintf(stderr, fmt, ap);
 178 va_end(ap);
 179}
 180
165#else 181#else
166#define DPRINTF(x) 182#define DPRINTF(x)
167#endif 183#endif
168 184
169static unsigned dup2mask; 
170#define ISDUP2D(fd) (((fd+1) & dup2mask) == ((fd)+1)) 
171 
172/* XXX: need runtime selection. low for now due to FD_SETSIZE */ 185/* XXX: need runtime selection. low for now due to FD_SETSIZE */
173#define HIJACK_FDOFF 128 186#define HIJACK_FDOFF 128
174#define HIJACK_SELECT 128 /* XXX */ 187#define HIJACK_SELECT 128 /* XXX */
175#define HIJACK_ASSERT 128 /* XXX */ 188#define HIJACK_ASSERT 128 /* XXX */
176static int 189static int
177fd_rump2host(int fd) 190fd_rump2host(int fd)
178{ 191{
179 192
180 if (fd == -1) 193 if (fd == -1)
181 return fd; 194 return fd;
182 195
183 if (!ISDUP2D(fd)) 196 if (!ISDUP2D(fd))
184 fd += HIJACK_FDOFF; 197 fd += HIJACK_FDOFF;
185 198
186 return fd; 199 return fd;
187} 200}
188 201
189static int 202static int
190fd_host2rump(int fd) 203fd_host2rump(int fd)
191{ 204{
192 205
193 if (!ISDUP2D(fd)) 206 if (!ISDUP2D(fd))
194 fd -= HIJACK_FDOFF; 207 fd -= HIJACK_FDOFF;
195 return fd; 208 return fd;
196} 209}
197 210
198static bool 211static bool
199fd_isrump(int fd) 212fd_isrump(int fd)
200{ 213{
201 214
202 return ISDUP2D(fd) || fd >= HIJACK_FDOFF; 215 return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
203} 216}
204 217
205#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_ASSERT) 218#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_ASSERT)
206#undef HIJACK_FDOFF 219#undef HIJACK_FDOFF
207 220
208/* 221/*
209 * Following wrappers always call the rump kernel. 222 * Following wrappers always call the rump kernel.
210 */ 223 */
211 224
212int __socket30(int, int, int); 225int __socket30(int, int, int);
213int 226int
214__socket30(int domain, int type, int protocol) 227__socket30(int domain, int type, int protocol)
215{ 228{
216 int (*rc_socket)(int, int, int); 229 int (*rc_socket)(int, int, int);
217 int fd; 230 int fd;
218 231
219 rc_socket = rumpcalls[RUMPCALL_SOCKET]; 232 rc_socket = rumpcalls[RUMPCALL_SOCKET];
220 fd = rc_socket(domain, type, protocol); 233 fd = rc_socket(domain, type, protocol);
221 234
222 DPRINTF(("socket <- %d\n", fd_rump2host(fd))); 235 DPRINTF(("socket <- %d\n", fd_rump2host(fd)));
223 236
224 return fd_rump2host(fd); 237 return fd_rump2host(fd);
225} 238}
226 239
227int 240int
228accept(int s, struct sockaddr *addr, socklen_t *addrlen) 241accept(int s, struct sockaddr *addr, socklen_t *addrlen)
229{ 242{
230 int (*rc_accept)(int, struct sockaddr *, socklen_t *); 243 int (*rc_accept)(int, struct sockaddr *, socklen_t *);
231 int fd; 244 int fd;
232 245
233 DPRINTF(("accept -> %d", s)); 246 DPRINTF(("accept -> %d", s));
234 assertfd(s); 247 assertfd(s);
235 rc_accept = rumpcalls[RUMPCALL_ACCEPT]; 248 rc_accept = rumpcalls[RUMPCALL_ACCEPT];
236 fd = rc_accept(fd_host2rump(s), addr, addrlen); 249 fd = rc_accept(fd_host2rump(s), addr, addrlen);
237 DPRINTF((" <- %d\n", fd_rump2host(fd))); 250 DPRINTF((" <- %d\n", fd_rump2host(fd)));
238 251
239 return fd_rump2host(fd); 252 return fd_rump2host(fd);
240} 253}
241 254
242int 255int
243bind(int s, const struct sockaddr *name, socklen_t namelen) 256bind(int s, const struct sockaddr *name, socklen_t namelen)
244{ 257{
245 int (*rc_bind)(int, const struct sockaddr *, socklen_t); 258 int (*rc_bind)(int, const struct sockaddr *, socklen_t);
246 259
247 DPRINTF(("bind -> %d\n", s)); 260 DPRINTF(("bind -> %d\n", s));
248 assertfd(s); 261 assertfd(s);
249 rc_bind = rumpcalls[RUMPCALL_BIND]; 262 rc_bind = rumpcalls[RUMPCALL_BIND];
250 263
251 return rc_bind(fd_host2rump(s), name, namelen); 264 return rc_bind(fd_host2rump(s), name, namelen);
252} 265}
253 266
254int 267int
255connect(int s, const struct sockaddr *name, socklen_t namelen) 268connect(int s, const struct sockaddr *name, socklen_t namelen)
256{ 269{
257 int (*rc_connect)(int, const struct sockaddr *, socklen_t); 270 int (*rc_connect)(int, const struct sockaddr *, socklen_t);
258 271
259 DPRINTF(("connect -> %d\n", s)); 272 DPRINTF(("connect -> %d\n", s));
260 assertfd(s); 273 assertfd(s);
261 rc_connect = rumpcalls[RUMPCALL_CONNECT]; 274 rc_connect = rumpcalls[RUMPCALL_CONNECT];
262 275
263 return rc_connect(fd_host2rump(s), name, namelen); 276 return rc_connect(fd_host2rump(s), name, namelen);
264} 277}
265 278
266int 279int
267getpeername(int s, struct sockaddr *name, socklen_t *namelen) 280getpeername(int s, struct sockaddr *name, socklen_t *namelen)
268{ 281{
269 int (*rc_getpeername)(int, struct sockaddr *, socklen_t *); 282 int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
270 283
271 DPRINTF(("getpeername -> %d\n", s)); 284 DPRINTF(("getpeername -> %d\n", s));
272 assertfd(s); 285 assertfd(s);
273 rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME]; 286 rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
274 return rc_getpeername(fd_host2rump(s), name, namelen); 287 return rc_getpeername(fd_host2rump(s), name, namelen);
275} 288}
276 289
277int 290int
278getsockname(int s, struct sockaddr *name, socklen_t *namelen) 291getsockname(int s, struct sockaddr *name, socklen_t *namelen)
279{ 292{
280 int (*rc_getsockname)(int, struct sockaddr *, socklen_t *); 293 int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
281 294
282 DPRINTF(("getsockname -> %d\n", s)); 295 DPRINTF(("getsockname -> %d\n", s));
283 assertfd(s); 296 assertfd(s);
284 rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME]; 297 rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
285 return rc_getsockname(fd_host2rump(s), name, namelen); 298 return rc_getsockname(fd_host2rump(s), name, namelen);
286} 299}
287 300
288int 301int
289listen(int s, int backlog) 302listen(int s, int backlog)
290{ 303{
291 int (*rc_listen)(int, int); 304 int (*rc_listen)(int, int);
292 305
293 DPRINTF(("listen -> %d\n", s)); 306 DPRINTF(("listen -> %d\n", s));
294 assertfd(s); 307 assertfd(s);
295 rc_listen = rumpcalls[RUMPCALL_LISTEN]; 308 rc_listen = rumpcalls[RUMPCALL_LISTEN];
296 return rc_listen(fd_host2rump(s), backlog); 309 return rc_listen(fd_host2rump(s), backlog);
297} 310}
298 311
299ssize_t 312ssize_t
300recv(int s, void *buf, size_t len, int flags) 313recv(int s, void *buf, size_t len, int flags)
301{ 314{
302 315
303 return recvfrom(s, buf, len, flags, NULL, NULL); 316 return recvfrom(s, buf, len, flags, NULL, NULL);
304} 317}
305 318
306ssize_t 319ssize_t
307recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, 320recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
308 socklen_t *fromlen) 321 socklen_t *fromlen)
309{ 322{
310 int (*rc_recvfrom)(int, void *, size_t, int, 323 int (*rc_recvfrom)(int, void *, size_t, int,
311 struct sockaddr *, socklen_t *); 324 struct sockaddr *, socklen_t *);
312 325
313 DPRINTF(("recvfrom\n")); 326 DPRINTF(("recvfrom\n"));
314 assertfd(s); 327 assertfd(s);
315 rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM]; 328 rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM];
316 return rc_recvfrom(fd_host2rump(s), buf, len, flags, from, fromlen); 329 return rc_recvfrom(fd_host2rump(s), buf, len, flags, from, fromlen);
317} 330}
318 331
319ssize_t 332ssize_t
320recvmsg(int s, struct msghdr *msg, int flags) 333recvmsg(int s, struct msghdr *msg, int flags)
321{ 334{
322 int (*rc_recvmsg)(int, struct msghdr *, int); 335 int (*rc_recvmsg)(int, struct msghdr *, int);
323 336
324 DPRINTF(("recvmsg\n")); 337 DPRINTF(("recvmsg\n"));
325 assertfd(s); 338 assertfd(s);
326 rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG]; 339 rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG];
327 return rc_recvmsg(fd_host2rump(s), msg, flags); 340 return rc_recvmsg(fd_host2rump(s), msg, flags);
328} 341}
329 342
330ssize_t 343ssize_t
331send(int s, const void *buf, size_t len, int flags) 344send(int s, const void *buf, size_t len, int flags)
332{ 345{
333 346
334 return sendto(s, buf, len, flags, NULL, 0); 347 return sendto(s, buf, len, flags, NULL, 0);
335} 348}
336 349
337ssize_t 350ssize_t
338sendto(int s, const void *buf, size_t len, int flags, 351sendto(int s, const void *buf, size_t len, int flags,
339 const struct sockaddr *to, socklen_t tolen) 352 const struct sockaddr *to, socklen_t tolen)
340{ 353{
341 int (*rc_sendto)(int, const void *, size_t, int, 354 int (*rc_sendto)(int, const void *, size_t, int,
342 const struct sockaddr *, socklen_t); 355 const struct sockaddr *, socklen_t);
343 356
344 if (s == -1) 357 if (s == -1)
345 return len; 358 return len;
346 359
347 DPRINTF(("sendto\n")); 360 DPRINTF(("sendto\n"));
348 assertfd(s); 361 assertfd(s);
349 rc_sendto = rumpcalls[RUMPCALL_SENDTO]; 362 rc_sendto = rumpcalls[RUMPCALL_SENDTO];
350 return rc_sendto(fd_host2rump(s), buf, len, flags, to, tolen); 363 return rc_sendto(fd_host2rump(s), buf, len, flags, to, tolen);
351} 364}
352 365
353ssize_t 366ssize_t
354sendmsg(int s, const struct msghdr *msg, int flags) 367sendmsg(int s, const struct msghdr *msg, int flags)
355{ 368{
356 int (*rc_sendmsg)(int, const struct msghdr *, int); 369 int (*rc_sendmsg)(int, const struct msghdr *, int);
357 370
358 DPRINTF(("sendmsg\n")); 371 DPRINTF(("sendmsg\n"));
359 assertfd(s); 372 assertfd(s);
360 rc_sendmsg = rumpcalls[RUMPCALL_SENDTO]; 373 rc_sendmsg = rumpcalls[RUMPCALL_SENDTO];
361 return rc_sendmsg(fd_host2rump(s), msg, flags); 374 return rc_sendmsg(fd_host2rump(s), msg, flags);
362} 375}
363 376
364int 377int
365getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) 378getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
366{ 379{
367 int (*rc_getsockopt)(int, int, int, void *, socklen_t *); 380 int (*rc_getsockopt)(int, int, int, void *, socklen_t *);
368 381
369 DPRINTF(("getsockopt\n")); 382 DPRINTF(("getsockopt\n"));
370 assertfd(s); 383 assertfd(s);
371 rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT]; 384 rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
372 return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen); 385 return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen);
373} 386}
374 387
375int 388int
376setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) 389setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
377{ 390{
378 int (*rc_setsockopt)(int, int, int, const void *, socklen_t); 391 int (*rc_setsockopt)(int, int, int, const void *, socklen_t);
379 392
380 DPRINTF(("setsockopt\n")); 393 DPRINTF(("setsockopt\n"));
381 assertfd(s); 394 assertfd(s);
382 rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT]; 395 rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
383 return rc_setsockopt(fd_host2rump(s), level, optname, optval, optlen); 396 return rc_setsockopt(fd_host2rump(s), level, optname, optval, optlen);
384} 397}
385 398
386int 399int
387shutdown(int s, int how) 400shutdown(int s, int how)
388{ 401{
389 int (*rc_shutdown)(int, int); 402 int (*rc_shutdown)(int, int);
390 403
391 DPRINTF(("shutdown\n")); 404 DPRINTF(("shutdown\n"));
392 assertfd(s); 405 assertfd(s);
393 rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN]; 406 rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
394 return rc_shutdown(fd_host2rump(s), how); 407 return rc_shutdown(fd_host2rump(s), how);
395} 408}
396 409
397/* 410/*
398 * dup2 is special. we allow dup2 of a rump kernel fd to 0-2 since 411 * dup2 is special. we allow dup2 of a rump kernel fd to 0-2 since
399 * many programs do that. dup2 of a rump kernel fd to another value 412 * many programs do that. dup2 of a rump kernel fd to another value
400 * not >= fdoff is an error. 413 * not >= fdoff is an error.
401 * 414 *
402 * Note: cannot rump2host newd, because it is often hardcoded. 415 * Note: cannot rump2host newd, because it is often hardcoded.
403 * 416 *
404 * XXX: should disable debug prints after stdout/stderr are dup2'd 417 * XXX: should disable debug prints after stdout/stderr are dup2'd
405 */ 418 */
406int 419int
407dup2(int oldd, int newd) 420dup2(int oldd, int newd)
408{ 421{
409 int rv; 422 int rv;
410 423
411 DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd)); 424 DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
412 425
413 if (fd_isrump(oldd)) { 426 if (fd_isrump(oldd)) {
414 if (!(newd >= 0 && newd <= 2)) 427 if (!(newd >= 0 && newd <= 2))
415 return EBADF; 428 return EBADF;
416 oldd = fd_host2rump(oldd); 429 oldd = fd_host2rump(oldd);
417 rv = rump_sys_dup2(oldd, newd); 430 rv = rump_sys_dup2(oldd, newd);
418 if (rv != -1) 431 if (rv != -1)
419 dup2mask |= newd+1; 432 dup2mask |= newd+1;
420 return rv; 433 return rv;
421 } else { 434 } else {
422 return host_dup2(oldd, newd); 435 return host_dup2(oldd, newd);
423 } 436 }
424} 437}
425 438
426/* 439/*
427 * We just wrap fork the appropriate rump client calls to preserve 440 * We just wrap fork the appropriate rump client calls to preserve
428 * the file descriptors of the forked parent in the child, but 441 * the file descriptors of the forked parent in the child, but
429 * prevent double use of connection fd. 442 * prevent double use of connection fd.
430 */ 443 */
431 444
432pid_t 445pid_t
433fork() 446fork()
434{ 447{
435 struct rumpclient_fork *rf; 448 struct rumpclient_fork *rf;
436 pid_t rv; 449 pid_t rv;
437 450
438 DPRINTF(("fork\n")); 451 DPRINTF(("fork\n"));
439 452
440 if ((rf = rumpclient_prefork()) == NULL) 453 if ((rf = rumpclient_prefork()) == NULL)
441 return -1; 454 return -1;
442 455
443 switch ((rv = host_fork())) { 456 switch ((rv = host_fork())) {
444 case -1: 457 case -1:
445 /* XXX: cancel rf */ 458 /* XXX: cancel rf */
446 break; 459 break;
447 case 0: 460 case 0:
448 if (rumpclient_fork_init(rf) == -1) 461 if (rumpclient_fork_init(rf) == -1)
449 rv = -1; 462 rv = -1;
450 break; 463 break;
451 default: 464 default:
452 break; 465 break;
453 } 466 }
454 467
455 DPRINTF(("fork returns %d\n", rv)); 468 DPRINTF(("fork returns %d\n", rv));
456 return rv; 469 return rv;
457} 470}
458 471
459/* 472/*
460 * Hybrids 473 * Hybrids
461 */ 474 */
462 475
463ssize_t 476ssize_t
464read(int fd, void *buf, size_t len) 477read(int fd, void *buf, size_t len)
465{ 478{
466 int (*op_read)(int, void *, size_t); 479 int (*op_read)(int, void *, size_t);
467 ssize_t n; 480 ssize_t n;
468 481
469 DPRINTF(("read %d\n", fd)); 482 DPRINTF(("read %d\n", fd));
470 if (fd_isrump(fd)) { 483 if (fd_isrump(fd)) {
471 fd = fd_host2rump(fd); 484 fd = fd_host2rump(fd);
472 op_read = rumpcalls[RUMPCALL_READ]; 485 op_read = rumpcalls[RUMPCALL_READ];
473 } else { 486 } else {
474 op_read = host_read; 487 op_read = host_read;
475 } 488 }
476 489
477 n = op_read(fd, buf, len); 490 n = op_read(fd, buf, len);
478 return n; 491 return n;
479} 492}
480 493
481ssize_t 494ssize_t
482readv(int fd, const struct iovec *iov, int iovcnt) 495readv(int fd, const struct iovec *iov, int iovcnt)
483{ 496{
484 int (*op_readv)(int, const struct iovec *, int); 497 int (*op_readv)(int, const struct iovec *, int);
485 498
486 if (fd_isrump(fd)) { 499 if (fd_isrump(fd)) {
487 fd = fd_host2rump(fd); 500 fd = fd_host2rump(fd);
488 op_readv = rumpcalls[RUMPCALL_READV]; 501 op_readv = rumpcalls[RUMPCALL_READV];
489 } else { 502 } else {
490 op_readv = host_readv; 503 op_readv = host_readv;
491 } 504 }
492 505
493 DPRINTF(("readv\n")); 506 DPRINTF(("readv\n"));
494 return op_readv(fd, iov, iovcnt); 507 return op_readv(fd, iov, iovcnt);
495} 508}
496 509
497ssize_t 510ssize_t
498write(int fd, const void *buf, size_t len) 511write(int fd, const void *buf, size_t len)
499{ 512{
500 int (*op_write)(int, const void *, size_t); 513 int (*op_write)(int, const void *, size_t);
501 514
502 if (fd_isrump(fd)) { 515 if (fd_isrump(fd)) {
503 fd = fd_host2rump(fd); 516 fd = fd_host2rump(fd);
504 op_write = rumpcalls[RUMPCALL_WRITE]; 517 op_write = rumpcalls[RUMPCALL_WRITE];
505 } else { 518 } else {
506 op_write = host_write; 519 op_write = host_write;
507 } 520 }
508 521
509 return op_write(fd, buf, len); 522 return op_write(fd, buf, len);
510} 523}
511 524
512ssize_t 525ssize_t
513writev(int fd, const struct iovec *iov, int iovcnt) 526writev(int fd, const struct iovec *iov, int iovcnt)
514{ 527{
515 int (*op_writev)(int, const struct iovec *, int); 528 int (*op_writev)(int, const struct iovec *, int);
516 529
517 if (fd_isrump(fd)) { 530 if (fd_isrump(fd)) {
518 fd = fd_host2rump(fd); 531 fd = fd_host2rump(fd);
519 op_writev = rumpcalls[RUMPCALL_WRITEV]; 532 op_writev = rumpcalls[RUMPCALL_WRITEV];
520 } else { 533 } else {
521 op_writev = host_writev; 534 op_writev = host_writev;
522 } 535 }
523 536
524 return op_writev(fd, iov, iovcnt); 537 return op_writev(fd, iov, iovcnt);
525} 538}
526 539
527int 540int
528ioctl(int fd, unsigned long cmd, ...) 541ioctl(int fd, unsigned long cmd, ...)
529{ 542{
530 int (*op_ioctl)(int, unsigned long cmd, ...); 543 int (*op_ioctl)(int, unsigned long cmd, ...);
531 va_list ap; 544 va_list ap;
532 int rv; 545 int rv;
533 546
534 DPRINTF(("ioctl\n")); 547 DPRINTF(("ioctl\n"));
535 if (fd_isrump(fd)) { 548 if (fd_isrump(fd)) {
536 fd = fd_host2rump(fd); 549 fd = fd_host2rump(fd);
537 op_ioctl = rumpcalls[RUMPCALL_IOCTL]; 550 op_ioctl = rumpcalls[RUMPCALL_IOCTL];
538 } else { 551 } else {
539 op_ioctl = host_ioctl; 552 op_ioctl = host_ioctl;
540 } 553 }
541 554
542 va_start(ap, cmd); 555 va_start(ap, cmd);
543 rv = op_ioctl(fd, cmd, va_arg(ap, void *)); 556 rv = op_ioctl(fd, cmd, va_arg(ap, void *));
544 va_end(ap); 557 va_end(ap);
545 return rv; 558 return rv;
546} 559}
547 560
548int 561int
549fcntl(int fd, int cmd, ...) 562fcntl(int fd, int cmd, ...)
550{ 563{
551 int (*op_fcntl)(int, int, ...); 564 int (*op_fcntl)(int, int, ...);
552 va_list ap; 565 va_list ap;
553 int rv; 566 int rv;
554 567
555 DPRINTF(("fcntl\n")); 568 DPRINTF(("fcntl\n"));
556 if (fd_isrump(fd)) { 569 if (fd_isrump(fd)) {
557 fd = fd_host2rump(fd); 570 fd = fd_host2rump(fd);
558 op_fcntl = rumpcalls[RUMPCALL_FCNTL]; 571 op_fcntl = rumpcalls[RUMPCALL_FCNTL];
559 } else { 572 } else {
560 op_fcntl = host_fcntl; 573 op_fcntl = host_fcntl;
561 } 574 }
562 575
563 va_start(ap, cmd); 576 va_start(ap, cmd);
564 rv = op_fcntl(fd, cmd, va_arg(ap, void *)); 577 rv = op_fcntl(fd, cmd, va_arg(ap, void *));
565 va_end(ap); 578 va_end(ap);
566 return rv; 579 return rv;
567} 580}
568 581
569int 582int
570close(int fd) 583close(int fd)
571{ 584{
572 int (*op_close)(int); 585 int (*op_close)(int);
573 586
574 DPRINTF(("close %d\n", fd)); 587 DPRINTF(("close %d\n", fd));
575 if (fd_isrump(fd)) { 588 if (fd_isrump(fd)) {
576 fd = fd_host2rump(fd); 589 fd = fd_host2rump(fd);
577 op_close = rumpcalls[RUMPCALL_CLOSE]; 590 op_close = rumpcalls[RUMPCALL_CLOSE];
578 } else { 591 } else {
579 op_close = host_close; 592 op_close = host_close;
580 } 593 }
581 594
582 return op_close(fd); 595 return op_close(fd);
583} 596}
584 597
585int 598int
586select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 599select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
587 struct timeval *timeout) 600 struct timeval *timeout)
588{ 601{
589 struct pollfd *pfds; 602 struct pollfd *pfds;
590 struct timespec ts, *tsp = NULL; 603 struct timespec ts, *tsp = NULL;
591 nfds_t i, j, realnfds; 604 nfds_t i, j, realnfds;
592 int rv, incr; 605 int rv, incr;
593 606
594 /* 607 /*
595 * Well, first we must scan the fds to figure out how many 608 * Well, first we must scan the fds to figure out how many
596 * fds there really are. This is because up to and including 609 * fds there really are. This is because up to and including
597 * nb5 poll() silently refuses nfds > process_open_fds. 610 * nb5 poll() silently refuses nfds > process_open_fds.
598 * Seems to be fixed in current, thank the maker. 611 * Seems to be fixed in current, thank the maker.
599 * god damn cluster...bomb. 612 * god damn cluster...bomb.
600 */ 613 */
601  614
602 for (i = 0, realnfds = 0; i < nfds; i++) { 615 for (i = 0, realnfds = 0; i < nfds; i++) {
603 if (readfds && FD_ISSET(i, readfds)) { 616 if (readfds && FD_ISSET(i, readfds)) {
604 realnfds++; 617 realnfds++;
605 continue; 618 continue;
606 } 619 }
607 if (writefds && FD_ISSET(i, writefds)) { 620 if (writefds && FD_ISSET(i, writefds)) {
608 realnfds++; 621 realnfds++;
609 continue; 622 continue;
610 } 623 }
611 if (exceptfds && FD_ISSET(i, exceptfds)) { 624 if (exceptfds && FD_ISSET(i, exceptfds)) {
612 realnfds++; 625 realnfds++;
613 continue; 626 continue;
614 } 627 }
615 } 628 }
616 629
617 pfds = malloc(sizeof(*pfds) * realnfds); 630 pfds = malloc(sizeof(*pfds) * realnfds);
618 if (!pfds) 631 if (!pfds)
619 return -1; 632 return -1;
620 633
621 for (i = 0, j = 0; i < nfds; i++) { 634 for (i = 0, j = 0; i < nfds; i++) {
622 incr = 0; 635 incr = 0;
623 pfds[j].events = pfds[j].revents = 0; 636 pfds[j].events = pfds[j].revents = 0;
624 if (readfds && FD_ISSET(i, readfds)) { 637 if (readfds && FD_ISSET(i, readfds)) {
625 pfds[j].fd = i; 638 pfds[j].fd = i;
626 pfds[j].events |= POLLIN; 639 pfds[j].events |= POLLIN;
627 incr=1; 640 incr=1;
628 } 641 }
629 if (writefds && FD_ISSET(i, writefds)) { 642 if (writefds && FD_ISSET(i, writefds)) {
630 pfds[j].fd = i; 643 pfds[j].fd = i;
631 pfds[j].events |= POLLOUT; 644 pfds[j].events |= POLLOUT;
632 incr=1; 645 incr=1;
633 } 646 }
634 if (exceptfds && FD_ISSET(i, exceptfds)) { 647 if (exceptfds && FD_ISSET(i, exceptfds)) {
635 pfds[j].fd = i; 648 pfds[j].fd = i;
636 pfds[j].events |= POLLHUP|POLLERR; 649 pfds[j].events |= POLLHUP|POLLERR;
637 incr=1; 650 incr=1;
638 } 651 }
639 if (incr) 652 if (incr)
640 j++; 653 j++;
641 } 654 }
642 655
643 if (timeout) { 656 if (timeout) {
644 TIMEVAL_TO_TIMESPEC(timeout, &ts); 657 TIMEVAL_TO_TIMESPEC(timeout, &ts);
645 tsp = &ts; 658 tsp = &ts;
646 } 659 }
647 rv = pollts(pfds, realnfds, tsp, NULL); 660 rv = pollts(pfds, realnfds, tsp, NULL);
648 if (rv <= 0) 661 if (rv <= 0)
649 goto out; 662 goto out;
650 663
651 /* 664 /*
652 * ok, harvest results. first zero out entries (can't use 665 * ok, harvest results. first zero out entries (can't use
653 * FD_ZERO for the obvious select-me-not reason). whee. 666 * FD_ZERO for the obvious select-me-not reason). whee.
654 */ 667 */
655 for (i = 0; i < nfds; i++) { 668 for (i = 0; i < nfds; i++) {
656 if (readfds) 669 if (readfds)
657 FD_CLR(i, readfds); 670 FD_CLR(i, readfds);
658 if (writefds) 671 if (writefds)
659 FD_CLR(i, writefds); 672 FD_CLR(i, writefds);
660 if (exceptfds) 673 if (exceptfds)
661 FD_CLR(i, exceptfds); 674 FD_CLR(i, exceptfds);
662 } 675 }
663 676
664 /* and then plug in the results */ 677 /* and then plug in the results */
665 for (i = 0; i < realnfds; i++) { 678 for (i = 0; i < realnfds; i++) {
666 if (readfds) { 679 if (readfds) {
667 if (pfds[i].revents & POLLIN) { 680 if (pfds[i].revents & POLLIN) {
668 FD_SET(pfds[i].fd, readfds); 681 FD_SET(pfds[i].fd, readfds);
669 } 682 }
670 } 683 }
671 if (writefds) { 684 if (writefds) {
672 if (pfds[i].revents & POLLOUT) { 685 if (pfds[i].revents & POLLOUT) {
673 FD_SET(pfds[i].fd, writefds); 686 FD_SET(pfds[i].fd, writefds);
674 } 687 }
675 } 688 }
676 if (exceptfds) { 689 if (exceptfds) {
677 if (pfds[i].revents & (POLLHUP|POLLERR)) { 690 if (pfds[i].revents & (POLLHUP|POLLERR)) {
678 FD_SET(pfds[i].fd, exceptfds); 691 FD_SET(pfds[i].fd, exceptfds);
679 } 692 }
680 } 693 }
681 } 694 }
682 695
683 out: 696 out:
684 free(pfds); 697 free(pfds);
685 return rv; 698 return rv;
686} 699}
687 700
688static void 701static void
689checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall) 702checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
690{ 703{
691 nfds_t i; 704 nfds_t i;
692 705
693 for (i = 0; i < nfds; i++) { 706 for (i = 0; i < nfds; i++) {
694 if (fd_isrump(fds[i].fd)) 707 if (fd_isrump(fds[i].fd))
695 (*rumpcall)++; 708 (*rumpcall)++;
696 else 709 else
697 (*hostcall)++; 710 (*hostcall)++;
698 } 711 }
699} 712}
700 713
701static void 714static void
702adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int)) 715adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
703{ 716{
704 nfds_t i; 717 nfds_t i;
705 718
706 for (i = 0; i < nfds; i++) { 719 for (i = 0; i < nfds; i++) {
707 fds[i].fd = fdadj(fds[i].fd); 720 fds[i].fd = fdadj(fds[i].fd);
708 } 721 }
709} 722}
710 723
711struct mytimespec { 724struct mytimespec {
712 uint64_t tv_sec; 725 uint64_t tv_sec;
713 long tv_nsec; 726 long tv_nsec;
714}; 727};
715 728
716/* 729/*
717 * poll is easy as long as the call comes in the fds only in one 730 * poll is easy as long as the call comes in the fds only in one
718 * kernel. otherwise its quite tricky... 731 * kernel. otherwise its quite tricky...
719 */ 732 */
720struct pollarg { 733struct pollarg {
721 struct pollfd *pfds; 734 struct pollfd *pfds;
722 nfds_t nfds; 735 nfds_t nfds;
723 const struct timespec *ts; 736 const struct timespec *ts;
724 const sigset_t *sigmask; 737 const sigset_t *sigmask;
725 int pipefd; 738 int pipefd;
726 int errnum; 739 int errnum;
727}; 740};
728 741
729static void * 742static void *
730hostpoll(void *arg) 743hostpoll(void *arg)
731{ 744{
732 struct pollarg *parg = arg; 745 struct pollarg *parg = arg;
733 intptr_t rv; 746 intptr_t rv;
734 747
735 rv = host_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask); 748 rv = host_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
736 if (rv == -1) 749 if (rv == -1)
737 parg->errnum = errno; 750 parg->errnum = errno;
738 rump_sys_write(parg->pipefd, &rv, sizeof(rv)); 751 rump_sys_write(parg->pipefd, &rv, sizeof(rv));
739 752
740 return (void *)(intptr_t)rv; 753 return (void *)(intptr_t)rv;
741} 754}
742 755
743int 756int
744pollts(struct pollfd *fds, nfds_t nfds, const struct timespec *ts, 757pollts(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
745 const sigset_t *sigmask) 758 const sigset_t *sigmask)
746{ 759{
747 int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *, 760 int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
748 const sigset_t *); 761 const sigset_t *);
749 int hostcall = 0, rumpcall = 0; 762 int hostcall = 0, rumpcall = 0;
750 pthread_t pt; 763 pthread_t pt;
751 nfds_t i; 764 nfds_t i;
752 int rv; 765 int rv;
753 766
754#if 0 767#if 0
755 /* XXX: quick 5.0 kludge. do syscall compat in rumpclient properly */ 768 /* XXX: quick 5.0 kludge. do syscall compat in rumpclient properly */
756 struct mytimespec mts; 769 struct mytimespec mts;
757 if (ts) { 770 if (ts) {
758 mts.tv_sec = ts->tv_sec; 771 mts.tv_sec = ts->tv_sec;
759 mts.tv_nsec = ts->tv_nsec; 772 mts.tv_nsec = ts->tv_nsec;
760 ts = (struct timespec *)&mts; 773 ts = (struct timespec *)&mts;
761 } 774 }
762#endif 775#endif
763 776
764 DPRINTF(("poll\n")); 777 DPRINTF(("poll\n"));
765 checkpoll(fds, nfds, &hostcall, &rumpcall); 778 checkpoll(fds, nfds, &hostcall, &rumpcall);
766 779
767 if (hostcall && rumpcall) { 780 if (hostcall && rumpcall) {
768 struct pollfd *pfd_host = NULL, *pfd_rump = NULL; 781 struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
769 int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1}; 782 int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
770 struct pollarg parg; 783 struct pollarg parg;
771 uintptr_t lrv; 784 uintptr_t lrv;
772 int sverrno = 0, trv; 785 int sverrno = 0, trv;
773 786
774 /* 787 /*
775 * ok, this is where it gets tricky. We must support 788 * ok, this is where it gets tricky. We must support
776 * this since it's a very common operation in certain 789 * this since it's a very common operation in certain
777 * types of software (telnet, netcat, etc). We allocate 790 * types of software (telnet, netcat, etc). We allocate
778 * two vectors and run two poll commands in separate 791 * two vectors and run two poll commands in separate
779 * threads. Whichever returns first "wins" and the 792 * threads. Whichever returns first "wins" and the
780 * other kernel's fds won't show activity. 793 * other kernel's fds won't show activity.
781 */ 794 */
782 rv = -1; 795 rv = -1;
783 796
784 /* allocate full vector for O(n) joining after call */ 797 /* allocate full vector for O(n) joining after call */
785 pfd_host = malloc(sizeof(*pfd_host)*(nfds+1)); 798 pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
786 if (!pfd_host) 799 if (!pfd_host)
787 goto out; 800 goto out;
788 pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1)); 801 pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
789 if (!pfd_rump) { 802 if (!pfd_rump) {
790 goto out; 803 goto out;
791 } 804 }
792 805
793 /* split vectors */ 806 /* split vectors */
794 for (i = 0; i < nfds; i++) { 807 for (i = 0; i < nfds; i++) {
795 if (fds[i].fd == -1) { 808 if (fds[i].fd == -1) {
796 pfd_host[i].fd = -1; 809 pfd_host[i].fd = -1;
797 pfd_rump[i].fd = -1; 810 pfd_rump[i].fd = -1;
798 } else if (fd_isrump(fds[i].fd)) { 811 } else if (fd_isrump(fds[i].fd)) {
799 pfd_host[i].fd = -1; 812 pfd_host[i].fd = -1;
800 pfd_rump[i].fd = fd_host2rump(fds[i].fd); 813 pfd_rump[i].fd = fd_host2rump(fds[i].fd);
801 pfd_rump[i].events = fds[i].events; 814 pfd_rump[i].events = fds[i].events;
802 } else { 815 } else {
803 pfd_rump[i].fd = -1; 816 pfd_rump[i].fd = -1;
804 pfd_host[i].fd = fds[i].fd; 817 pfd_host[i].fd = fds[i].fd;
805 pfd_host[i].events = fds[i].events; 818 pfd_host[i].events = fds[i].events;
806 } 819 }
807 } 820 }
808 821
809 /* 822 /*
810 * then, open two pipes, one for notifications 823 * then, open two pipes, one for notifications
811 * to each kernel. 824 * to each kernel.
812 */ 825 */
813 if (rump_sys_pipe(rpipe) == -1) 826 if (rump_sys_pipe(rpipe) == -1)
814 goto out; 827 goto out;
815 if (pipe(hpipe) == -1) 828 if (pipe(hpipe) == -1)
816 goto out; 829 goto out;
817 830
818 pfd_host[nfds].fd = hpipe[0]; 831 pfd_host[nfds].fd = hpipe[0];
819 pfd_host[nfds].events = POLLIN; 832 pfd_host[nfds].events = POLLIN;
820 pfd_rump[nfds].fd = rpipe[0]; 833 pfd_rump[nfds].fd = rpipe[0];
821 pfd_rump[nfds].events = POLLIN; 834 pfd_rump[nfds].events = POLLIN;
822 835
823 /* 836 /*
824 * then, create a thread to do host part and meanwhile 837 * then, create a thread to do host part and meanwhile
825 * do rump kernel part right here 838 * do rump kernel part right here
826 */ 839 */
827 840
828 parg.pfds = pfd_host; 841 parg.pfds = pfd_host;
829 parg.nfds = nfds+1; 842 parg.nfds = nfds+1;
830 parg.ts = ts; 843 parg.ts = ts;
831 parg.sigmask = sigmask; 844 parg.sigmask = sigmask;
832 parg.pipefd = rpipe[1]; 845 parg.pipefd = rpipe[1];
833 pthread_create(&pt, NULL, hostpoll, &parg); 846 pthread_create(&pt, NULL, hostpoll, &parg);
834 847
835 op_pollts = rumpcalls[RUMPCALL_POLLTS]; 848 op_pollts = rumpcalls[RUMPCALL_POLLTS];
836 lrv = op_pollts(pfd_rump, nfds+1, ts, NULL); 849 lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
837 sverrno = errno; 850 sverrno = errno;
838 write(hpipe[1], &rv, sizeof(rv)); 851 write(hpipe[1], &rv, sizeof(rv));
839 pthread_join(pt, (void *)&trv); 852 pthread_join(pt, (void *)&trv);
840 853
841 /* check who "won" and merge results */ 854 /* check who "won" and merge results */
842 if (lrv != 0 && pfd_host[nfds].revents & POLLIN) { 855 if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
843 rv = trv; 856 rv = trv;
844 857
845 for (i = 0; i < nfds; i++) { 858 for (i = 0; i < nfds; i++) {
846 if (pfd_rump[i].fd != -1) 859 if (pfd_rump[i].fd != -1)
847 fds[i].revents = pfd_rump[i].revents; 860 fds[i].revents = pfd_rump[i].revents;
848 } 861 }
849 sverrno = parg.errnum; 862 sverrno = parg.errnum;
850 } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) { 863 } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
851 rv = trv; 864 rv = trv;
852 865
853 for (i = 0; i < nfds; i++) { 866 for (i = 0; i < nfds; i++) {
854 if (pfd_host[i].fd != -1) 867 if (pfd_host[i].fd != -1)
855 fds[i].revents = pfd_host[i].revents; 868 fds[i].revents = pfd_host[i].revents;
856 } 869 }
857 } else { 870 } else {
858 rv = 0; 871 rv = 0;
859 } 872 }
860 873
861 out: 874 out:
862 if (rpipe[0] != -1) 875 if (rpipe[0] != -1)
863 rump_sys_close(rpipe[0]); 876 rump_sys_close(rpipe[0]);
864 if (rpipe[1] != -1) 877 if (rpipe[1] != -1)
865 rump_sys_close(rpipe[1]); 878 rump_sys_close(rpipe[1]);
866 if (hpipe[0] != -1) 879 if (hpipe[0] != -1)
867 close(hpipe[0]); 880 close(hpipe[0]);
868 if (hpipe[1] != -1) 881 if (hpipe[1] != -1)
869 close(hpipe[1]); 882 close(hpipe[1]);
870 free(pfd_host); 883 free(pfd_host);
871 free(pfd_rump); 884 free(pfd_rump);
872 errno = sverrno; 885 errno = sverrno;
873 } else { 886 } else {
874 if (hostcall) { 887 if (hostcall) {
875 op_pollts = host_pollts; 888 op_pollts = host_pollts;
876 } else { 889 } else {
877 op_pollts = rumpcalls[RUMPCALL_POLLTS]; 890 op_pollts = rumpcalls[RUMPCALL_POLLTS];
878 adjustpoll(fds, nfds, fd_host2rump); 891 adjustpoll(fds, nfds, fd_host2rump);
879 } 892 }
880 893
881 rv = op_pollts(fds, nfds, ts, sigmask); 894 rv = op_pollts(fds, nfds, ts, sigmask);
882 if (rumpcall) 895 if (rumpcall)
883 adjustpoll(fds, nfds, fd_rump2host); 896 adjustpoll(fds, nfds, fd_rump2host);
884 } 897 }
885 898
886 return rv; 899 return rv;
887} 900}
888 901
889int 902int
890poll(struct pollfd *fds, nfds_t nfds, int timeout) 903poll(struct pollfd *fds, nfds_t nfds, int timeout)
891{ 904{
892 struct timespec ts; 905 struct timespec ts;
893 struct timespec *tsp = NULL; 906 struct timespec *tsp = NULL;
894 907
895 if (timeout != INFTIM) { 908 if (timeout != INFTIM) {
896 ts.tv_sec = timeout / 1000; 909 ts.tv_sec = timeout / 1000;
897 ts.tv_nsec = (timeout % 1000) * 1000; 910 ts.tv_nsec = (timeout % 1000) * 1000;
898 911
899 tsp = &ts; 912 tsp = &ts;
900 } 913 }
901 914
902 return pollts(fds, nfds, tsp, NULL); 915 return pollts(fds, nfds, tsp, NULL);
903} 916}