123384Smckusick /*
263865Sbostic * Copyright (c) 1982, 1986, 1989, 1993
363865Sbostic * The Regents of the University of California. All rights reserved.
465771Sbostic * (c) UNIX System Laboratories, Inc.
565771Sbostic * All or some portions of this file are derived from material licensed
665771Sbostic * to the University of California by American Telephone and Telegraph
765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865771Sbostic * the permission of UNIX System Laboratories, Inc.
923384Smckusick *
1044444Sbostic * %sccs.include.redist.c%
1137728Smckusick *
12*68316Scgd * @(#)sys_generic.c 8.9 (Berkeley) 02/14/95
1323384Smckusick */
147423Sroot
1556517Sbostic #include <sys/param.h>
1656517Sbostic #include <sys/systm.h>
1756517Sbostic #include <sys/filedesc.h>
1856517Sbostic #include <sys/ioctl.h>
1956517Sbostic #include <sys/file.h>
2056517Sbostic #include <sys/proc.h>
2156517Sbostic #include <sys/socketvar.h>
2256517Sbostic #include <sys/uio.h>
2356517Sbostic #include <sys/kernel.h>
2456517Sbostic #include <sys/stat.h>
2556517Sbostic #include <sys/malloc.h>
2637127Skarels #ifdef KTRACE
2756517Sbostic #include <sys/ktrace.h>
2837127Skarels #endif
297423Sroot
30*68316Scgd #include <sys/mount.h>
31*68316Scgd #include <sys/syscallargs.h>
32*68316Scgd
337423Sroot /*
347423Sroot * Read system call.
357423Sroot */
3645122Sbostic /* ARGSUSED */
37*68316Scgd int
read(p,uap,retval)3842922Smckusick read(p, uap, retval)
3942922Smckusick struct proc *p;
40*68316Scgd register struct read_args /* {
41*68316Scgd syscallarg(int) fd;
42*68316Scgd syscallarg(char *) buf;
43*68316Scgd syscallarg(u_int) nbyte;
44*68316Scgd } */ *uap;
45*68316Scgd register_t *retval;
4642922Smckusick {
4737728Smckusick register struct file *fp;
4845914Smckusick register struct filedesc *fdp = p->p_fd;
497746Sroot struct uio auio;
507746Sroot struct iovec aiov;
5137728Smckusick long cnt, error = 0;
5237728Smckusick #ifdef KTRACE
5337728Smckusick struct iovec ktriov;
5437728Smckusick #endif
557423Sroot
56*68316Scgd if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
57*68316Scgd (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
5837728Smckusick (fp->f_flag & FREAD) == 0)
5944405Skarels return (EBADF);
60*68316Scgd aiov.iov_base = (caddr_t)SCARG(uap, buf);
61*68316Scgd aiov.iov_len = SCARG(uap, nbyte);
627820Sroot auio.uio_iov = &aiov;
637820Sroot auio.uio_iovcnt = 1;
64*68316Scgd auio.uio_resid = SCARG(uap, nbyte);
6537728Smckusick auio.uio_rw = UIO_READ;
6637728Smckusick auio.uio_segflg = UIO_USERSPACE;
6748027Smckusick auio.uio_procp = p;
6837728Smckusick #ifdef KTRACE
6937728Smckusick /*
7037728Smckusick * if tracing, save a copy of iovec
7137728Smckusick */
7242922Smckusick if (KTRPOINT(p, KTR_GENIO))
7337728Smckusick ktriov = aiov;
7437728Smckusick #endif
75*68316Scgd cnt = SCARG(uap, nbyte);
7640703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
7740703Skarels if (auio.uio_resid != cnt && (error == ERESTART ||
7840703Skarels error == EINTR || error == EWOULDBLOCK))
7940703Skarels error = 0;
8037728Smckusick cnt -= auio.uio_resid;
8137728Smckusick #ifdef KTRACE
8242922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0)
83*68316Scgd ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
84*68316Scgd cnt, error);
8537728Smckusick #endif
8642922Smckusick *retval = cnt;
8744405Skarels return (error);
887820Sroot }
897820Sroot
9042922Smckusick /*
9142922Smckusick * Scatter read system call.
9242922Smckusick */
93*68316Scgd int
readv(p,uap,retval)9442922Smckusick readv(p, uap, retval)
9542922Smckusick struct proc *p;
96*68316Scgd register struct readv_args /* {
97*68316Scgd syscallarg(int) fd;
98*68316Scgd syscallarg(struct iovec *) iovp;
99*68316Scgd syscallarg(u_int) iovcnt;
100*68316Scgd } */ *uap;
101*68316Scgd register_t *retval;
10242922Smckusick {
10337728Smckusick register struct file *fp;
10445914Smckusick register struct filedesc *fdp = p->p_fd;
1057820Sroot struct uio auio;
10637728Smckusick register struct iovec *iov;
10752481Storek struct iovec *needfree;
10837728Smckusick struct iovec aiov[UIO_SMALLIOV];
10937728Smckusick long i, cnt, error = 0;
11064409Sbostic u_int iovlen;
11137728Smckusick #ifdef KTRACE
11237728Smckusick struct iovec *ktriov = NULL;
11337728Smckusick #endif
1147820Sroot
115*68316Scgd if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
116*68316Scgd (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
11737728Smckusick (fp->f_flag & FREAD) == 0)
11844405Skarels return (EBADF);
11944939Skarels /* note: can't use iovlen until iovcnt is validated */
120*68316Scgd iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
121*68316Scgd if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
122*68316Scgd if (SCARG(uap, iovcnt) > UIO_MAXIOV)
12344405Skarels return (EINVAL);
12444939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
12552481Storek needfree = iov;
12652481Storek } else {
12737127Skarels iov = aiov;
12852481Storek needfree = NULL;
12952481Storek }
13037127Skarels auio.uio_iov = iov;
131*68316Scgd auio.uio_iovcnt = SCARG(uap, iovcnt);
13237728Smckusick auio.uio_rw = UIO_READ;
13337728Smckusick auio.uio_segflg = UIO_USERSPACE;
13448027Smckusick auio.uio_procp = p;
135*68316Scgd if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
13637127Skarels goto done;
13737728Smckusick auio.uio_resid = 0;
138*68316Scgd for (i = 0; i < SCARG(uap, iovcnt); i++) {
13967491Smckusick if (auio.uio_resid + iov->iov_len < auio.uio_resid) {
14037728Smckusick error = EINVAL;
14137728Smckusick goto done;
14237728Smckusick }
14337728Smckusick auio.uio_resid += iov->iov_len;
14437728Smckusick iov++;
14537728Smckusick }
14637728Smckusick #ifdef KTRACE
14737728Smckusick /*
14837728Smckusick * if tracing, save a copy of iovec
14937728Smckusick */
15042922Smckusick if (KTRPOINT(p, KTR_GENIO)) {
15137728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
15237728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
15337728Smckusick }
15437728Smckusick #endif
15537728Smckusick cnt = auio.uio_resid;
15640703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
15740703Skarels if (auio.uio_resid != cnt && (error == ERESTART ||
15840703Skarels error == EINTR || error == EWOULDBLOCK))
15940703Skarels error = 0;
16037728Smckusick cnt -= auio.uio_resid;
16137728Smckusick #ifdef KTRACE
16237728Smckusick if (ktriov != NULL) {
16341178Smarc if (error == 0)
164*68316Scgd ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
16543448Smckusick cnt, error);
16637728Smckusick FREE(ktriov, M_TEMP);
16737728Smckusick }
16837728Smckusick #endif
16942922Smckusick *retval = cnt;
17037127Skarels done:
17152481Storek if (needfree)
17252481Storek FREE(needfree, M_IOV);
17344405Skarels return (error);
1747423Sroot }
1757423Sroot
1767423Sroot /*
1777423Sroot * Write system call
1787423Sroot */
179*68316Scgd int
write(p,uap,retval)18042922Smckusick write(p, uap, retval)
18142922Smckusick struct proc *p;
182*68316Scgd register struct write_args /* {
183*68316Scgd syscallarg(int) fd;
184*68316Scgd syscallarg(char *) buf;
185*68316Scgd syscallarg(u_int) nbyte;
186*68316Scgd } */ *uap;
187*68316Scgd register_t *retval;
18842922Smckusick {
18937728Smckusick register struct file *fp;
19045914Smckusick register struct filedesc *fdp = p->p_fd;
1917820Sroot struct uio auio;
1927820Sroot struct iovec aiov;
19337728Smckusick long cnt, error = 0;
19437728Smckusick #ifdef KTRACE
19537728Smckusick struct iovec ktriov;
19637728Smckusick #endif
1977423Sroot
198*68316Scgd if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
199*68316Scgd (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
20037728Smckusick (fp->f_flag & FWRITE) == 0)
20144405Skarels return (EBADF);
202*68316Scgd aiov.iov_base = (caddr_t)SCARG(uap, buf);
203*68316Scgd aiov.iov_len = SCARG(uap, nbyte);
2047820Sroot auio.uio_iov = &aiov;
2057820Sroot auio.uio_iovcnt = 1;
206*68316Scgd auio.uio_resid = SCARG(uap, nbyte);
20737728Smckusick auio.uio_rw = UIO_WRITE;
20837728Smckusick auio.uio_segflg = UIO_USERSPACE;
20948027Smckusick auio.uio_procp = p;
21037728Smckusick #ifdef KTRACE
21137728Smckusick /*
21237728Smckusick * if tracing, save a copy of iovec
21337728Smckusick */
21442922Smckusick if (KTRPOINT(p, KTR_GENIO))
21537728Smckusick ktriov = aiov;
21637728Smckusick #endif
217*68316Scgd cnt = SCARG(uap, nbyte);
21840703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
21940703Skarels if (auio.uio_resid != cnt && (error == ERESTART ||
22040703Skarels error == EINTR || error == EWOULDBLOCK))
22140703Skarels error = 0;
22240703Skarels if (error == EPIPE)
22342922Smckusick psignal(p, SIGPIPE);
22440703Skarels }
22537728Smckusick cnt -= auio.uio_resid;
22637728Smckusick #ifdef KTRACE
22742922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0)
228*68316Scgd ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
22943448Smckusick &ktriov, cnt, error);
23037728Smckusick #endif
23142922Smckusick *retval = cnt;
23244405Skarels return (error);
2337820Sroot }
2347820Sroot
23542922Smckusick /*
23642922Smckusick * Gather write system call
23742922Smckusick */
238*68316Scgd int
writev(p,uap,retval)23942922Smckusick writev(p, uap, retval)
24042922Smckusick struct proc *p;
241*68316Scgd register struct writev_args /* {
242*68316Scgd syscallarg(int) fd;
243*68316Scgd syscallarg(struct iovec *) iovp;
244*68316Scgd syscallarg(u_int) iovcnt;
245*68316Scgd } */ *uap;
246*68316Scgd register_t *retval;
24742922Smckusick {
24837728Smckusick register struct file *fp;
24945914Smckusick register struct filedesc *fdp = p->p_fd;
2507820Sroot struct uio auio;
25137728Smckusick register struct iovec *iov;
25252481Storek struct iovec *needfree;
25337728Smckusick struct iovec aiov[UIO_SMALLIOV];
25437728Smckusick long i, cnt, error = 0;
25564409Sbostic u_int iovlen;
25637728Smckusick #ifdef KTRACE
25737728Smckusick struct iovec *ktriov = NULL;
25837728Smckusick #endif
2597820Sroot
260*68316Scgd if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
261*68316Scgd (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
26237728Smckusick (fp->f_flag & FWRITE) == 0)
26344405Skarels return (EBADF);
26444939Skarels /* note: can't use iovlen until iovcnt is validated */
265*68316Scgd iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
266*68316Scgd if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
267*68316Scgd if (SCARG(uap, iovcnt) > UIO_MAXIOV)
26844405Skarels return (EINVAL);
26944939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
27052481Storek needfree = iov;
27152481Storek } else {
27237127Skarels iov = aiov;
27352481Storek needfree = NULL;
27452481Storek }
27537127Skarels auio.uio_iov = iov;
276*68316Scgd auio.uio_iovcnt = SCARG(uap, iovcnt);
27737728Smckusick auio.uio_rw = UIO_WRITE;
27837728Smckusick auio.uio_segflg = UIO_USERSPACE;
27948027Smckusick auio.uio_procp = p;
280*68316Scgd if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
28137127Skarels goto done;
28237728Smckusick auio.uio_resid = 0;
283*68316Scgd for (i = 0; i < SCARG(uap, iovcnt); i++) {
28467491Smckusick if (auio.uio_resid + iov->iov_len < auio.uio_resid) {
28537728Smckusick error = EINVAL;
28637728Smckusick goto done;
2877820Sroot }
28837728Smckusick auio.uio_resid += iov->iov_len;
28913270Ssam iov++;
2907820Sroot }
29137127Skarels #ifdef KTRACE
29237728Smckusick /*
29337728Smckusick * if tracing, save a copy of iovec
29437728Smckusick */
29542922Smckusick if (KTRPOINT(p, KTR_GENIO)) {
29637127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
29737728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
29837127Skarels }
29937127Skarels #endif
30037728Smckusick cnt = auio.uio_resid;
30140703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
30240703Skarels if (auio.uio_resid != cnt && (error == ERESTART ||
30340703Skarels error == EINTR || error == EWOULDBLOCK))
30440703Skarels error = 0;
30540703Skarels if (error == EPIPE)
30642922Smckusick psignal(p, SIGPIPE);
30740703Skarels }
30837728Smckusick cnt -= auio.uio_resid;
30937127Skarels #ifdef KTRACE
31037127Skarels if (ktriov != NULL) {
31141178Smarc if (error == 0)
312*68316Scgd ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
31343448Smckusick ktriov, cnt, error);
31437127Skarels FREE(ktriov, M_TEMP);
31537127Skarels }
31637127Skarels #endif
31742922Smckusick *retval = cnt;
31837728Smckusick done:
31952481Storek if (needfree)
32052481Storek FREE(needfree, M_IOV);
32144405Skarels return (error);
3227423Sroot }
3237423Sroot
3247423Sroot /*
3257423Sroot * Ioctl system call
3267423Sroot */
32742922Smckusick /* ARGSUSED */
328*68316Scgd int
ioctl(p,uap,retval)32942922Smckusick ioctl(p, uap, retval)
33042922Smckusick struct proc *p;
331*68316Scgd register struct ioctl_args /* {
332*68316Scgd syscallarg(int) fd;
333*68316Scgd syscallarg(u_long) com;
334*68316Scgd syscallarg(caddr_t) data;
335*68316Scgd } */ *uap;
336*68316Scgd register_t *retval;
33742922Smckusick {
33842922Smckusick register struct file *fp;
33964538Sbostic register struct filedesc *fdp;
340*68316Scgd register u_long com;
341*68316Scgd register int error;
3427820Sroot register u_int size;
34364538Sbostic caddr_t data, memp;
34464538Sbostic int tmp;
34530530Skarels #define STK_PARAMS 128
34633480Skarels char stkbuf[STK_PARAMS];
3477423Sroot
34864538Sbostic fdp = p->p_fd;
349*68316Scgd if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
350*68316Scgd (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
35144405Skarels return (EBADF);
35264538Sbostic
35364538Sbostic if ((fp->f_flag & (FREAD | FWRITE)) == 0)
35444405Skarels return (EBADF);
3557624Ssam
356*68316Scgd switch (com = SCARG(uap, com)) {
35764538Sbostic case FIONCLEX:
358*68316Scgd fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
35964538Sbostic return (0);
36064538Sbostic case FIOCLEX:
361*68316Scgd fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
36244405Skarels return (0);
3637423Sroot }
3647624Ssam
3657624Ssam /*
36664538Sbostic * Interpret high order word to find amount of data to be
36764538Sbostic * copied to/from the user's address space.
3687624Ssam */
36930530Skarels size = IOCPARM_LEN(com);
37040703Skarels if (size > IOCPARM_MAX)
37144405Skarels return (ENOTTY);
37264538Sbostic memp = NULL;
37333480Skarels if (size > sizeof (stkbuf)) {
37443383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
37531653Smckusick data = memp;
37664538Sbostic } else
37764538Sbostic data = stkbuf;
37810601Ssam if (com&IOC_IN) {
37910601Ssam if (size) {
380*68316Scgd error = copyin(SCARG(uap, data), data, (u_int)size);
38140703Skarels if (error) {
38231653Smckusick if (memp)
38331653Smckusick free(memp, M_IOCTLOPS);
38444405Skarels return (error);
38531653Smckusick }
38610601Ssam } else
387*68316Scgd *(caddr_t *)data = SCARG(uap, data);
38810601Ssam } else if ((com&IOC_OUT) && size)
38910601Ssam /*
39037127Skarels * Zero the buffer so the user always
39137127Skarels * gets back something deterministic.
39210601Ssam */
39330530Skarels bzero(data, size);
39411284Ssam else if (com&IOC_VOID)
395*68316Scgd *(caddr_t *)data = SCARG(uap, data);
3967423Sroot
39712751Ssam switch (com) {
3987624Ssam
39912751Ssam case FIONBIO:
40048027Smckusick if (tmp = *(int *)data)
40149941Smckusick fp->f_flag |= FNONBLOCK;
40248027Smckusick else
40349941Smckusick fp->f_flag &= ~FNONBLOCK;
40448027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
40530530Skarels break;
40612751Ssam
40712751Ssam case FIOASYNC:
40848027Smckusick if (tmp = *(int *)data)
40948027Smckusick fp->f_flag |= FASYNC;
41048027Smckusick else
41148027Smckusick fp->f_flag &= ~FASYNC;
41248027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
41330530Skarels break;
41412751Ssam
41512751Ssam case FIOSETOWN:
41648027Smckusick tmp = *(int *)data;
41748027Smckusick if (fp->f_type == DTYPE_SOCKET) {
41848027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp;
41948027Smckusick error = 0;
42048027Smckusick break;
42148027Smckusick }
42248027Smckusick if (tmp <= 0) {
42348027Smckusick tmp = -tmp;
42448027Smckusick } else {
42548027Smckusick struct proc *p1 = pfind(tmp);
42648027Smckusick if (p1 == 0) {
42748027Smckusick error = ESRCH;
42848027Smckusick break;
42948027Smckusick }
43048027Smckusick tmp = p1->p_pgrp->pg_id;
43148027Smckusick }
43248027Smckusick error = (*fp->f_ops->fo_ioctl)
433*68316Scgd (fp, TIOCSPGRP, (caddr_t)&tmp, p);
43430530Skarels break;
43512751Ssam
43612751Ssam case FIOGETOWN:
43748027Smckusick if (fp->f_type == DTYPE_SOCKET) {
43848027Smckusick error = 0;
43948027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
44048027Smckusick break;
44148027Smckusick }
442*68316Scgd error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
44348027Smckusick *(int *)data = -*(int *)data;
44430530Skarels break;
44548027Smckusick
44630530Skarels default:
44747540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
44830530Skarels /*
44930530Skarels * Copy any data to user, size was
45030530Skarels * already set and checked above.
45130530Skarels */
45240703Skarels if (error == 0 && (com&IOC_OUT) && size)
453*68316Scgd error = copyout(data, SCARG(uap, data), (u_int)size);
45430530Skarels break;
4557423Sroot }
45631653Smckusick if (memp)
45731653Smckusick free(memp, M_IOCTLOPS);
45844405Skarels return (error);
4597423Sroot }
4607423Sroot
46149227Skarels int selwait, nselcoll;
46217593Skarels
4637423Sroot /*
46412751Ssam * Select system call.
4657423Sroot */
466*68316Scgd int
select(p,uap,retval)46742922Smckusick select(p, uap, retval)
46842922Smckusick register struct proc *p;
469*68316Scgd register struct select_args /* {
470*68316Scgd syscallarg(u_int) nd;
471*68316Scgd syscallarg(fd_set *) in;
472*68316Scgd syscallarg(fd_set *) ou;
473*68316Scgd syscallarg(fd_set *) ex;
474*68316Scgd syscallarg(struct timeval *) tv;
475*68316Scgd } */ *uap;
476*68316Scgd register_t *retval;
47742922Smckusick {
47823523Skarels fd_set ibits[3], obits[3];
47912751Ssam struct timeval atv;
48067661Smckusick int s, ncoll, error, timo = 0;
48163864Smckusick u_int ni;
48212751Ssam
48326277Skarels bzero((caddr_t)ibits, sizeof(ibits));
48426277Skarels bzero((caddr_t)obits, sizeof(obits));
485*68316Scgd if (SCARG(uap, nd) > FD_SETSIZE)
48663864Smckusick return (EINVAL);
487*68316Scgd if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
488*68316Scgd /* forgiving; slightly wrong */
489*68316Scgd SCARG(uap, nd) = p->p_fd->fd_nfiles;
490*68316Scgd }
491*68316Scgd ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
49212751Ssam
49312751Ssam #define getbits(name, x) \
494*68316Scgd if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
495*68316Scgd (caddr_t)&ibits[x], ni))) \
49663864Smckusick goto done;
49712751Ssam getbits(in, 0);
49812751Ssam getbits(ou, 1);
49912751Ssam getbits(ex, 2);
50012751Ssam #undef getbits
50112751Ssam
502*68316Scgd if (SCARG(uap, tv)) {
503*68316Scgd error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
50412751Ssam sizeof (atv));
50540703Skarels if (error)
50612751Ssam goto done;
50712751Ssam if (itimerfix(&atv)) {
50840703Skarels error = EINVAL;
50912751Ssam goto done;
51012751Ssam }
51154760Storek s = splclock();
51254760Storek timevaladd(&atv, (struct timeval *)&time);
51354276Sbostic splx(s);
51467661Smckusick }
51512751Ssam retry:
51612751Ssam ncoll = nselcoll;
51764583Sbostic p->p_flag |= P_SELECT;
518*68316Scgd error = selscan(p, ibits, obits, SCARG(uap, nd), retval);
51942922Smckusick if (error || *retval)
52012751Ssam goto done;
52117934Skarels s = splhigh();
522*68316Scgd if (SCARG(uap, tv)) {
52367633Smckusick if (timercmp(&time, &atv, >=)) {
52467633Smckusick splx(s);
52567633Smckusick goto done;
52667633Smckusick }
52767633Smckusick /*
52867661Smckusick * If poll wait was tiny, this could be zero; we will
52967661Smckusick * have to round it up to avoid sleeping forever. If
53067661Smckusick * we retry below, the timercmp above will get us out.
53167661Smckusick * Note that if wait was 0, the timercmp will prevent
53267661Smckusick * us from getting here the first time.
53367633Smckusick */
53467661Smckusick timo = hzto(&atv);
53567661Smckusick if (timo == 0)
53667633Smckusick timo = 1;
53712751Ssam }
53864583Sbostic if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
53912751Ssam splx(s);
54012751Ssam goto retry;
54112751Ssam }
54264583Sbostic p->p_flag &= ~P_SELECT;
54340703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
54412751Ssam splx(s);
54540703Skarels if (error == 0)
54640703Skarels goto retry;
54712751Ssam done:
54864583Sbostic p->p_flag &= ~P_SELECT;
54940703Skarels /* select is not restarted after signals... */
55040703Skarels if (error == ERESTART)
55140703Skarels error = EINTR;
55240703Skarels if (error == EWOULDBLOCK)
55340703Skarels error = 0;
55412751Ssam #define putbits(name, x) \
555*68316Scgd if (SCARG(uap, name) && (error2 = copyout((caddr_t)&obits[x], \
556*68316Scgd (caddr_t)SCARG(uap, name), ni))) \
55763864Smckusick error = error2;
55840703Skarels if (error == 0) {
55963864Smckusick int error2;
56063864Smckusick
56121106Skarels putbits(in, 0);
56221106Skarels putbits(ou, 1);
56321106Skarels putbits(ex, 2);
56412751Ssam #undef putbits
56521106Skarels }
56644405Skarels return (error);
56712751Ssam }
56812751Ssam
569*68316Scgd int
selscan(p,ibits,obits,nfd,retval)57047540Skarels selscan(p, ibits, obits, nfd, retval)
57147540Skarels struct proc *p;
57223523Skarels fd_set *ibits, *obits;
573*68316Scgd int nfd;
574*68316Scgd register_t *retval;
57512751Ssam {
57647540Skarels register struct filedesc *fdp = p->p_fd;
57752481Storek register int msk, i, j, fd;
57823523Skarels register fd_mask bits;
57912751Ssam struct file *fp;
58052481Storek int n = 0;
58152481Storek static int flag[3] = { FREAD, FWRITE, 0 };
58212751Ssam
58352481Storek for (msk = 0; msk < 3; msk++) {
58423523Skarels for (i = 0; i < nfd; i += NFDBITS) {
58552481Storek bits = ibits[msk].fds_bits[i/NFDBITS];
58652481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
58717593Skarels bits &= ~(1 << j);
58852481Storek fp = fdp->fd_ofiles[fd];
58952481Storek if (fp == NULL)
59052481Storek return (EBADF);
59152481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
59252481Storek FD_SET(fd, &obits[msk]);
59317593Skarels n++;
59417593Skarels }
59512751Ssam }
59612751Ssam }
59712751Ssam }
59842922Smckusick *retval = n;
59952481Storek return (0);
60012751Ssam }
60112751Ssam
6027423Sroot /*ARGSUSED*/
603*68316Scgd int
seltrue(dev,flag,p)60447540Skarels seltrue(dev, flag, p)
60512751Ssam dev_t dev;
60612751Ssam int flag;
60747540Skarels struct proc *p;
6087423Sroot {
6097423Sroot
61012751Ssam return (1);
6117423Sroot }
6128103Sroot
61352525Smckusick /*
61452525Smckusick * Record a select request.
61552525Smckusick */
61652525Smckusick void
selrecord(selector,sip)61752525Smckusick selrecord(selector, sip)
61852525Smckusick struct proc *selector;
61952525Smckusick struct selinfo *sip;
6208103Sroot {
62152525Smckusick struct proc *p;
62252525Smckusick pid_t mypid;
6238103Sroot
62452525Smckusick mypid = selector->p_pid;
62552525Smckusick if (sip->si_pid == mypid)
62652525Smckusick return;
62752525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) &&
62852525Smckusick p->p_wchan == (caddr_t)&selwait)
62952525Smckusick sip->si_flags |= SI_COLL;
63052525Smckusick else
63152525Smckusick sip->si_pid = mypid;
63252525Smckusick }
63352525Smckusick
63452525Smckusick /*
63552525Smckusick * Do a wakeup when a selectable event occurs.
63652525Smckusick */
63752525Smckusick void
selwakeup(sip)63852525Smckusick selwakeup(sip)
63952525Smckusick register struct selinfo *sip;
64052525Smckusick {
64152525Smckusick register struct proc *p;
64252525Smckusick int s;
64352525Smckusick
64452525Smckusick if (sip->si_pid == 0)
64552525Smckusick return;
64652525Smckusick if (sip->si_flags & SI_COLL) {
64712751Ssam nselcoll++;
64852525Smckusick sip->si_flags &= ~SI_COLL;
64912751Ssam wakeup((caddr_t)&selwait);
65012751Ssam }
65152922Smckusick p = pfind(sip->si_pid);
65252922Smckusick sip->si_pid = 0;
65352922Smckusick if (p != NULL) {
65452525Smckusick s = splhigh();
65517270Skarels if (p->p_wchan == (caddr_t)&selwait) {
65617270Skarels if (p->p_stat == SSLEEP)
65764538Sbostic setrunnable(p);
65817270Skarels else
65917270Skarels unsleep(p);
66064583Sbostic } else if (p->p_flag & P_SELECT)
66164583Sbostic p->p_flag &= ~P_SELECT;
66212751Ssam splx(s);
66312751Ssam }
6648103Sroot }
665