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