]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/tcpip/v2_0/src/sys/kern/sys_generic.c
Initial revision
[karo-tx-redboot.git] / packages / net / tcpip / v2_0 / src / sys / kern / sys_generic.c
1 //==========================================================================
2 //
3 //      sys/kern/sys_generic.c
4 //
5 //     
6 //
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 //
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
14 //
15 // -------------------------------------------
16 //
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
20 //
21 // Author(s):    gthomas
22 // Contributors: gthomas
23 // Date:         2000-01-10
24 // Purpose:      
25 // Description:  
26 //              
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32
33 /*      $OpenBSD: sys_generic.c,v 1.22 1999/11/29 22:02:14 deraadt Exp $        */
34 /*      $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */
35
36 /*
37  * Copyright (c) 1996 Theo de Raadt
38  * Copyright (c) 1982, 1986, 1989, 1993
39  *      The Regents of the University of California.  All rights reserved.
40  * (c) UNIX System Laboratories, Inc.
41  * All or some portions of this file are derived from material licensed
42  * to the University of California by American Telephone and Telegraph
43  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
44  * the permission of UNIX System Laboratories, Inc.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *      This product includes software developed by the University of
57  *      California, Berkeley and its contributors.
58  * 4. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  *      @(#)sys_generic.c       8.5 (Berkeley) 1/21/94
75  */
76
77 #include <sys/param.h>
78 #ifndef __ECOS
79 #include <sys/systm.h>
80 #include <sys/filedesc.h>
81 #endif // __ECOS
82 #include <sys/ioctl.h>
83 #ifdef __ECOS
84 #include <cyg/io/file.h>
85 #else // __ECOS
86 #include <sys/file.h>
87 #include <sys/proc.h>
88 #include <sys/resourcevar.h>
89 #endif // __ECOS
90 #include <sys/socketvar.h>
91 #ifndef __ECOS
92 #include <sys/signalvar.h>
93 #include <sys/kernel.h>
94 #include <sys/uio.h>
95 #include <sys/stat.h>
96 #endif // __ECOS
97 #include <sys/malloc.h>
98 #ifndef __ECOS
99 #include <sys/poll.h>
100 #endif // __ECOS
101 #ifdef KTRACE
102 #include <sys/ktrace.h>
103 #endif
104
105 #ifndef __ECOS
106 #include <sys/mount.h>
107 #endif // __ECOS
108 #include <sys/syscallargs.h>
109
110 #ifndef __ECOS
111 int selscan __P((struct proc *, fd_set *, fd_set *, int, register_t *));
112 int seltrue __P((dev_t, int, struct proc *));
113 void pollscan __P((struct proc *, struct pollfd *, int, register_t *));
114 #endif // __ECOS
115
116 /*
117  * Read system call.
118  */
119 #ifdef __ECOS
120 int
121 sys_read(struct sys_read_args *uap, register_t *retval)
122 #else
123 /* ARGSUSED */
124 int
125 sys_read(p, v, retval)
126         struct proc *p;
127         void *v;
128         register_t *retval;
129 #endif
130 {
131 #ifndef __ECOS
132         register struct sys_read_args /* {
133                 syscallarg(int) fd;
134                 syscallarg(void *) buf;
135                 syscallarg(size_t) nbyte;
136         } */ *uap = v;
137         register struct filedesc *fdp = p->p_fd;
138 #endif
139         struct file *fp;
140         struct uio auio;
141         struct iovec aiov;
142         long cnt, error = 0;
143 #ifdef KTRACE
144         struct iovec ktriov;
145 #endif
146
147 #ifdef __ECOS
148         if (getfp((u_int)SCARG(uap, fd), &fp) ||
149 #else
150         if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
151             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
152 #endif
153             (fp->f_flag & FREAD) == 0)
154                 return (EBADF);
155         /* Don't allow nbyte to be larger than max return val */
156         if (SCARG(uap, nbyte) > SSIZE_MAX)
157                 return(EINVAL);
158         aiov.iov_base = (caddr_t)SCARG(uap, buf);
159         aiov.iov_len = SCARG(uap, nbyte);
160         auio.uio_iov = &aiov;
161         auio.uio_iovcnt = 1;
162         auio.uio_resid = SCARG(uap, nbyte);
163         auio.uio_rw = UIO_READ;
164         auio.uio_segflg = UIO_USERSPACE;
165 #ifndef __ECOS
166         auio.uio_procp = p;
167 #endif
168 #ifdef KTRACE
169         /*
170          * if tracing, save a copy of iovec
171          */
172         if (KTRPOINT(p, KTR_GENIO))
173                 ktriov = aiov;
174 #endif
175         cnt = SCARG(uap, nbyte);
176 #ifdef __ECOS
177         error = (*fp->f_ops->fo_read)(fp, &auio);
178 #else
179         error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
180 #endif
181         if (error)
182 #ifdef __ECOS
183                 if (auio.uio_resid != cnt && (
184 #else
185                 if (auio.uio_resid != cnt && (error == ERESTART ||
186 #endif
187                     error == EINTR || error == EWOULDBLOCK))
188                         error = 0;
189         cnt -= auio.uio_resid;
190 #ifdef KTRACE
191         if (KTRPOINT(p, KTR_GENIO) && error == 0)
192                 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
193                     cnt, error);
194 #endif
195         *retval = cnt;
196         return (error);
197 }
198
199
200 #ifndef __ECOS
201 /*
202  * Scatter read system call.
203  */
204 int
205 sys_readv(p, v, retval)
206         struct proc *p;
207         void *v;
208         register_t *retval;
209 {
210         register struct sys_readv_args /* {
211                 syscallarg(int) fd;
212                 syscallarg(struct iovec *) iovp;
213                 syscallarg(int) iovcnt;
214         } */ *uap = v;
215         register struct file *fp;
216         register struct filedesc *fdp = p->p_fd;
217         struct uio auio;
218         register struct iovec *iov;
219         struct iovec *needfree;
220         struct iovec aiov[UIO_SMALLIOV];
221         long i, cnt, error = 0;
222         u_int iovlen;
223 #ifdef KTRACE
224         struct iovec *ktriov = NULL;
225 #endif
226
227         if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
228             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
229             (fp->f_flag & FREAD) == 0)
230                 return (EBADF);
231         if (SCARG(uap, iovcnt) <= 0)
232                 return (EINVAL);
233         /* note: can't use iovlen until iovcnt is validated */
234         iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
235         if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
236                 if (SCARG(uap, iovcnt) > IOV_MAX)
237                         return (EINVAL);
238                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
239                 needfree = iov;
240         } else {
241                 iov = aiov;
242                 needfree = NULL;
243         }
244         auio.uio_iov = iov;
245         auio.uio_iovcnt = SCARG(uap, iovcnt);
246         auio.uio_rw = UIO_READ;
247         auio.uio_segflg = UIO_USERSPACE;
248         auio.uio_procp = p;
249         error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
250         if (error)
251                 goto done;
252         auio.uio_resid = 0;
253         for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
254                 /* Don't allow sum > SSIZE_MAX */
255                 if (iov->iov_len > SSIZE_MAX ||
256                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
257                         error = EINVAL;
258                         goto done;
259                 }
260         }
261 #ifdef KTRACE
262         /*
263          * if tracing, save a copy of iovec
264          */
265         if (KTRPOINT(p, KTR_GENIO))  {
266                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
267                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
268         }
269 #endif
270         cnt = auio.uio_resid;
271         error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
272         if (error)
273                 if (auio.uio_resid != cnt && (error == ERESTART ||
274                     error == EINTR || error == EWOULDBLOCK))
275                         error = 0;
276         cnt -= auio.uio_resid;
277 #ifdef KTRACE
278         if (ktriov != NULL) {
279                 if (error == 0)
280                         ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
281                             cnt, error);
282                 FREE(ktriov, M_TEMP);
283         }
284 #endif
285         *retval = cnt;
286 done:
287         if (needfree)
288                 FREE(needfree, M_IOV);
289         return (error);
290 }
291 #endif
292
293 /*
294  * Write system call
295  */
296 #ifdef __ECOS
297 int
298 sys_write(struct sys_write_args *uap, register_t *retval)
299 #else
300 int
301 sys_write(p, v, retval)
302         struct proc *p;
303         void *v;
304         register_t *retval;
305 #endif
306 {
307 #ifndef __ECOS
308         register struct sys_write_args /* {
309                 syscallarg(int) fd;
310                 syscallarg(void *) buf;
311                 syscallarg(size_t) nbyte;
312         } */ *uap = v;
313         register struct filedesc *fdp = p->p_fd;
314 #endif
315         struct file *fp;
316         struct uio auio;
317         struct iovec aiov;
318         long cnt, error = 0;
319 #ifdef KTRACE
320         struct iovec ktriov;
321 #endif
322
323 #ifdef __ECOS
324         if (getfp((u_int)SCARG(uap, fd), &fp) ||
325 #else
326         if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
327             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
328 #endif
329             (fp->f_flag & FWRITE) == 0)
330                 return (EBADF);
331         /* Don't allow nbyte to be larger than max return val */
332         if (SCARG(uap, nbyte) > SSIZE_MAX)
333                 return(EINVAL);
334         aiov.iov_base = (caddr_t)SCARG(uap, buf);
335         aiov.iov_len = SCARG(uap, nbyte);
336         auio.uio_iov = &aiov;
337         auio.uio_iovcnt = 1;
338         auio.uio_resid = SCARG(uap, nbyte);
339         auio.uio_rw = UIO_WRITE;
340         auio.uio_segflg = UIO_USERSPACE;
341 #ifndef __ECOS
342         auio.uio_procp = p;
343 #endif
344 #ifdef KTRACE
345         /*
346          * if tracing, save a copy of iovec
347          */
348         if (KTRPOINT(p, KTR_GENIO))
349                 ktriov = aiov;
350 #endif
351         cnt = SCARG(uap, nbyte);
352 #ifdef __ECOS
353         error = (*fp->f_ops->fo_write)(fp, &auio);
354 #else
355         error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
356 #endif
357         if (error) {
358 #ifdef __ECOS
359                 if (auio.uio_resid != cnt &&
360                     (error == EINTR || error == EWOULDBLOCK))
361                         error = 0;
362 #else
363                 if (auio.uio_resid != cnt && (error == ERESTART ||
364                     error == EINTR || error == EWOULDBLOCK))
365                         error = 0;
366                 if (error == EPIPE)
367                         psignal(p, SIGPIPE);
368 #endif
369         }
370         cnt -= auio.uio_resid;
371 #ifdef KTRACE
372         if (KTRPOINT(p, KTR_GENIO) && error == 0)
373                 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
374                     &ktriov, cnt, error);
375 #endif
376         *retval = cnt;
377         return (error);
378 }
379
380 #ifndef __ECOS
381 /*
382  * Gather write system call
383  */
384 int
385 sys_writev(p, v, retval)
386         struct proc *p;
387         void *v;
388         register_t *retval;
389 {
390         register struct sys_writev_args /* {
391                 syscallarg(int) fd;
392                 syscallarg(struct iovec *) iovp;
393                 syscallarg(int) iovcnt;
394         } */ *uap = v;
395         register struct file *fp;
396         register struct filedesc *fdp = p->p_fd;
397         struct uio auio;
398         register struct iovec *iov;
399         struct iovec *needfree;
400         struct iovec aiov[UIO_SMALLIOV];
401         long i, cnt, error = 0;
402         u_int iovlen;
403 #ifdef KTRACE
404         struct iovec *ktriov = NULL;
405 #endif
406
407         if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
408             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
409             (fp->f_flag & FWRITE) == 0)
410                 return (EBADF);
411         if (SCARG(uap, iovcnt) <= 0)
412                 return (EINVAL);
413         /* note: can't use iovlen until iovcnt is validated */
414         iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
415         if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
416                 if (SCARG(uap, iovcnt) > IOV_MAX)
417                         return (EINVAL);
418                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
419                 needfree = iov;
420         } else {
421                 iov = aiov;
422                 needfree = NULL;
423         }
424         auio.uio_iov = iov;
425         auio.uio_iovcnt = SCARG(uap, iovcnt);
426         auio.uio_rw = UIO_WRITE;
427         auio.uio_segflg = UIO_USERSPACE;
428         auio.uio_procp = p;
429         error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
430         if (error)
431                 goto done;
432         auio.uio_resid = 0;
433         for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
434                 /* Don't allow sum > SSIZE_MAX */
435                 if (iov->iov_len > SSIZE_MAX ||
436                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
437                         error = EINVAL;
438                         goto done;
439                 }
440         }
441 #ifdef KTRACE
442         /*
443          * if tracing, save a copy of iovec
444          */
445         if (KTRPOINT(p, KTR_GENIO))  {
446                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
447                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
448         }
449 #endif
450         cnt = auio.uio_resid;
451         error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
452         if (error) {
453                 if (auio.uio_resid != cnt && (error == ERESTART ||
454                     error == EINTR || error == EWOULDBLOCK))
455                         error = 0;
456                 if (error == EPIPE)
457                         psignal(p, SIGPIPE);
458         }
459         cnt -= auio.uio_resid;
460 #ifdef KTRACE
461         if (ktriov != NULL) {
462                 if (error == 0)
463                         ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
464                                 ktriov, cnt, error);
465                 FREE(ktriov, M_TEMP);
466         }
467 #endif
468         *retval = cnt;
469 done:
470         if (needfree)
471                 FREE(needfree, M_IOV);
472         return (error);
473 }
474 #endif
475
476 /*
477  * Ioctl system call
478  */
479 #ifdef __ECOS
480 int
481 sys_ioctl(struct sys_ioctl_args *uap, register_t *retval)
482 #else
483 /* ARGSUSED */
484 int
485 sys_ioctl(p, v, retval)
486         struct proc *p;
487         void *v;
488         register_t *retval;
489 #endif
490 {
491 #ifndef __ECOS
492         register struct sys_ioctl_args /* {
493                 syscallarg(int) fd;
494                 syscallarg(u_long) com;
495                 syscallarg(caddr_t) data;
496         } */ *uap = v;
497         register struct filedesc *fdp;
498 #endif
499         int tmp;
500         struct file *fp;
501         register u_long com;
502         register int error;
503         register u_int size;
504         caddr_t data, memp;
505 #define STK_PARAMS      128
506         char stkbuf[STK_PARAMS];
507
508 #ifdef __ECOS
509         if (getfp(SCARG(uap, fd), &fp))
510 #else
511         fdp = p->p_fd;
512         if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
513             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
514 #endif
515                 return (EBADF);
516
517         if ((fp->f_flag & (FREAD | FWRITE)) == 0)
518                 return (EBADF);
519
520 #ifdef __ECOS
521         com = SCARG(uap, com);
522 #else
523         switch (com = SCARG(uap, com)) {
524         case FIONCLEX:
525                 fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
526                 return (0);
527         case FIOCLEX:
528                 fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
529                 return (0);
530         }
531 #endif
532
533         /*
534          * Interpret high order word to find amount of data to be
535          * copied to/from the user's address space.
536          */
537         size = IOCPARM_LEN(com);
538 #ifndef __ECOS
539         if (size > IOCPARM_MAX)
540                 return (ENOTTY);
541 #endif
542         memp = NULL;
543         if (size > sizeof (stkbuf)) {
544                 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
545                 data = memp;
546         } else
547                 data = stkbuf;
548         if (com&IOC_IN) {
549                 if (size) {
550                         error = copyin(SCARG(uap, data), data, (u_int)size);
551                         if (error) {
552                                 if (memp)
553                                         free(memp, M_IOCTLOPS);
554                                 return (error);
555                         }
556                 } else
557                         *(caddr_t *)data = SCARG(uap, data);
558         } else if ((com&IOC_OUT) && size)
559                 /*
560                  * Zero the buffer so the user always
561                  * gets back something deterministic.
562                  */
563                 bzero(data, size);
564         else if (com&IOC_VOID)
565                 *(caddr_t *)data = SCARG(uap, data);
566
567         switch (com) {
568
569         case FIONBIO:
570                 if ((tmp = *(int *)data) != 0)
571                         fp->f_flag |= FNONBLOCK;
572                 else
573                         fp->f_flag &= ~FNONBLOCK;
574 #ifdef __ECOS
575                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (CYG_ADDRWORD)&tmp);
576 #else
577                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
578 #endif
579                 break;
580
581         case FIOASYNC:
582                 if ((tmp = *(int *)data) != 0)
583                         fp->f_flag |= FASYNC;
584                 else
585                         fp->f_flag &= ~FASYNC;
586 #ifdef __ECOS
587                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (CYG_ADDRWORD)&tmp);
588 #else
589                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
590 #endif
591                 break;
592
593 #ifndef __ECOS
594         case FIOSETOWN:
595                 tmp = *(int *)data;
596                 if (fp->f_type == DTYPE_SOCKET) {
597                         struct socket *so = (struct socket *)fp->f_data;
598
599                         so->so_pgid = tmp;
600                         so->so_siguid = p->p_cred->p_ruid;
601                         so->so_sigeuid = p->p_ucred->cr_uid;
602                         error = 0;
603                         break;
604                 }
605                 if (tmp <= 0) {
606                         tmp = -tmp;
607                 } else {
608                         struct proc *p1 = pfind(tmp);
609                         if (p1 == 0) {
610                                 error = ESRCH;
611                                 break;
612                         }
613                         tmp = p1->p_pgrp->pg_id;
614                 }
615                 error = (*fp->f_ops->fo_ioctl)
616                         (fp, TIOCSPGRP, (caddr_t)&tmp, p);
617                 break;
618
619         case FIOGETOWN:
620                 if (fp->f_type == DTYPE_SOCKET) {
621                         error = 0;
622                         *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
623                         break;
624                 }
625                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
626                 *(int *)data = -*(int *)data;
627                 break;
628 #endif
629         default:
630 #ifdef __ECOS
631                 error = (*fp->f_ops->fo_ioctl)(fp, com, (CYG_ADDRWORD)data);
632 #else
633                 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
634 #endif
635                 /*
636                  * Copy any data to user, size was
637                  * already set and checked above.
638                  */
639                 if (error == 0 && (com&IOC_OUT) && size)
640                         error = copyout(data, SCARG(uap, data), (u_int)size);
641                 break;
642         }
643         if (memp)
644                 free(memp, M_IOCTLOPS);
645         return (error);
646 }
647
648 #ifndef __ECOS
649 int     selwait, nselcoll;
650
651 /*
652  * Select system call.
653  */
654 int
655 sys_select(p, v, retval)
656         register struct proc *p;
657         void *v;
658         register_t *retval;
659 {
660         register struct sys_select_args /* {
661                 syscallarg(int) nd;
662                 syscallarg(fd_set *) in;
663                 syscallarg(fd_set *) ou;
664                 syscallarg(fd_set *) ex;
665                 syscallarg(struct timeval *) tv;
666         } */ *uap = v;
667         fd_set bits[6], *pibits[3], *pobits[3];
668         struct timeval atv;
669         int s, ncoll, error = 0, timo;
670         u_int ni;
671
672         if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
673                 /* forgiving; slightly wrong */
674                 SCARG(uap, nd) = p->p_fd->fd_nfiles;
675         }
676         ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
677         if (SCARG(uap, nd) > FD_SETSIZE) {
678                 caddr_t mbits;
679
680                 if ((mbits = malloc(ni * 6, M_TEMP, M_WAITOK)) == NULL) {
681                         error = EINVAL;
682                         goto cleanup;
683                 }
684                 bzero(mbits, ni * 6);
685                 pibits[0] = (fd_set *)&mbits[ni * 0];
686                 pibits[1] = (fd_set *)&mbits[ni * 1];
687                 pibits[2] = (fd_set *)&mbits[ni * 2];
688                 pobits[0] = (fd_set *)&mbits[ni * 3];
689                 pobits[1] = (fd_set *)&mbits[ni * 4];
690                 pobits[2] = (fd_set *)&mbits[ni * 5];
691         } else {
692                 bzero((caddr_t)bits, sizeof(bits));
693                 pibits[0] = &bits[0];
694                 pibits[1] = &bits[1];
695                 pibits[2] = &bits[2];
696                 pobits[0] = &bits[3];
697                 pobits[1] = &bits[4];
698                 pobits[2] = &bits[5];
699         }
700
701 #define getbits(name, x) \
702         if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
703             (caddr_t)pibits[x], ni))) \
704                 goto done;
705         getbits(in, 0);
706         getbits(ou, 1);
707         getbits(ex, 2);
708 #undef  getbits
709
710         if (SCARG(uap, tv)) {
711                 error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
712                         sizeof (atv));
713                 if (error)
714                         goto done;
715                 if (itimerfix(&atv)) {
716                         error = EINVAL;
717                         goto done;
718                 }
719                 s = splclock();
720                 timeradd(&atv, &time, &atv);
721                 timo = hzto(&atv);
722                 /*
723                  * Avoid inadvertently sleeping forever.
724                  */
725                 if (timo == 0)
726                         timo = 1;
727                 splx(s);
728         } else
729                 timo = 0;
730 retry:
731         ncoll = nselcoll;
732         p->p_flag |= P_SELECT;
733         error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval);
734         if (error || *retval)
735                 goto done;
736         s = splhigh();
737         /* this should be timercmp(&time, &atv, >=) */
738         if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec ||
739             (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) {
740                 splx(s);
741                 goto done;
742         }
743         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
744                 splx(s);
745                 goto retry;
746         }
747         p->p_flag &= ~P_SELECT;
748         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
749         splx(s);
750         if (error == 0)
751                 goto retry;
752 done:
753         p->p_flag &= ~P_SELECT;
754         /* select is not restarted after signals... */
755         if (error == ERESTART)
756                 error = EINTR;
757         if (error == EWOULDBLOCK)
758                 error = 0;
759 #define putbits(name, x) \
760         if (SCARG(uap, name) && (error2 = copyout((caddr_t)pobits[x], \
761             (caddr_t)SCARG(uap, name), ni))) \
762                 error = error2;
763         if (error == 0) {
764                 int error2;
765
766                 putbits(in, 0);
767                 putbits(ou, 1);
768                 putbits(ex, 2);
769 #undef putbits
770         }
771         
772 cleanup:
773         if (pibits[0] != &bits[0])
774                 free(pibits[0], M_TEMP);
775         return (error);
776 }
777
778 int
779 selscan(p, ibits, obits, nfd, retval)
780         struct proc *p;
781         fd_set *ibits, *obits;
782         int nfd;
783         register_t *retval;
784 {
785         caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits;
786         register struct filedesc *fdp = p->p_fd;
787         register int msk, i, j, fd;
788         register fd_mask bits;
789         struct file *fp;
790         int ni, n = 0;
791         static int flag[3] = { FREAD, FWRITE, 0 };
792
793         /*
794          * if nfd > FD_SETSIZE then the fd_set's contain nfd bits (rounded
795          * up to the next byte) otherwise the fd_set's are normal sized.
796          */
797         ni = sizeof(fd_set);
798         if (nfd > FD_SETSIZE)
799                 ni = howmany(nfd, NFDBITS) * sizeof(fd_mask);
800
801         for (msk = 0; msk < 3; msk++) {
802                 fd_set *pibits = (fd_set *)&cibits[msk*ni];
803                 fd_set *pobits = (fd_set *)&cobits[msk*ni];
804
805                 for (i = 0; i < nfd; i += NFDBITS) {
806                         bits = pibits->fds_bits[i/NFDBITS];
807                         while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
808                                 bits &= ~(1 << j);
809                                 fp = fdp->fd_ofiles[fd];
810                                 if (fp == NULL)
811                                         return (EBADF);
812                                 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
813                                         FD_SET(fd, pobits);
814                                         n++;
815                                 }
816                         }
817                 }
818         }
819         *retval = n;
820         return (0);
821 }
822
823 /*ARGSUSED*/
824 int
825 seltrue(dev, flag, p)
826         dev_t dev;
827         int flag;
828         struct proc *p;
829 {
830
831         return (1);
832 }
833
834 /*
835  * Record a select request.
836  */
837 void
838 selrecord(selector, sip)
839         struct proc *selector;
840         struct selinfo *sip;
841 {
842         struct proc *p;
843         pid_t mypid;
844
845         mypid = selector->p_pid;
846         if (sip->si_selpid == mypid)
847                 return;
848         if (sip->si_selpid && (p = pfind(sip->si_selpid)) &&
849             p->p_wchan == (caddr_t)&selwait)
850                 sip->si_flags |= SI_COLL;
851         else
852                 sip->si_selpid = mypid;
853 }
854
855 /*
856  * Do a wakeup when a selectable event occurs.
857  */
858 void
859 selwakeup(sip)
860         register struct selinfo *sip;
861 {
862         register struct proc *p;
863         int s;
864
865         if (sip->si_selpid == 0)
866                 return;
867         if (sip->si_flags & SI_COLL) {
868                 nselcoll++;
869                 sip->si_flags &= ~SI_COLL;
870                 wakeup((caddr_t)&selwait);
871         }
872         p = pfind(sip->si_selpid);
873         sip->si_selpid = 0;
874         if (p != NULL) {
875                 s = splhigh();
876                 if (p->p_wchan == (caddr_t)&selwait) {
877                         if (p->p_stat == SSLEEP)
878                                 setrunnable(p);
879                         else
880                                 unsleep(p);
881                 } else if (p->p_flag & P_SELECT)
882                         p->p_flag &= ~P_SELECT;
883                 splx(s);
884         }
885 }
886
887 void
888 pollscan(p, pl, nfd, retval)
889         struct proc *p;
890         struct pollfd *pl;
891         int nfd;
892         register_t *retval;
893 {
894         register struct filedesc *fdp = p->p_fd;
895         register int msk, i;
896         struct file *fp;
897         int x, n = 0;
898         static int flag[3] = { FREAD, FWRITE, 0 };
899         static int pflag[3] = { POLLIN|POLLRDNORM, POLLOUT, POLLERR };
900
901         /* 
902          * XXX: We need to implement the rest of the flags.
903          */
904         for (i = 0; i < nfd; i++) {
905                 /* Check the file descriptor. */
906                 if (pl[i].fd < 0)
907                         continue;
908                 if (pl[i].fd >= fdp->fd_nfiles) {
909                         pl[i].revents = POLLNVAL;
910                         n++;
911                         continue;
912                 }
913
914                 fp = fdp->fd_ofiles[pl[i].fd];
915                 if (fp == NULL) {
916                         pl[i].revents = POLLNVAL;
917                         n++;
918                         continue;
919                 }
920                 for (x = msk = 0; msk < 3; msk++) {
921                         if (pl[i].events & pflag[msk]) {
922                                 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
923                                         pl[i].revents |= pflag[msk] &
924                                             pl[i].events;
925                                         x++;
926                                 }
927                         }
928                 }
929                 if (x)
930                         n++;
931         }
932         *retval = n;
933 }
934
935 /*
936  * We are using the same mechanism as select only we encode/decode args
937  * differently.
938  */
939 int
940 sys_poll(p, v, retval)
941         register struct proc *p;
942         void *v;
943         register_t *retval;
944 {
945         struct sys_poll_args *uap = v;
946         size_t sz;
947         struct pollfd pfds[4], *pl = pfds;
948         int msec = SCARG(uap, timeout);
949         struct timeval atv;
950         int timo, ncoll, i, s, error, error2;
951         extern int nselcoll, selwait;
952
953         /* Standards say no more than MAX_OPEN; this is possibly better. */
954         if (SCARG(uap, nfds) > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, 
955             maxfiles))
956                 return (EINVAL);
957
958         sz = sizeof(struct pollfd) * SCARG(uap, nfds);
959         
960         /* optimize for the default case, of a small nfds value */
961         if (sz > sizeof(pfds))
962                 pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK);
963
964         if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)
965                 goto bad;
966
967         for (i = 0; i < SCARG(uap, nfds); i++)
968                 pl[i].revents = 0;
969
970         if (msec != -1) {
971                 atv.tv_sec = msec / 1000;
972                 atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000;
973
974                 if (itimerfix(&atv)) {
975                         error = EINVAL;
976                         goto done;
977                 }
978                 s = splclock();
979                 timeradd(&atv, &time, &atv);
980                 timo = hzto(&atv);
981                 /*
982                  * Avoid inadvertently sleeping forever.
983                  */
984                 if (timo == 0)
985                         timo = 1;
986                 splx(s);
987         } else
988                 timo = 0;
989
990 retry:
991         ncoll = nselcoll;
992         p->p_flag |= P_SELECT;
993         pollscan(p, pl, SCARG(uap, nfds), retval);
994         if (*retval)
995                 goto done;
996         s = splhigh();
997         if (timo && timercmp(&time, &atv, >=)) {
998                 splx(s);
999                 goto done;
1000         }
1001         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
1002                 splx(s);
1003                 goto retry;
1004         }
1005         p->p_flag &= ~P_SELECT;
1006         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
1007         splx(s);
1008         if (error == 0)
1009                 goto retry;
1010
1011 done:
1012         p->p_flag &= ~P_SELECT;
1013         /* poll is not restarted after signals... */
1014         if (error == ERESTART)
1015                 error = EINTR;
1016         if (error == EWOULDBLOCK)
1017                 error = 0;
1018         if ((error2 = copyout(pl, SCARG(uap, fds), sz)) != 0)
1019                 error = error2;
1020 bad:
1021         if (pl != pfds)
1022                 free((char *) pl, M_TEMP);
1023         return (error);
1024 }
1025 #endif