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