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