Deleted Added
full compact
sys_generic.c (31364) sys_generic.c (34961)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
39 * $Id: sys_generic.c,v 1.32 1997/11/06 19:29:20 phk Exp $
39 * $Id: sys_generic.c,v 1.33 1997/11/23 10:30:50 bde Exp $
40 */
41
42#include "opt_ktrace.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/sysproto.h>
47#include <sys/filedesc.h>
48#include <sys/filio.h>
49#include <sys/ttycom.h>
50#include <sys/fcntl.h>
51#include <sys/file.h>
52#include <sys/proc.h>
53#include <sys/signalvar.h>
54#include <sys/socketvar.h>
55#include <sys/uio.h>
56#include <sys/kernel.h>
57#include <sys/malloc.h>
58#include <sys/poll.h>
59#include <sys/sysent.h>
60#ifdef KTRACE
61#include <sys/ktrace.h>
62#endif
63
64static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
65static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
66MALLOC_DEFINE(M_IOV, "iov", "large iov's");
67
68static int pollscan __P((struct proc *, struct pollfd *, int));
69static int selscan __P((struct proc *, fd_mask **, fd_mask **, int));
70
71/*
72 * Read system call.
73 */
74#ifndef _SYS_SYSPROTO_H_
75struct read_args {
76 int fd;
77 char *buf;
78 u_int nbyte;
79};
80#endif
81/* ARGSUSED */
82int
83read(p, uap)
84 struct proc *p;
85 register struct read_args *uap;
86{
87 register struct file *fp;
88 register struct filedesc *fdp = p->p_fd;
89 struct uio auio;
90 struct iovec aiov;
91 long cnt, error = 0;
92#ifdef KTRACE
93 struct iovec ktriov;
94#endif
95
96 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
97 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
98 (fp->f_flag & FREAD) == 0)
99 return (EBADF);
100 aiov.iov_base = (caddr_t)uap->buf;
101 aiov.iov_len = uap->nbyte;
102 auio.uio_iov = &aiov;
103 auio.uio_iovcnt = 1;
104 auio.uio_offset = -1;
105
106 auio.uio_resid = uap->nbyte;
107 if (auio.uio_resid < 0)
108 return (EINVAL);
109
110 auio.uio_rw = UIO_READ;
111 auio.uio_segflg = UIO_USERSPACE;
112 auio.uio_procp = p;
113#ifdef KTRACE
114 /*
115 * if tracing, save a copy of iovec
116 */
117 if (KTRPOINT(p, KTR_GENIO))
118 ktriov = aiov;
119#endif
120 cnt = uap->nbyte;
121 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
122 if (auio.uio_resid != cnt && (error == ERESTART ||
123 error == EINTR || error == EWOULDBLOCK))
124 error = 0;
125 cnt -= auio.uio_resid;
126#ifdef KTRACE
127 if (KTRPOINT(p, KTR_GENIO) && error == 0)
128 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error);
129#endif
130 p->p_retval[0] = cnt;
131 return (error);
132}
133
134/*
135 * Scatter read system call.
136 */
137#ifndef _SYS_SYSPROTO_H_
138struct readv_args {
139 int fd;
140 struct iovec *iovp;
141 u_int iovcnt;
142};
143#endif
144int
145readv(p, uap)
146 struct proc *p;
147 register struct readv_args *uap;
148{
149 register struct file *fp;
150 register struct filedesc *fdp = p->p_fd;
151 struct uio auio;
152 register struct iovec *iov;
153 struct iovec *needfree;
154 struct iovec aiov[UIO_SMALLIOV];
155 long i, cnt, error = 0;
156 u_int iovlen;
157#ifdef KTRACE
158 struct iovec *ktriov = NULL;
159#endif
160
161 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
162 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
163 (fp->f_flag & FREAD) == 0)
164 return (EBADF);
165 /* note: can't use iovlen until iovcnt is validated */
166 iovlen = uap->iovcnt * sizeof (struct iovec);
167 if (uap->iovcnt > UIO_SMALLIOV) {
168 if (uap->iovcnt > UIO_MAXIOV)
169 return (EINVAL);
170 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
171 needfree = iov;
172 } else {
173 iov = aiov;
174 needfree = NULL;
175 }
176 auio.uio_iov = iov;
177 auio.uio_iovcnt = uap->iovcnt;
178 auio.uio_rw = UIO_READ;
179 auio.uio_segflg = UIO_USERSPACE;
180 auio.uio_procp = p;
181 auio.uio_offset = -1;
182 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
183 goto done;
184 auio.uio_resid = 0;
185 for (i = 0; i < uap->iovcnt; i++) {
186 auio.uio_resid += iov->iov_len;
187 if (auio.uio_resid < 0) {
188 error = EINVAL;
189 goto done;
190 }
191 iov++;
192 }
193#ifdef KTRACE
194 /*
195 * if tracing, save a copy of iovec
196 */
197 if (KTRPOINT(p, KTR_GENIO)) {
198 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
199 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
200 }
201#endif
202 cnt = auio.uio_resid;
203 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
204 if (auio.uio_resid != cnt && (error == ERESTART ||
205 error == EINTR || error == EWOULDBLOCK))
206 error = 0;
207 cnt -= auio.uio_resid;
208#ifdef KTRACE
209 if (ktriov != NULL) {
210 if (error == 0)
211 ktrgenio(p->p_tracep, uap->fd, UIO_READ, ktriov,
212 cnt, error);
213 FREE(ktriov, M_TEMP);
214 }
215#endif
216 p->p_retval[0] = cnt;
217done:
218 if (needfree)
219 FREE(needfree, M_IOV);
220 return (error);
221}
222
223/*
224 * Write system call
225 */
226#ifndef _SYS_SYSPROTO_H_
227struct write_args {
228 int fd;
229 char *buf;
230 u_int nbyte;
231};
232#endif
233int
234write(p, uap)
235 struct proc *p;
236 register struct write_args *uap;
237{
238 register struct file *fp;
239 register struct filedesc *fdp = p->p_fd;
240 struct uio auio;
241 struct iovec aiov;
242 long cnt, error = 0;
243#ifdef KTRACE
244 struct iovec ktriov;
245#endif
246
247 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
248 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
249 (fp->f_flag & FWRITE) == 0)
250 return (EBADF);
251 aiov.iov_base = (caddr_t)uap->buf;
252 aiov.iov_len = uap->nbyte;
253 auio.uio_iov = &aiov;
254 auio.uio_iovcnt = 1;
255 auio.uio_offset = -1;
256 auio.uio_resid = uap->nbyte;
257 auio.uio_rw = UIO_WRITE;
258 auio.uio_segflg = UIO_USERSPACE;
259 auio.uio_procp = p;
260#ifdef KTRACE
261 /*
262 * if tracing, save a copy of iovec
263 */
264 if (KTRPOINT(p, KTR_GENIO))
265 ktriov = aiov;
266#endif
267 cnt = uap->nbyte;
268 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
269 if (auio.uio_resid != cnt && (error == ERESTART ||
270 error == EINTR || error == EWOULDBLOCK))
271 error = 0;
272 if (error == EPIPE)
273 psignal(p, SIGPIPE);
274 }
275 cnt -= auio.uio_resid;
276#ifdef KTRACE
277 if (KTRPOINT(p, KTR_GENIO) && error == 0)
278 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
279 &ktriov, cnt, error);
280#endif
281 p->p_retval[0] = cnt;
282 return (error);
283}
284
285/*
286 * Gather write system call
287 */
288#ifndef _SYS_SYSPROTO_H_
289struct writev_args {
290 int fd;
291 struct iovec *iovp;
292 u_int iovcnt;
293};
294#endif
295int
296writev(p, uap)
297 struct proc *p;
298 register struct writev_args *uap;
299{
300 register struct file *fp;
301 register struct filedesc *fdp = p->p_fd;
302 struct uio auio;
303 register struct iovec *iov;
304 struct iovec *needfree;
305 struct iovec aiov[UIO_SMALLIOV];
306 long i, cnt, error = 0;
307 u_int iovlen;
308#ifdef KTRACE
309 struct iovec *ktriov = NULL;
310#endif
311
312 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
313 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
314 (fp->f_flag & FWRITE) == 0)
315 return (EBADF);
316 /* note: can't use iovlen until iovcnt is validated */
317 iovlen = uap->iovcnt * sizeof (struct iovec);
318 if (uap->iovcnt > UIO_SMALLIOV) {
319 if (uap->iovcnt > UIO_MAXIOV)
320 return (EINVAL);
321 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
322 needfree = iov;
323 } else {
324 iov = aiov;
325 needfree = NULL;
326 }
327 auio.uio_iov = iov;
328 auio.uio_iovcnt = uap->iovcnt;
329 auio.uio_rw = UIO_WRITE;
330 auio.uio_segflg = UIO_USERSPACE;
331 auio.uio_procp = p;
332 auio.uio_offset = -1;
333 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
334 goto done;
335 auio.uio_resid = 0;
336 for (i = 0; i < uap->iovcnt; i++) {
337 auio.uio_resid += iov->iov_len;
338 if (auio.uio_resid < 0) {
339 error = EINVAL;
340 goto done;
341 }
342 iov++;
343 }
344#ifdef KTRACE
345 /*
346 * if tracing, save a copy of iovec
347 */
348 if (KTRPOINT(p, KTR_GENIO)) {
349 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
350 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
351 }
352#endif
353 cnt = auio.uio_resid;
354 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
355 if (auio.uio_resid != cnt && (error == ERESTART ||
356 error == EINTR || error == EWOULDBLOCK))
357 error = 0;
358 if (error == EPIPE)
359 psignal(p, SIGPIPE);
360 }
361 cnt -= auio.uio_resid;
362#ifdef KTRACE
363 if (ktriov != NULL) {
364 if (error == 0)
365 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
366 ktriov, cnt, error);
367 FREE(ktriov, M_TEMP);
368 }
369#endif
370 p->p_retval[0] = cnt;
371done:
372 if (needfree)
373 FREE(needfree, M_IOV);
374 return (error);
375}
376
377/*
378 * Ioctl system call
379 */
380#ifndef _SYS_SYSPROTO_H_
381struct ioctl_args {
382 int fd;
383 int com;
384 caddr_t data;
385};
386#endif
387/* ARGSUSED */
388int
389ioctl(p, uap)
390 struct proc *p;
391 register struct ioctl_args *uap;
392{
393 register struct file *fp;
394 register struct filedesc *fdp;
395 register int com, error;
396 register u_int size;
397 caddr_t data, memp;
398 int tmp;
399#define STK_PARAMS 128
400 char stkbuf[STK_PARAMS];
401
402 fdp = p->p_fd;
403 if ((u_int)uap->fd >= fdp->fd_nfiles ||
404 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
405 return (EBADF);
406
407 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
408 return (EBADF);
409
410 switch (com = uap->com) {
411 case FIONCLEX:
412 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
413 return (0);
414 case FIOCLEX:
415 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
416 return (0);
417 }
418
419 /*
420 * Interpret high order word to find amount of data to be
421 * copied to/from the user's address space.
422 */
423 size = IOCPARM_LEN(com);
424 if (size > IOCPARM_MAX)
425 return (ENOTTY);
426 memp = NULL;
427 if (size > sizeof (stkbuf)) {
428 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
429 data = memp;
430 } else
431 data = stkbuf;
432 if (com&IOC_IN) {
433 if (size) {
434 error = copyin(uap->data, data, (u_int)size);
435 if (error) {
436 if (memp)
437 free(memp, M_IOCTLOPS);
438 return (error);
439 }
440 } else
441 *(caddr_t *)data = uap->data;
442 } else if ((com&IOC_OUT) && size)
443 /*
444 * Zero the buffer so the user always
445 * gets back something deterministic.
446 */
447 bzero(data, size);
448 else if (com&IOC_VOID)
449 *(caddr_t *)data = uap->data;
450
451 switch (com) {
452
453 case FIONBIO:
454 if ((tmp = *(int *)data))
455 fp->f_flag |= FNONBLOCK;
456 else
457 fp->f_flag &= ~FNONBLOCK;
458 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
459 break;
460
461 case FIOASYNC:
462 if ((tmp = *(int *)data))
463 fp->f_flag |= FASYNC;
464 else
465 fp->f_flag &= ~FASYNC;
466 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
467 break;
468
469 case FIOSETOWN:
470 tmp = *(int *)data;
471 if (fp->f_type == DTYPE_SOCKET) {
472 ((struct socket *)fp->f_data)->so_pgid = tmp;
473 error = 0;
474 break;
475 }
476 if (tmp <= 0) {
477 tmp = -tmp;
478 } else {
479 struct proc *p1 = pfind(tmp);
480 if (p1 == 0) {
481 error = ESRCH;
482 break;
483 }
484 tmp = p1->p_pgrp->pg_id;
485 }
486 error = (*fp->f_ops->fo_ioctl)
487 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
488 break;
489
490 case FIOGETOWN:
491 if (fp->f_type == DTYPE_SOCKET) {
492 error = 0;
493 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
494 break;
495 }
496 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
497 *(int *)data = -*(int *)data;
498 break;
499
500 default:
501 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
502 /*
503 * Copy any data to user, size was
504 * already set and checked above.
505 */
506 if (error == 0 && (com&IOC_OUT) && size)
507 error = copyout(data, uap->data, (u_int)size);
508 break;
509 }
510 if (memp)
511 free(memp, M_IOCTLOPS);
512 return (error);
513}
514
515static int nselcoll;
516int selwait;
517
518/*
519 * Select system call.
520 */
521#ifndef _SYS_SYSPROTO_H_
522struct select_args {
523 int nd;
524 fd_set *in, *ou, *ex;
525 struct timeval *tv;
526};
527#endif
528int
529select(p, uap)
530 register struct proc *p;
531 register struct select_args *uap;
532{
533 /*
534 * The magic 2048 here is chosen to be just enough for FD_SETSIZE
535 * infds with the new FD_SETSIZE of 1024, and more than enough for
536 * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE
537 * of 256.
538 */
539 fd_mask s_selbits[howmany(2048, NFDBITS)];
540 fd_mask *ibits[3], *obits[3], *selbits, *sbp;
541 struct timeval atv;
40 */
41
42#include "opt_ktrace.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/sysproto.h>
47#include <sys/filedesc.h>
48#include <sys/filio.h>
49#include <sys/ttycom.h>
50#include <sys/fcntl.h>
51#include <sys/file.h>
52#include <sys/proc.h>
53#include <sys/signalvar.h>
54#include <sys/socketvar.h>
55#include <sys/uio.h>
56#include <sys/kernel.h>
57#include <sys/malloc.h>
58#include <sys/poll.h>
59#include <sys/sysent.h>
60#ifdef KTRACE
61#include <sys/ktrace.h>
62#endif
63
64static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
65static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
66MALLOC_DEFINE(M_IOV, "iov", "large iov's");
67
68static int pollscan __P((struct proc *, struct pollfd *, int));
69static int selscan __P((struct proc *, fd_mask **, fd_mask **, int));
70
71/*
72 * Read system call.
73 */
74#ifndef _SYS_SYSPROTO_H_
75struct read_args {
76 int fd;
77 char *buf;
78 u_int nbyte;
79};
80#endif
81/* ARGSUSED */
82int
83read(p, uap)
84 struct proc *p;
85 register struct read_args *uap;
86{
87 register struct file *fp;
88 register struct filedesc *fdp = p->p_fd;
89 struct uio auio;
90 struct iovec aiov;
91 long cnt, error = 0;
92#ifdef KTRACE
93 struct iovec ktriov;
94#endif
95
96 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
97 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
98 (fp->f_flag & FREAD) == 0)
99 return (EBADF);
100 aiov.iov_base = (caddr_t)uap->buf;
101 aiov.iov_len = uap->nbyte;
102 auio.uio_iov = &aiov;
103 auio.uio_iovcnt = 1;
104 auio.uio_offset = -1;
105
106 auio.uio_resid = uap->nbyte;
107 if (auio.uio_resid < 0)
108 return (EINVAL);
109
110 auio.uio_rw = UIO_READ;
111 auio.uio_segflg = UIO_USERSPACE;
112 auio.uio_procp = p;
113#ifdef KTRACE
114 /*
115 * if tracing, save a copy of iovec
116 */
117 if (KTRPOINT(p, KTR_GENIO))
118 ktriov = aiov;
119#endif
120 cnt = uap->nbyte;
121 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
122 if (auio.uio_resid != cnt && (error == ERESTART ||
123 error == EINTR || error == EWOULDBLOCK))
124 error = 0;
125 cnt -= auio.uio_resid;
126#ifdef KTRACE
127 if (KTRPOINT(p, KTR_GENIO) && error == 0)
128 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error);
129#endif
130 p->p_retval[0] = cnt;
131 return (error);
132}
133
134/*
135 * Scatter read system call.
136 */
137#ifndef _SYS_SYSPROTO_H_
138struct readv_args {
139 int fd;
140 struct iovec *iovp;
141 u_int iovcnt;
142};
143#endif
144int
145readv(p, uap)
146 struct proc *p;
147 register struct readv_args *uap;
148{
149 register struct file *fp;
150 register struct filedesc *fdp = p->p_fd;
151 struct uio auio;
152 register struct iovec *iov;
153 struct iovec *needfree;
154 struct iovec aiov[UIO_SMALLIOV];
155 long i, cnt, error = 0;
156 u_int iovlen;
157#ifdef KTRACE
158 struct iovec *ktriov = NULL;
159#endif
160
161 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
162 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
163 (fp->f_flag & FREAD) == 0)
164 return (EBADF);
165 /* note: can't use iovlen until iovcnt is validated */
166 iovlen = uap->iovcnt * sizeof (struct iovec);
167 if (uap->iovcnt > UIO_SMALLIOV) {
168 if (uap->iovcnt > UIO_MAXIOV)
169 return (EINVAL);
170 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
171 needfree = iov;
172 } else {
173 iov = aiov;
174 needfree = NULL;
175 }
176 auio.uio_iov = iov;
177 auio.uio_iovcnt = uap->iovcnt;
178 auio.uio_rw = UIO_READ;
179 auio.uio_segflg = UIO_USERSPACE;
180 auio.uio_procp = p;
181 auio.uio_offset = -1;
182 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
183 goto done;
184 auio.uio_resid = 0;
185 for (i = 0; i < uap->iovcnt; i++) {
186 auio.uio_resid += iov->iov_len;
187 if (auio.uio_resid < 0) {
188 error = EINVAL;
189 goto done;
190 }
191 iov++;
192 }
193#ifdef KTRACE
194 /*
195 * if tracing, save a copy of iovec
196 */
197 if (KTRPOINT(p, KTR_GENIO)) {
198 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
199 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
200 }
201#endif
202 cnt = auio.uio_resid;
203 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
204 if (auio.uio_resid != cnt && (error == ERESTART ||
205 error == EINTR || error == EWOULDBLOCK))
206 error = 0;
207 cnt -= auio.uio_resid;
208#ifdef KTRACE
209 if (ktriov != NULL) {
210 if (error == 0)
211 ktrgenio(p->p_tracep, uap->fd, UIO_READ, ktriov,
212 cnt, error);
213 FREE(ktriov, M_TEMP);
214 }
215#endif
216 p->p_retval[0] = cnt;
217done:
218 if (needfree)
219 FREE(needfree, M_IOV);
220 return (error);
221}
222
223/*
224 * Write system call
225 */
226#ifndef _SYS_SYSPROTO_H_
227struct write_args {
228 int fd;
229 char *buf;
230 u_int nbyte;
231};
232#endif
233int
234write(p, uap)
235 struct proc *p;
236 register struct write_args *uap;
237{
238 register struct file *fp;
239 register struct filedesc *fdp = p->p_fd;
240 struct uio auio;
241 struct iovec aiov;
242 long cnt, error = 0;
243#ifdef KTRACE
244 struct iovec ktriov;
245#endif
246
247 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
248 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
249 (fp->f_flag & FWRITE) == 0)
250 return (EBADF);
251 aiov.iov_base = (caddr_t)uap->buf;
252 aiov.iov_len = uap->nbyte;
253 auio.uio_iov = &aiov;
254 auio.uio_iovcnt = 1;
255 auio.uio_offset = -1;
256 auio.uio_resid = uap->nbyte;
257 auio.uio_rw = UIO_WRITE;
258 auio.uio_segflg = UIO_USERSPACE;
259 auio.uio_procp = p;
260#ifdef KTRACE
261 /*
262 * if tracing, save a copy of iovec
263 */
264 if (KTRPOINT(p, KTR_GENIO))
265 ktriov = aiov;
266#endif
267 cnt = uap->nbyte;
268 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
269 if (auio.uio_resid != cnt && (error == ERESTART ||
270 error == EINTR || error == EWOULDBLOCK))
271 error = 0;
272 if (error == EPIPE)
273 psignal(p, SIGPIPE);
274 }
275 cnt -= auio.uio_resid;
276#ifdef KTRACE
277 if (KTRPOINT(p, KTR_GENIO) && error == 0)
278 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
279 &ktriov, cnt, error);
280#endif
281 p->p_retval[0] = cnt;
282 return (error);
283}
284
285/*
286 * Gather write system call
287 */
288#ifndef _SYS_SYSPROTO_H_
289struct writev_args {
290 int fd;
291 struct iovec *iovp;
292 u_int iovcnt;
293};
294#endif
295int
296writev(p, uap)
297 struct proc *p;
298 register struct writev_args *uap;
299{
300 register struct file *fp;
301 register struct filedesc *fdp = p->p_fd;
302 struct uio auio;
303 register struct iovec *iov;
304 struct iovec *needfree;
305 struct iovec aiov[UIO_SMALLIOV];
306 long i, cnt, error = 0;
307 u_int iovlen;
308#ifdef KTRACE
309 struct iovec *ktriov = NULL;
310#endif
311
312 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
313 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
314 (fp->f_flag & FWRITE) == 0)
315 return (EBADF);
316 /* note: can't use iovlen until iovcnt is validated */
317 iovlen = uap->iovcnt * sizeof (struct iovec);
318 if (uap->iovcnt > UIO_SMALLIOV) {
319 if (uap->iovcnt > UIO_MAXIOV)
320 return (EINVAL);
321 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
322 needfree = iov;
323 } else {
324 iov = aiov;
325 needfree = NULL;
326 }
327 auio.uio_iov = iov;
328 auio.uio_iovcnt = uap->iovcnt;
329 auio.uio_rw = UIO_WRITE;
330 auio.uio_segflg = UIO_USERSPACE;
331 auio.uio_procp = p;
332 auio.uio_offset = -1;
333 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
334 goto done;
335 auio.uio_resid = 0;
336 for (i = 0; i < uap->iovcnt; i++) {
337 auio.uio_resid += iov->iov_len;
338 if (auio.uio_resid < 0) {
339 error = EINVAL;
340 goto done;
341 }
342 iov++;
343 }
344#ifdef KTRACE
345 /*
346 * if tracing, save a copy of iovec
347 */
348 if (KTRPOINT(p, KTR_GENIO)) {
349 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
350 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
351 }
352#endif
353 cnt = auio.uio_resid;
354 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
355 if (auio.uio_resid != cnt && (error == ERESTART ||
356 error == EINTR || error == EWOULDBLOCK))
357 error = 0;
358 if (error == EPIPE)
359 psignal(p, SIGPIPE);
360 }
361 cnt -= auio.uio_resid;
362#ifdef KTRACE
363 if (ktriov != NULL) {
364 if (error == 0)
365 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
366 ktriov, cnt, error);
367 FREE(ktriov, M_TEMP);
368 }
369#endif
370 p->p_retval[0] = cnt;
371done:
372 if (needfree)
373 FREE(needfree, M_IOV);
374 return (error);
375}
376
377/*
378 * Ioctl system call
379 */
380#ifndef _SYS_SYSPROTO_H_
381struct ioctl_args {
382 int fd;
383 int com;
384 caddr_t data;
385};
386#endif
387/* ARGSUSED */
388int
389ioctl(p, uap)
390 struct proc *p;
391 register struct ioctl_args *uap;
392{
393 register struct file *fp;
394 register struct filedesc *fdp;
395 register int com, error;
396 register u_int size;
397 caddr_t data, memp;
398 int tmp;
399#define STK_PARAMS 128
400 char stkbuf[STK_PARAMS];
401
402 fdp = p->p_fd;
403 if ((u_int)uap->fd >= fdp->fd_nfiles ||
404 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
405 return (EBADF);
406
407 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
408 return (EBADF);
409
410 switch (com = uap->com) {
411 case FIONCLEX:
412 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
413 return (0);
414 case FIOCLEX:
415 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
416 return (0);
417 }
418
419 /*
420 * Interpret high order word to find amount of data to be
421 * copied to/from the user's address space.
422 */
423 size = IOCPARM_LEN(com);
424 if (size > IOCPARM_MAX)
425 return (ENOTTY);
426 memp = NULL;
427 if (size > sizeof (stkbuf)) {
428 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
429 data = memp;
430 } else
431 data = stkbuf;
432 if (com&IOC_IN) {
433 if (size) {
434 error = copyin(uap->data, data, (u_int)size);
435 if (error) {
436 if (memp)
437 free(memp, M_IOCTLOPS);
438 return (error);
439 }
440 } else
441 *(caddr_t *)data = uap->data;
442 } else if ((com&IOC_OUT) && size)
443 /*
444 * Zero the buffer so the user always
445 * gets back something deterministic.
446 */
447 bzero(data, size);
448 else if (com&IOC_VOID)
449 *(caddr_t *)data = uap->data;
450
451 switch (com) {
452
453 case FIONBIO:
454 if ((tmp = *(int *)data))
455 fp->f_flag |= FNONBLOCK;
456 else
457 fp->f_flag &= ~FNONBLOCK;
458 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
459 break;
460
461 case FIOASYNC:
462 if ((tmp = *(int *)data))
463 fp->f_flag |= FASYNC;
464 else
465 fp->f_flag &= ~FASYNC;
466 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
467 break;
468
469 case FIOSETOWN:
470 tmp = *(int *)data;
471 if (fp->f_type == DTYPE_SOCKET) {
472 ((struct socket *)fp->f_data)->so_pgid = tmp;
473 error = 0;
474 break;
475 }
476 if (tmp <= 0) {
477 tmp = -tmp;
478 } else {
479 struct proc *p1 = pfind(tmp);
480 if (p1 == 0) {
481 error = ESRCH;
482 break;
483 }
484 tmp = p1->p_pgrp->pg_id;
485 }
486 error = (*fp->f_ops->fo_ioctl)
487 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
488 break;
489
490 case FIOGETOWN:
491 if (fp->f_type == DTYPE_SOCKET) {
492 error = 0;
493 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
494 break;
495 }
496 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
497 *(int *)data = -*(int *)data;
498 break;
499
500 default:
501 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
502 /*
503 * Copy any data to user, size was
504 * already set and checked above.
505 */
506 if (error == 0 && (com&IOC_OUT) && size)
507 error = copyout(data, uap->data, (u_int)size);
508 break;
509 }
510 if (memp)
511 free(memp, M_IOCTLOPS);
512 return (error);
513}
514
515static int nselcoll;
516int selwait;
517
518/*
519 * Select system call.
520 */
521#ifndef _SYS_SYSPROTO_H_
522struct select_args {
523 int nd;
524 fd_set *in, *ou, *ex;
525 struct timeval *tv;
526};
527#endif
528int
529select(p, uap)
530 register struct proc *p;
531 register struct select_args *uap;
532{
533 /*
534 * The magic 2048 here is chosen to be just enough for FD_SETSIZE
535 * infds with the new FD_SETSIZE of 1024, and more than enough for
536 * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE
537 * of 256.
538 */
539 fd_mask s_selbits[howmany(2048, NFDBITS)];
540 fd_mask *ibits[3], *obits[3], *selbits, *sbp;
541 struct timeval atv;
542 int s, ncoll, error, timo;
542 int s, ncoll, error, timo, term;
543 u_int nbufbytes, ncpbytes, nfdbits;
544
545 if (uap->nd < 0)
546 return (EINVAL);
547 if (uap->nd > p->p_fd->fd_nfiles)
548 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
549
550 /*
551 * Allocate just enough bits for the non-null fd_sets. Use the
552 * preallocated auto buffer if possible.
553 */
554 nfdbits = roundup(uap->nd, NFDBITS);
555 ncpbytes = nfdbits / NBBY;
556 nbufbytes = 0;
557 if (uap->in != NULL)
558 nbufbytes += 2 * ncpbytes;
559 if (uap->ou != NULL)
560 nbufbytes += 2 * ncpbytes;
561 if (uap->ex != NULL)
562 nbufbytes += 2 * ncpbytes;
563 if (nbufbytes <= sizeof s_selbits)
564 selbits = &s_selbits[0];
565 else
566 selbits = malloc(nbufbytes, M_SELECT, M_WAITOK);
567
568 /*
569 * Assign pointers into the bit buffers and fetch the input bits.
570 * Put the output buffers together so that they can be bzeroed
571 * together.
572 */
573 sbp = selbits;
574#define getbits(name, x) \
575 do { \
576 if (uap->name == NULL) \
577 ibits[x] = NULL; \
578 else { \
579 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
580 obits[x] = sbp; \
581 sbp += ncpbytes / sizeof *sbp; \
582 error = copyin(uap->name, ibits[x], ncpbytes); \
583 if (error != 0) \
584 goto done; \
585 } \
586 } while (0)
587 getbits(in, 0);
588 getbits(ou, 1);
589 getbits(ex, 2);
590#undef getbits
591 if (nbufbytes != 0)
592 bzero(selbits, nbufbytes / 2);
593
594 if (uap->tv) {
595 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
596 sizeof (atv));
597 if (error)
598 goto done;
599 if (itimerfix(&atv)) {
600 error = EINVAL;
601 goto done;
602 }
543 u_int nbufbytes, ncpbytes, nfdbits;
544
545 if (uap->nd < 0)
546 return (EINVAL);
547 if (uap->nd > p->p_fd->fd_nfiles)
548 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
549
550 /*
551 * Allocate just enough bits for the non-null fd_sets. Use the
552 * preallocated auto buffer if possible.
553 */
554 nfdbits = roundup(uap->nd, NFDBITS);
555 ncpbytes = nfdbits / NBBY;
556 nbufbytes = 0;
557 if (uap->in != NULL)
558 nbufbytes += 2 * ncpbytes;
559 if (uap->ou != NULL)
560 nbufbytes += 2 * ncpbytes;
561 if (uap->ex != NULL)
562 nbufbytes += 2 * ncpbytes;
563 if (nbufbytes <= sizeof s_selbits)
564 selbits = &s_selbits[0];
565 else
566 selbits = malloc(nbufbytes, M_SELECT, M_WAITOK);
567
568 /*
569 * Assign pointers into the bit buffers and fetch the input bits.
570 * Put the output buffers together so that they can be bzeroed
571 * together.
572 */
573 sbp = selbits;
574#define getbits(name, x) \
575 do { \
576 if (uap->name == NULL) \
577 ibits[x] = NULL; \
578 else { \
579 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
580 obits[x] = sbp; \
581 sbp += ncpbytes / sizeof *sbp; \
582 error = copyin(uap->name, ibits[x], ncpbytes); \
583 if (error != 0) \
584 goto done; \
585 } \
586 } while (0)
587 getbits(in, 0);
588 getbits(ou, 1);
589 getbits(ex, 2);
590#undef getbits
591 if (nbufbytes != 0)
592 bzero(selbits, nbufbytes / 2);
593
594 if (uap->tv) {
595 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
596 sizeof (atv));
597 if (error)
598 goto done;
599 if (itimerfix(&atv)) {
600 error = EINVAL;
601 goto done;
602 }
603 s = splclock();
604 timevaladd(&atv, &time);
605 timo = hzto(&atv);
606 splx(s);
603 timo = tvtohz(&atv);
607 } else
608 timo = 0;
604 } else
605 timo = 0;
606 if (timo)
607 term = timo + ticks;
609retry:
610 ncoll = nselcoll;
611 p->p_flag |= P_SELECT;
612 error = selscan(p, ibits, obits, uap->nd);
613 if (error || p->p_retval[0])
614 goto done;
615 s = splhigh();
608retry:
609 ncoll = nselcoll;
610 p->p_flag |= P_SELECT;
611 error = selscan(p, ibits, obits, uap->nd);
612 if (error || p->p_retval[0])
613 goto done;
614 s = splhigh();
616 /* this should be timercmp(&time, &atv, >=) */
617 if (uap->tv && (time.tv_sec > atv.tv_sec ||
618 (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) {
615 if (timo && term <= ticks) {
619 splx(s);
620 goto done;
621 }
622 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
623 splx(s);
624 goto retry;
625 }
626 p->p_flag &= ~P_SELECT;
627 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
628 splx(s);
629 if (error == 0)
630 goto retry;
631done:
632 p->p_flag &= ~P_SELECT;
633 /* select is not restarted after signals... */
634 if (error == ERESTART)
635 error = EINTR;
636 if (error == EWOULDBLOCK)
637 error = 0;
638#define putbits(name, x) \
639 if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
640 error = error2;
641 if (error == 0) {
642 int error2;
643
644 putbits(in, 0);
645 putbits(ou, 1);
646 putbits(ex, 2);
647#undef putbits
648 }
649 if (selbits != &s_selbits[0])
650 free(selbits, M_SELECT);
651 return (error);
652}
653
654static int
655selscan(p, ibits, obits, nfd)
656 struct proc *p;
657 fd_mask **ibits, **obits;
658 int nfd;
659{
660 register struct filedesc *fdp = p->p_fd;
661 register int msk, i, j, fd;
662 register fd_mask bits;
663 struct file *fp;
664 int n = 0;
665 /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
666 static int flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
667
668 for (msk = 0; msk < 3; msk++) {
669 if (ibits[msk] == NULL)
670 continue;
671 for (i = 0; i < nfd; i += NFDBITS) {
672 bits = ibits[msk][i/NFDBITS];
673 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
674 bits &= ~(1 << j);
675 fp = fdp->fd_ofiles[fd];
676 if (fp == NULL)
677 return (EBADF);
678 if ((*fp->f_ops->fo_poll)(fp, flag[msk],
679 fp->f_cred, p)) {
680 obits[msk][(fd)/NFDBITS] |=
681 (1 << ((fd) % NFDBITS));
682 n++;
683 }
684 }
685 }
686 }
687 p->p_retval[0] = n;
688 return (0);
689}
690
691/*
692 * Poll system call.
693 */
694#ifndef _SYS_SYSPROTO_H_
695struct poll_args {
696 struct pollfd *fds;
697 u_int nfds;
698 int timeout;
699};
700#endif
701int
702poll(p, uap)
703 register struct proc *p;
704 register struct poll_args *uap;
705{
706 caddr_t bits;
707 char smallbits[32 * sizeof(struct pollfd)];
708 struct timeval atv;
616 splx(s);
617 goto done;
618 }
619 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
620 splx(s);
621 goto retry;
622 }
623 p->p_flag &= ~P_SELECT;
624 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
625 splx(s);
626 if (error == 0)
627 goto retry;
628done:
629 p->p_flag &= ~P_SELECT;
630 /* select is not restarted after signals... */
631 if (error == ERESTART)
632 error = EINTR;
633 if (error == EWOULDBLOCK)
634 error = 0;
635#define putbits(name, x) \
636 if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
637 error = error2;
638 if (error == 0) {
639 int error2;
640
641 putbits(in, 0);
642 putbits(ou, 1);
643 putbits(ex, 2);
644#undef putbits
645 }
646 if (selbits != &s_selbits[0])
647 free(selbits, M_SELECT);
648 return (error);
649}
650
651static int
652selscan(p, ibits, obits, nfd)
653 struct proc *p;
654 fd_mask **ibits, **obits;
655 int nfd;
656{
657 register struct filedesc *fdp = p->p_fd;
658 register int msk, i, j, fd;
659 register fd_mask bits;
660 struct file *fp;
661 int n = 0;
662 /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
663 static int flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
664
665 for (msk = 0; msk < 3; msk++) {
666 if (ibits[msk] == NULL)
667 continue;
668 for (i = 0; i < nfd; i += NFDBITS) {
669 bits = ibits[msk][i/NFDBITS];
670 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
671 bits &= ~(1 << j);
672 fp = fdp->fd_ofiles[fd];
673 if (fp == NULL)
674 return (EBADF);
675 if ((*fp->f_ops->fo_poll)(fp, flag[msk],
676 fp->f_cred, p)) {
677 obits[msk][(fd)/NFDBITS] |=
678 (1 << ((fd) % NFDBITS));
679 n++;
680 }
681 }
682 }
683 }
684 p->p_retval[0] = n;
685 return (0);
686}
687
688/*
689 * Poll system call.
690 */
691#ifndef _SYS_SYSPROTO_H_
692struct poll_args {
693 struct pollfd *fds;
694 u_int nfds;
695 int timeout;
696};
697#endif
698int
699poll(p, uap)
700 register struct proc *p;
701 register struct poll_args *uap;
702{
703 caddr_t bits;
704 char smallbits[32 * sizeof(struct pollfd)];
705 struct timeval atv;
709 int s, ncoll, error = 0, timo;
706 int s, ncoll, error = 0, timo, term;
710 size_t ni;
711
712 if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) {
713 /* forgiving; slightly wrong */
714 SCARG(uap, nfds) = p->p_fd->fd_nfiles;
715 }
716 ni = SCARG(uap, nfds) * sizeof(struct pollfd);
717 if (ni > sizeof(smallbits))
718 bits = malloc(ni, M_TEMP, M_WAITOK);
719 else
720 bits = smallbits;
721 error = copyin(SCARG(uap, fds), bits, ni);
722 if (error)
723 goto done;
724 if (SCARG(uap, timeout) != INFTIM) {
725 atv.tv_sec = SCARG(uap, timeout) / 1000;
726 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
727 if (itimerfix(&atv)) {
728 error = EINVAL;
729 goto done;
730 }
707 size_t ni;
708
709 if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) {
710 /* forgiving; slightly wrong */
711 SCARG(uap, nfds) = p->p_fd->fd_nfiles;
712 }
713 ni = SCARG(uap, nfds) * sizeof(struct pollfd);
714 if (ni > sizeof(smallbits))
715 bits = malloc(ni, M_TEMP, M_WAITOK);
716 else
717 bits = smallbits;
718 error = copyin(SCARG(uap, fds), bits, ni);
719 if (error)
720 goto done;
721 if (SCARG(uap, timeout) != INFTIM) {
722 atv.tv_sec = SCARG(uap, timeout) / 1000;
723 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
724 if (itimerfix(&atv)) {
725 error = EINVAL;
726 goto done;
727 }
731 s = splclock();
732 timevaladd(&atv, &time);
733 timo = hzto(&atv);
734 splx(s);
728 timo = tvtohz(&atv);
735 } else
736 timo = 0;
729 } else
730 timo = 0;
731 if (timo)
732 term = timo + ticks;
737retry:
738 ncoll = nselcoll;
739 p->p_flag |= P_SELECT;
740 error = pollscan(p, (struct pollfd *)bits, SCARG(uap, nfds));
741 if (error || p->p_retval[0])
742 goto done;
733retry:
734 ncoll = nselcoll;
735 p->p_flag |= P_SELECT;
736 error = pollscan(p, (struct pollfd *)bits, SCARG(uap, nfds));
737 if (error || p->p_retval[0])
738 goto done;
743 s = splhigh();
744 if (timo && timercmp(&time, &atv, >=)) {
739 s = splhigh();
740 if (timo && term <= ticks) {
745 splx(s);
746 goto done;
747 }
748 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
749 splx(s);
750 goto retry;
751 }
752 p->p_flag &= ~P_SELECT;
753 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
754 splx(s);
755 if (error == 0)
756 goto retry;
757done:
758 p->p_flag &= ~P_SELECT;
759 /* poll is not restarted after signals... */
760 if (error == ERESTART)
761 error = EINTR;
762 if (error == EWOULDBLOCK)
763 error = 0;
764 if (error == 0) {
765 error = copyout(bits, SCARG(uap, fds), ni);
766 if (error)
767 goto out;
768 }
769out:
770 if (ni > sizeof(smallbits))
771 free(bits, M_TEMP);
772 return (error);
773}
774
775static int
776pollscan(p, fds, nfd)
777 struct proc *p;
778 struct pollfd *fds;
779 int nfd;
780{
781 register struct filedesc *fdp = p->p_fd;
782 int i;
783 struct file *fp;
784 int n = 0;
785
786 for (i = 0; i < nfd; i++, fds++) {
787 if ((u_int)fds->fd >= fdp->fd_nfiles) {
788 fds->revents = POLLNVAL;
789 n++;
790 } else {
791 fp = fdp->fd_ofiles[fds->fd];
792 if (fp == 0) {
793 fds->revents = POLLNVAL;
794 n++;
795 } else {
796 /*
797 * Note: backend also returns POLLHUP and
798 * POLLERR if appropriate.
799 */
800 fds->revents = (*fp->f_ops->fo_poll)(fp,
801 fds->events, fp->f_cred, p);
802 if (fds->revents != 0)
803 n++;
804 }
805 }
806 }
807 p->p_retval[0] = n;
808 return (0);
809}
810
811/*
812 * OpenBSD poll system call.
813 * XXX this isn't quite a true representation.. OpenBSD uses select ops.
814 */
815#ifndef _SYS_SYSPROTO_H_
816struct openbsd_poll_args {
817 struct pollfd *fds;
818 u_int nfds;
819 int timeout;
820};
821#endif
822int
823openbsd_poll(p, uap)
824 register struct proc *p;
825 register struct openbsd_poll_args *uap;
826{
827 return (poll(p, (struct poll_args *)uap));
828}
829
830/*ARGSUSED*/
831int
832seltrue(dev, events, p)
833 dev_t dev;
834 int events;
835 struct proc *p;
836{
837
838 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
839}
840
841/*
842 * Record a select request.
843 */
844void
845selrecord(selector, sip)
846 struct proc *selector;
847 struct selinfo *sip;
848{
849 struct proc *p;
850 pid_t mypid;
851
852 mypid = selector->p_pid;
853 if (sip->si_pid == mypid)
854 return;
855 if (sip->si_pid && (p = pfind(sip->si_pid)) &&
856 p->p_wchan == (caddr_t)&selwait)
857 sip->si_flags |= SI_COLL;
858 else
859 sip->si_pid = mypid;
860}
861
862/*
863 * Do a wakeup when a selectable event occurs.
864 */
865void
866selwakeup(sip)
867 register struct selinfo *sip;
868{
869 register struct proc *p;
870 int s;
871
872 if (sip->si_pid == 0)
873 return;
874 if (sip->si_flags & SI_COLL) {
875 nselcoll++;
876 sip->si_flags &= ~SI_COLL;
877 wakeup((caddr_t)&selwait);
878 }
879 p = pfind(sip->si_pid);
880 sip->si_pid = 0;
881 if (p != NULL) {
882 s = splhigh();
883 if (p->p_wchan == (caddr_t)&selwait) {
884 if (p->p_stat == SSLEEP)
885 setrunnable(p);
886 else
887 unsleep(p);
888 } else if (p->p_flag & P_SELECT)
889 p->p_flag &= ~P_SELECT;
890 splx(s);
891 }
892}
741 splx(s);
742 goto done;
743 }
744 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
745 splx(s);
746 goto retry;
747 }
748 p->p_flag &= ~P_SELECT;
749 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
750 splx(s);
751 if (error == 0)
752 goto retry;
753done:
754 p->p_flag &= ~P_SELECT;
755 /* poll is not restarted after signals... */
756 if (error == ERESTART)
757 error = EINTR;
758 if (error == EWOULDBLOCK)
759 error = 0;
760 if (error == 0) {
761 error = copyout(bits, SCARG(uap, fds), ni);
762 if (error)
763 goto out;
764 }
765out:
766 if (ni > sizeof(smallbits))
767 free(bits, M_TEMP);
768 return (error);
769}
770
771static int
772pollscan(p, fds, nfd)
773 struct proc *p;
774 struct pollfd *fds;
775 int nfd;
776{
777 register struct filedesc *fdp = p->p_fd;
778 int i;
779 struct file *fp;
780 int n = 0;
781
782 for (i = 0; i < nfd; i++, fds++) {
783 if ((u_int)fds->fd >= fdp->fd_nfiles) {
784 fds->revents = POLLNVAL;
785 n++;
786 } else {
787 fp = fdp->fd_ofiles[fds->fd];
788 if (fp == 0) {
789 fds->revents = POLLNVAL;
790 n++;
791 } else {
792 /*
793 * Note: backend also returns POLLHUP and
794 * POLLERR if appropriate.
795 */
796 fds->revents = (*fp->f_ops->fo_poll)(fp,
797 fds->events, fp->f_cred, p);
798 if (fds->revents != 0)
799 n++;
800 }
801 }
802 }
803 p->p_retval[0] = n;
804 return (0);
805}
806
807/*
808 * OpenBSD poll system call.
809 * XXX this isn't quite a true representation.. OpenBSD uses select ops.
810 */
811#ifndef _SYS_SYSPROTO_H_
812struct openbsd_poll_args {
813 struct pollfd *fds;
814 u_int nfds;
815 int timeout;
816};
817#endif
818int
819openbsd_poll(p, uap)
820 register struct proc *p;
821 register struct openbsd_poll_args *uap;
822{
823 return (poll(p, (struct poll_args *)uap));
824}
825
826/*ARGSUSED*/
827int
828seltrue(dev, events, p)
829 dev_t dev;
830 int events;
831 struct proc *p;
832{
833
834 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
835}
836
837/*
838 * Record a select request.
839 */
840void
841selrecord(selector, sip)
842 struct proc *selector;
843 struct selinfo *sip;
844{
845 struct proc *p;
846 pid_t mypid;
847
848 mypid = selector->p_pid;
849 if (sip->si_pid == mypid)
850 return;
851 if (sip->si_pid && (p = pfind(sip->si_pid)) &&
852 p->p_wchan == (caddr_t)&selwait)
853 sip->si_flags |= SI_COLL;
854 else
855 sip->si_pid = mypid;
856}
857
858/*
859 * Do a wakeup when a selectable event occurs.
860 */
861void
862selwakeup(sip)
863 register struct selinfo *sip;
864{
865 register struct proc *p;
866 int s;
867
868 if (sip->si_pid == 0)
869 return;
870 if (sip->si_flags & SI_COLL) {
871 nselcoll++;
872 sip->si_flags &= ~SI_COLL;
873 wakeup((caddr_t)&selwait);
874 }
875 p = pfind(sip->si_pid);
876 sip->si_pid = 0;
877 if (p != NULL) {
878 s = splhigh();
879 if (p->p_wchan == (caddr_t)&selwait) {
880 if (p->p_stat == SSLEEP)
881 setrunnable(p);
882 else
883 unsleep(p);
884 } else if (p->p_flag & P_SELECT)
885 p->p_flag &= ~P_SELECT;
886 splx(s);
887 }
888}