guard against negative fd counts in select
[unix-history] / usr / src / sys / kern / sys_generic.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
a298f08c 7 * @(#)sys_generic.c 7.39 (Berkeley) %G%
da7c5cc6 8 */
ffe28cfe 9
38a01dbe
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/filedesc.h>
13#include <sys/ioctl.h>
14#include <sys/file.h>
15#include <sys/proc.h>
16#include <sys/socketvar.h>
17#include <sys/uio.h>
18#include <sys/kernel.h>
19#include <sys/stat.h>
20#include <sys/malloc.h>
46814581 21#ifdef KTRACE
38a01dbe 22#include <sys/ktrace.h>
46814581 23#endif
ffe28cfe
BJ
24
25/*
26 * Read system call.
27 */
1d369105
CT
28struct read_args {
29 int fdes;
30 char *cbuf;
31 unsigned count;
32};
25ed1cf1 33/* ARGSUSED */
c9714ae3
KM
34read(p, uap, retval)
35 struct proc *p;
1d369105 36 register struct read_args *uap;
c9714ae3
KM
37 int *retval;
38{
c4ec2128 39 register struct file *fp;
5e00df3b 40 register struct filedesc *fdp = p->p_fd;
32a43ee2
BJ
41 struct uio auio;
42 struct iovec aiov;
c4ec2128
KM
43 long cnt, error = 0;
44#ifdef KTRACE
45 struct iovec ktriov;
46#endif
ffe28cfe 47
8429d022 48 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
43ed8e9d 49 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
c4ec2128 50 (fp->f_flag & FREAD) == 0)
d9c2f47f 51 return (EBADF);
32a43ee2
BJ
52 aiov.iov_base = (caddr_t)uap->cbuf;
53 aiov.iov_len = uap->count;
54 auio.uio_iov = &aiov;
55 auio.uio_iovcnt = 1;
c4ec2128
KM
56 auio.uio_resid = uap->count;
57 auio.uio_rw = UIO_READ;
58 auio.uio_segflg = UIO_USERSPACE;
221dba7d 59 auio.uio_procp = p;
c4ec2128
KM
60#ifdef KTRACE
61 /*
62 * if tracing, save a copy of iovec
63 */
c9714ae3 64 if (KTRPOINT(p, KTR_GENIO))
c4ec2128
KM
65 ktriov = aiov;
66#endif
67 cnt = uap->count;
9754d709
MK
68 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
69 if (auio.uio_resid != cnt && (error == ERESTART ||
70 error == EINTR || error == EWOULDBLOCK))
71 error = 0;
c4ec2128
KM
72 cnt -= auio.uio_resid;
73#ifdef KTRACE
c9714ae3 74 if (KTRPOINT(p, KTR_GENIO) && error == 0)
51322105 75 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
c4ec2128 76#endif
c9714ae3 77 *retval = cnt;
d9c2f47f 78 return (error);
b9429893
BJ
79}
80
c9714ae3
KM
81/*
82 * Scatter read system call.
83 */
1d369105
CT
84struct readv_args {
85 int fdes;
86 struct iovec *iovp;
87 unsigned iovcnt;
88};
c9714ae3
KM
89readv(p, uap, retval)
90 struct proc *p;
1d369105 91 register struct readv_args *uap;
c9714ae3
KM
92 int *retval;
93{
c4ec2128 94 register struct file *fp;
5e00df3b 95 register struct filedesc *fdp = p->p_fd;
b9429893 96 struct uio auio;
c4ec2128 97 register struct iovec *iov;
7b7210d3 98 struct iovec *needfree;
c4ec2128
KM
99 struct iovec aiov[UIO_SMALLIOV];
100 long i, cnt, error = 0;
c9773de9 101 unsigned iovlen;
c4ec2128
KM
102#ifdef KTRACE
103 struct iovec *ktriov = NULL;
104#endif
b9429893 105
8429d022 106 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
43ed8e9d 107 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
c4ec2128 108 (fp->f_flag & FREAD) == 0)
d9c2f47f 109 return (EBADF);
c9773de9
MK
110 /* note: can't use iovlen until iovcnt is validated */
111 iovlen = uap->iovcnt * sizeof (struct iovec);
46814581 112 if (uap->iovcnt > UIO_SMALLIOV) {
c4ec2128 113 if (uap->iovcnt > UIO_MAXIOV)
d9c2f47f 114 return (EINVAL);
c9773de9 115 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
7b7210d3
CT
116 needfree = iov;
117 } else {
46814581 118 iov = aiov;
7b7210d3
CT
119 needfree = NULL;
120 }
46814581 121 auio.uio_iov = iov;
b9429893 122 auio.uio_iovcnt = uap->iovcnt;
c4ec2128
KM
123 auio.uio_rw = UIO_READ;
124 auio.uio_segflg = UIO_USERSPACE;
221dba7d 125 auio.uio_procp = p;
c9773de9 126 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
46814581 127 goto done;
c4ec2128
KM
128 auio.uio_resid = 0;
129 for (i = 0; i < uap->iovcnt; i++) {
130 if (iov->iov_len < 0) {
131 error = EINVAL;
132 goto done;
133 }
134 auio.uio_resid += iov->iov_len;
135 if (auio.uio_resid < 0) {
136 error = EINVAL;
137 goto done;
138 }
139 iov++;
140 }
141#ifdef KTRACE
142 /*
143 * if tracing, save a copy of iovec
144 */
c9714ae3 145 if (KTRPOINT(p, KTR_GENIO)) {
c4ec2128
KM
146 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
147 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
148 }
149#endif
150 cnt = auio.uio_resid;
9754d709
MK
151 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
152 if (auio.uio_resid != cnt && (error == ERESTART ||
153 error == EINTR || error == EWOULDBLOCK))
154 error = 0;
c4ec2128
KM
155 cnt -= auio.uio_resid;
156#ifdef KTRACE
157 if (ktriov != NULL) {
e64d087d 158 if (error == 0)
51322105
KM
159 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
160 cnt, error);
c4ec2128
KM
161 FREE(ktriov, M_TEMP);
162 }
163#endif
c9714ae3 164 *retval = cnt;
46814581 165done:
7b7210d3
CT
166 if (needfree)
167 FREE(needfree, M_IOV);
d9c2f47f 168 return (error);
ffe28cfe
BJ
169}
170
171/*
172 * Write system call
173 */
1d369105
CT
174struct write_args {
175 int fdes;
176 char *cbuf;
177 unsigned count;
178};
c9714ae3
KM
179write(p, uap, retval)
180 struct proc *p;
1d369105 181 register struct write_args *uap;
c9714ae3
KM
182 int *retval;
183{
c4ec2128 184 register struct file *fp;
5e00df3b 185 register struct filedesc *fdp = p->p_fd;
b9429893
BJ
186 struct uio auio;
187 struct iovec aiov;
c4ec2128
KM
188 long cnt, error = 0;
189#ifdef KTRACE
190 struct iovec ktriov;
191#endif
ffe28cfe 192
8429d022 193 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
43ed8e9d 194 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
c4ec2128 195 (fp->f_flag & FWRITE) == 0)
d9c2f47f 196 return (EBADF);
c4ec2128
KM
197 aiov.iov_base = (caddr_t)uap->cbuf;
198 aiov.iov_len = uap->count;
b9429893
BJ
199 auio.uio_iov = &aiov;
200 auio.uio_iovcnt = 1;
c4ec2128
KM
201 auio.uio_resid = uap->count;
202 auio.uio_rw = UIO_WRITE;
203 auio.uio_segflg = UIO_USERSPACE;
221dba7d 204 auio.uio_procp = p;
c4ec2128
KM
205#ifdef KTRACE
206 /*
207 * if tracing, save a copy of iovec
208 */
c9714ae3 209 if (KTRPOINT(p, KTR_GENIO))
c4ec2128
KM
210 ktriov = aiov;
211#endif
212 cnt = uap->count;
9754d709
MK
213 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
214 if (auio.uio_resid != cnt && (error == ERESTART ||
215 error == EINTR || error == EWOULDBLOCK))
216 error = 0;
217 if (error == EPIPE)
c9714ae3 218 psignal(p, SIGPIPE);
9754d709 219 }
c4ec2128
KM
220 cnt -= auio.uio_resid;
221#ifdef KTRACE
c9714ae3
KM
222 if (KTRPOINT(p, KTR_GENIO) && error == 0)
223 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
51322105 224 &ktriov, cnt, error);
c4ec2128 225#endif
c9714ae3 226 *retval = cnt;
d9c2f47f 227 return (error);
b9429893
BJ
228}
229
c9714ae3
KM
230/*
231 * Gather write system call
232 */
1d369105
CT
233struct writev_args {
234 int fdes;
235 struct iovec *iovp;
236 unsigned iovcnt;
237};
c9714ae3
KM
238writev(p, uap, retval)
239 struct proc *p;
1d369105 240 register struct writev_args *uap;
c9714ae3
KM
241 int *retval;
242{
c4ec2128 243 register struct file *fp;
5e00df3b 244 register struct filedesc *fdp = p->p_fd;
b9429893 245 struct uio auio;
c4ec2128 246 register struct iovec *iov;
7b7210d3 247 struct iovec *needfree;
c4ec2128
KM
248 struct iovec aiov[UIO_SMALLIOV];
249 long i, cnt, error = 0;
c9773de9 250 unsigned iovlen;
c4ec2128
KM
251#ifdef KTRACE
252 struct iovec *ktriov = NULL;
253#endif
b9429893 254
8429d022 255 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
43ed8e9d 256 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
c4ec2128 257 (fp->f_flag & FWRITE) == 0)
d9c2f47f 258 return (EBADF);
c9773de9
MK
259 /* note: can't use iovlen until iovcnt is validated */
260 iovlen = uap->iovcnt * sizeof (struct iovec);
46814581 261 if (uap->iovcnt > UIO_SMALLIOV) {
c4ec2128 262 if (uap->iovcnt > UIO_MAXIOV)
d9c2f47f 263 return (EINVAL);
c9773de9 264 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
7b7210d3
CT
265 needfree = iov;
266 } else {
46814581 267 iov = aiov;
7b7210d3
CT
268 needfree = NULL;
269 }
46814581 270 auio.uio_iov = iov;
b9429893 271 auio.uio_iovcnt = uap->iovcnt;
c4ec2128
KM
272 auio.uio_rw = UIO_WRITE;
273 auio.uio_segflg = UIO_USERSPACE;
221dba7d 274 auio.uio_procp = p;
c9773de9 275 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
46814581 276 goto done;
c4ec2128
KM
277 auio.uio_resid = 0;
278 for (i = 0; i < uap->iovcnt; i++) {
b9429893 279 if (iov->iov_len < 0) {
c4ec2128
KM
280 error = EINVAL;
281 goto done;
b9429893 282 }
c4ec2128
KM
283 auio.uio_resid += iov->iov_len;
284 if (auio.uio_resid < 0) {
285 error = EINVAL;
286 goto done;
b9429893 287 }
2a0114a8 288 iov++;
b9429893 289 }
46814581 290#ifdef KTRACE
c4ec2128
KM
291 /*
292 * if tracing, save a copy of iovec
293 */
c9714ae3 294 if (KTRPOINT(p, KTR_GENIO)) {
46814581 295 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
c4ec2128 296 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
46814581
MK
297 }
298#endif
c4ec2128 299 cnt = auio.uio_resid;
9754d709
MK
300 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
301 if (auio.uio_resid != cnt && (error == ERESTART ||
302 error == EINTR || error == EWOULDBLOCK))
303 error = 0;
304 if (error == EPIPE)
c9714ae3 305 psignal(p, SIGPIPE);
9754d709 306 }
c4ec2128 307 cnt -= auio.uio_resid;
46814581
MK
308#ifdef KTRACE
309 if (ktriov != NULL) {
e64d087d 310 if (error == 0)
c9714ae3 311 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
51322105 312 ktriov, cnt, error);
46814581
MK
313 FREE(ktriov, M_TEMP);
314 }
315#endif
c9714ae3 316 *retval = cnt;
c4ec2128 317done:
7b7210d3
CT
318 if (needfree)
319 FREE(needfree, M_IOV);
d9c2f47f 320 return (error);
4147b3f6 321}
ffe28cfe
BJ
322
323/*
324 * Ioctl system call
ffe28cfe 325 */
1d369105
CT
326struct ioctl_args {
327 int fdes;
328 int cmd;
329 caddr_t cmarg;
330};
c9714ae3
KM
331/* ARGSUSED */
332ioctl(p, uap, retval)
333 struct proc *p;
1d369105 334 register struct ioctl_args *uap;
c9714ae3
KM
335 int *retval;
336{
337 register struct file *fp;
5e00df3b 338 register struct filedesc *fdp = p->p_fd;
9754d709 339 register int com, error;
b9429893 340 register u_int size;
e0b18aec 341 caddr_t memp = 0;
c0bb7b0e 342#define STK_PARAMS 128
08eb908c
MK
343 char stkbuf[STK_PARAMS];
344 caddr_t data = stkbuf;
221dba7d 345 int tmp;
ffe28cfe 346
8429d022 347 if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
43ed8e9d 348 (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
d9c2f47f 349 return (EBADF);
9754d709 350 if ((fp->f_flag & (FREAD|FWRITE)) == 0)
d9c2f47f 351 return (EBADF);
4b72e2f9
SL
352 com = uap->cmd;
353
4b72e2f9 354 if (com == FIOCLEX) {
43ed8e9d 355 fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
d9c2f47f 356 return (0);
ffe28cfe 357 }
4b72e2f9 358 if (com == FIONCLEX) {
43ed8e9d 359 fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
d9c2f47f 360 return (0);
ffe28cfe 361 }
4b72e2f9
SL
362
363 /*
364 * Interpret high order word to find
365 * amount of data to be copied to/from the
366 * user's address space.
4b72e2f9 367 */
c0bb7b0e 368 size = IOCPARM_LEN(com);
9754d709 369 if (size > IOCPARM_MAX)
d9c2f47f 370 return (ENOTTY);
08eb908c 371 if (size > sizeof (stkbuf)) {
f452da3a 372 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
e0b18aec 373 data = memp;
c0bb7b0e 374 }
471f17ed
SL
375 if (com&IOC_IN) {
376 if (size) {
9754d709
MK
377 error = copyin(uap->cmarg, data, (u_int)size);
378 if (error) {
e0b18aec
KM
379 if (memp)
380 free(memp, M_IOCTLOPS);
d9c2f47f 381 return (error);
e0b18aec 382 }
471f17ed
SL
383 } else
384 *(caddr_t *)data = uap->cmarg;
385 } else if ((com&IOC_OUT) && size)
386 /*
46814581
MK
387 * Zero the buffer so the user always
388 * gets back something deterministic.
471f17ed 389 */
c0bb7b0e 390 bzero(data, size);
a76b60f6
SL
391 else if (com&IOC_VOID)
392 *(caddr_t *)data = uap->cmarg;
4b72e2f9 393
88a7a62a
SL
394 switch (com) {
395
396 case FIONBIO:
221dba7d 397 if (tmp = *(int *)data)
93080c46 398 fp->f_flag |= FNONBLOCK;
221dba7d 399 else
93080c46 400 fp->f_flag &= ~FNONBLOCK;
221dba7d 401 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
c0bb7b0e 402 break;
88a7a62a
SL
403
404 case FIOASYNC:
221dba7d
KM
405 if (tmp = *(int *)data)
406 fp->f_flag |= FASYNC;
407 else
408 fp->f_flag &= ~FASYNC;
409 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
c0bb7b0e 410 break;
88a7a62a
SL
411
412 case FIOSETOWN:
221dba7d
KM
413 tmp = *(int *)data;
414 if (fp->f_type == DTYPE_SOCKET) {
415 ((struct socket *)fp->f_data)->so_pgid = tmp;
416 error = 0;
417 break;
418 }
419 if (tmp <= 0) {
420 tmp = -tmp;
421 } else {
422 struct proc *p1 = pfind(tmp);
423 if (p1 == 0) {
424 error = ESRCH;
425 break;
426 }
427 tmp = p1->p_pgrp->pg_id;
428 }
429 error = (*fp->f_ops->fo_ioctl)
430 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
c0bb7b0e 431 break;
4b72e2f9 432
88a7a62a 433 case FIOGETOWN:
221dba7d
KM
434 if (fp->f_type == DTYPE_SOCKET) {
435 error = 0;
436 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
437 break;
438 }
439 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
440 *(int *)data = -*(int *)data;
c0bb7b0e 441 break;
221dba7d 442
c0bb7b0e 443 default:
8429d022 444 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
c0bb7b0e
MK
445 /*
446 * Copy any data to user, size was
447 * already set and checked above.
448 */
9754d709
MK
449 if (error == 0 && (com&IOC_OUT) && size)
450 error = copyout(data, uap->cmarg, (u_int)size);
c0bb7b0e 451 break;
88a7a62a 452 }
e0b18aec
KM
453 if (memp)
454 free(memp, M_IOCTLOPS);
d9c2f47f 455 return (error);
ffe28cfe
BJ
456}
457
44adcf01 458int selwait, nselcoll;
d441e5bc 459
ffe28cfe 460/*
88a7a62a 461 * Select system call.
ffe28cfe 462 */
1d369105 463struct select_args {
a298f08c 464 u_int nd;
1d369105
CT
465 fd_set *in, *ou, *ex;
466 struct timeval *tv;
467};
c9714ae3
KM
468select(p, uap, retval)
469 register struct proc *p;
1d369105 470 register struct select_args *uap;
c9714ae3
KM
471 int *retval;
472{
b8e71e77 473 fd_set ibits[3], obits[3];
88a7a62a 474 struct timeval atv;
a298f08c
KM
475 int s, ncoll, error = 0, timo;
476 u_int ni;
88a7a62a 477
01b0e233
MK
478 bzero((caddr_t)ibits, sizeof(ibits));
479 bzero((caddr_t)obits, sizeof(obits));
a298f08c
KM
480 if (uap->nd > FD_SETSIZE)
481 return (EINVAL);
8429d022
MK
482 if (uap->nd > p->p_fd->fd_nfiles)
483 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
a298f08c 484 ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
88a7a62a
SL
485
486#define getbits(name, x) \
a298f08c
KM
487 if (uap->name && \
488 (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \
489 goto done;
88a7a62a
SL
490 getbits(in, 0);
491 getbits(ou, 1);
492 getbits(ex, 2);
493#undef getbits
494
495 if (uap->tv) {
9754d709 496 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
88a7a62a 497 sizeof (atv));
9754d709 498 if (error)
88a7a62a
SL
499 goto done;
500 if (itimerfix(&atv)) {
9754d709 501 error = EINVAL;
88a7a62a
SL
502 goto done;
503 }
2b6d0fc1
CT
504 s = splclock();
505 timevaladd(&atv, (struct timeval *)&time);
9754d709 506 timo = hzto(&atv);
4fc80098
KM
507 /*
508 * Avoid inadvertently sleeping forever.
509 */
510 if (timo == 0)
511 timo = 1;
856f902f 512 splx(s);
9754d709
MK
513 } else
514 timo = 0;
88a7a62a
SL
515retry:
516 ncoll = nselcoll;
c9714ae3 517 p->p_flag |= SSEL;
8429d022 518 error = selscan(p, ibits, obits, uap->nd, retval);
c9714ae3 519 if (error || *retval)
88a7a62a 520 goto done;
c4e1f1e5 521 s = splhigh();
e394e134
SL
522 /* this should be timercmp(&time, &atv, >=) */
523 if (uap->tv && (time.tv_sec > atv.tv_sec ||
524 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
88a7a62a
SL
525 splx(s);
526 goto done;
527 }
c9714ae3 528 if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
88a7a62a
SL
529 splx(s);
530 goto retry;
531 }
c9714ae3 532 p->p_flag &= ~SSEL;
9754d709 533 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
88a7a62a 534 splx(s);
9754d709
MK
535 if (error == 0)
536 goto retry;
88a7a62a 537done:
c9714ae3 538 p->p_flag &= ~SSEL;
9754d709
MK
539 /* select is not restarted after signals... */
540 if (error == ERESTART)
541 error = EINTR;
542 if (error == EWOULDBLOCK)
543 error = 0;
88a7a62a 544#define putbits(name, x) \
a298f08c
KM
545 if (uap->name && \
546 (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \
547 error = error2;
9754d709 548 if (error == 0) {
a298f08c
KM
549 int error2;
550
79f403fc
MK
551 putbits(in, 0);
552 putbits(ou, 1);
553 putbits(ex, 2);
88a7a62a 554#undef putbits
79f403fc 555 }
d9c2f47f 556 return (error);
88a7a62a
SL
557}
558
8429d022
MK
559selscan(p, ibits, obits, nfd, retval)
560 struct proc *p;
b8e71e77 561 fd_set *ibits, *obits;
c9714ae3 562 int nfd, *retval;
88a7a62a 563{
8429d022 564 register struct filedesc *fdp = p->p_fd;
7b7210d3 565 register int msk, i, j, fd;
b8e71e77 566 register fd_mask bits;
88a7a62a 567 struct file *fp;
7b7210d3
CT
568 int n = 0;
569 static int flag[3] = { FREAD, FWRITE, 0 };
88a7a62a 570
7b7210d3 571 for (msk = 0; msk < 3; msk++) {
b8e71e77 572 for (i = 0; i < nfd; i += NFDBITS) {
7b7210d3
CT
573 bits = ibits[msk].fds_bits[i/NFDBITS];
574 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
d441e5bc 575 bits &= ~(1 << j);
7b7210d3
CT
576 fp = fdp->fd_ofiles[fd];
577 if (fp == NULL)
578 return (EBADF);
579 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
580 FD_SET(fd, &obits[msk]);
d441e5bc
MK
581 n++;
582 }
88a7a62a
SL
583 }
584 }
585 }
c9714ae3 586 *retval = n;
7b7210d3 587 return (0);
88a7a62a
SL
588}
589
ffe28cfe 590/*ARGSUSED*/
8429d022 591seltrue(dev, flag, p)
88a7a62a
SL
592 dev_t dev;
593 int flag;
8429d022 594 struct proc *p;
ffe28cfe
BJ
595{
596
88a7a62a 597 return (1);
ffe28cfe 598}
1edb1cf8 599
4a4fcc2c
KM
600/*
601 * Record a select request.
602 */
603void
604selrecord(selector, sip)
605 struct proc *selector;
606 struct selinfo *sip;
607{
608 struct proc *p;
609 pid_t mypid;
610
611 mypid = selector->p_pid;
612 if (sip->si_pid == mypid)
613 return;
614 if (sip->si_pid && (p = pfind(sip->si_pid)) &&
615 p->p_wchan == (caddr_t)&selwait)
616 sip->si_flags |= SI_COLL;
617 else
618 sip->si_pid = mypid;
619}
620
621/*
622 * Do a wakeup when a selectable event occurs.
623 */
624void
625selwakeup(sip)
626 register struct selinfo *sip;
1edb1cf8 627{
4a4fcc2c
KM
628 register struct proc *p;
629 int s;
1edb1cf8 630
4a4fcc2c
KM
631 if (sip->si_pid == 0)
632 return;
633 if (sip->si_flags & SI_COLL) {
88a7a62a 634 nselcoll++;
4a4fcc2c 635 sip->si_flags &= ~SI_COLL;
88a7a62a
SL
636 wakeup((caddr_t)&selwait);
637 }
9c2b41ec
KM
638 p = pfind(sip->si_pid);
639 sip->si_pid = 0;
640 if (p != NULL) {
4a4fcc2c 641 s = splhigh();
6bc3aba9
MK
642 if (p->p_wchan == (caddr_t)&selwait) {
643 if (p->p_stat == SSLEEP)
644 setrun(p);
645 else
646 unsleep(p);
647 } else if (p->p_flag & SSEL)
88a7a62a
SL
648 p->p_flag &= ~SSEL;
649 splx(s);
650 }
1edb1cf8 651}