Annotation of XNU/bsd/kern/sys_generic.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            23: /*
        !            24:  * Copyright (c) 1982, 1986, 1989, 1993
        !            25:  *     The Regents of the University of California.  All rights reserved.
        !            26:  * (c) UNIX System Laboratories, Inc.
        !            27:  * All or some portions of this file are derived from material licensed
        !            28:  * to the University of California by American Telephone and Telegraph
        !            29:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            30:  * the permission of UNIX System Laboratories, Inc.
        !            31:  *
        !            32:  * Redistribution and use in source and binary forms, with or without
        !            33:  * modification, are permitted provided that the following conditions
        !            34:  * are met:
        !            35:  * 1. Redistributions of source code must retain the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer.
        !            37:  * 2. Redistributions in binary form must reproduce the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer in the
        !            39:  *    documentation and/or other materials provided with the distribution.
        !            40:  * 3. All advertising materials mentioning features or use of this software
        !            41:  *    must display the following acknowledgement:
        !            42:  *     This product includes software developed by the University of
        !            43:  *     California, Berkeley and its contributors.
        !            44:  * 4. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)sys_generic.c       8.9 (Berkeley) 2/14/95
        !            61:  */
        !            62: 
        !            63: #include <sys/param.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/filedesc.h>
        !            66: #include <sys/ioctl.h>
        !            67: #include <sys/file.h>
        !            68: #include <sys/proc.h>
        !            69: #include <sys/socketvar.h>
        !            70: #include <sys/uio.h>
        !            71: #include <sys/kernel.h>
        !            72: #include <sys/stat.h>
        !            73: #include <sys/malloc.h>
        !            74: 
        !            75: #if KTRACE
        !            76: #include <sys/ktrace.h>
        !            77: #endif
        !            78: 
        !            79: #include <sys/mount.h>
        !            80: #include <sys/protosw.h>
        !            81: #include <sys/ev.h>
        !            82: #include <sys/user.h>
        !            83: #include <sys/kdebug.h>
        !            84: #include <kern/assert.h>
        !            85: #include <kern/thread_act.h>
        !            86: 
        !            87: #include <sys/mbuf.h>
        !            88: #include <sys/socket.h>
        !            89: #include <sys/socketvar.h>
        !            90: #include <sys/errno.h>
        !            91: 
        !            92: #include <net/if.h>
        !            93: #include <net/route.h>
        !            94: 
        !            95: #include <netinet/in.h>
        !            96: #include <netinet/in_systm.h>
        !            97: #include <netinet/ip.h>
        !            98: #include <netinet/in_pcb.h>
        !            99: #include <netinet/ip_var.h>
        !           100: #include <netinet/tcp.h>
        !           101: #include <netinet/tcp_fsm.h>
        !           102: #include <netinet/tcp_seq.h>
        !           103: #include <netinet/tcp_timer.h>
        !           104: #include <netinet/tcp_var.h>
        !           105: #include <netinet/tcpip.h>
        !           106: #include <netinet/tcp_debug.h>
        !           107: 
        !           108: /*
        !           109:  * Read system call.
        !           110:  */
        !           111: struct read_args {
        !           112:        int fd;
        !           113:        char *cbuf;
        !           114:        u_int nbyte;
        !           115: };
        !           116: /* ARGSUSED */
        !           117: read(p, uap, retval)
        !           118:        struct proc *p;
        !           119:        register struct read_args *uap;
        !           120:        register_t *retval;
        !           121: {
        !           122:        struct uio auio;
        !           123:        struct iovec aiov;
        !           124: 
        !           125:        aiov.iov_base = (caddr_t)uap->cbuf;
        !           126:        aiov.iov_len = uap->nbyte;
        !           127:        auio.uio_iov = &aiov;
        !           128:        auio.uio_iovcnt = 1;
        !           129:        auio.uio_rw = UIO_READ;
        !           130:        return (rwuio(p, uap->fd, &auio, UIO_READ, retval));    
        !           131: }
        !           132: 
        !           133: struct readv_args {
        !           134:        int fd;
        !           135:        struct iovec *iovp;
        !           136:        u_int iovcnt;
        !           137: };
        !           138: readv(p, uap, retval)
        !           139:        struct proc *p;
        !           140:        register struct readv_args *uap;
        !           141:        int *retval;
        !           142: {
        !           143:        struct uio auio;
        !           144:        register struct iovec *iov;
        !           145:        int error;
        !           146:        struct iovec aiov[UIO_SMALLIOV];
        !           147: 
        !           148:        if (uap->iovcnt > UIO_SMALLIOV) {
        !           149:                if (uap->iovcnt > UIO_MAXIOV)
        !           150:                        return (EINVAL);        
        !           151:                if ((iov = (struct iovec *)
        !           152:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
        !           153:                        return (ENOMEM);
        !           154:        } else
        !           155:                iov = aiov;
        !           156:        auio.uio_iov = iov;
        !           157:        auio.uio_iovcnt = uap->iovcnt;
        !           158:        auio.uio_rw = UIO_READ;
        !           159:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
        !           160:            uap->iovcnt * sizeof (struct iovec));
        !           161:        if (!error)
        !           162:                error = rwuio(p, uap->fd, &auio, UIO_READ, retval);
        !           163:        if (uap->iovcnt > UIO_SMALLIOV)
        !           164:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
        !           165:        return (error);
        !           166: }
        !           167: 
        !           168: /*
        !           169:  * Write system call
        !           170:  */
        !           171: struct write_args {
        !           172:        int fd;
        !           173:        char *cbuf;
        !           174:        u_int nbyte;
        !           175: };
        !           176: write(p, uap, retval)
        !           177:        struct proc *p;
        !           178:        register struct write_args *uap;
        !           179:        int *retval;
        !           180: {
        !           181:        struct uio auio;
        !           182:        struct iovec aiov;
        !           183: 
        !           184:        aiov.iov_base = uap->cbuf;
        !           185:        aiov.iov_len = uap->nbyte;
        !           186:        auio.uio_iov = &aiov;
        !           187:        auio.uio_iovcnt = 1;
        !           188:        auio.uio_rw = UIO_WRITE;
        !           189:        return (rwuio(p, uap->fd, &auio, UIO_WRITE, retval));
        !           190: }
        !           191: 
        !           192: struct writev_args {
        !           193:        int fd;
        !           194:        struct iovec *iovp;
        !           195:        u_int iovcnt;
        !           196: };
        !           197: writev(p, uap, retval)
        !           198:        struct proc *p;
        !           199:        register struct writev_args *uap;
        !           200:        int *retval;
        !           201: {
        !           202:        struct uio auio;
        !           203:        register struct iovec *iov;
        !           204:        int error;
        !           205:        struct iovec aiov[UIO_SMALLIOV];
        !           206: 
        !           207:        if (uap->iovcnt > UIO_SMALLIOV) {
        !           208:                if (uap->iovcnt > UIO_MAXIOV)
        !           209:                        return (EINVAL);        
        !           210:                if ((iov = (struct iovec *)
        !           211:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
        !           212:                        return (ENOMEM);
        !           213:        } else
        !           214:                iov = aiov;
        !           215:        auio.uio_iov = iov;
        !           216:        auio.uio_iovcnt = uap->iovcnt;
        !           217:        auio.uio_rw = UIO_WRITE;
        !           218:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
        !           219:            uap->iovcnt * sizeof (struct iovec));
        !           220:        if (!error)
        !           221:                error = rwuio(p, uap->fd, &auio, UIO_WRITE, retval);
        !           222:        if (uap->iovcnt > UIO_SMALLIOV)
        !           223:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
        !           224:        return (error);
        !           225: }
        !           226: 
        !           227: rwuio(p, fdes, uio, rw, retval)
        !           228:        struct proc *p;
        !           229:        int fdes;
        !           230:        register struct uio *uio;
        !           231:        enum uio_rw rw;
        !           232:        int *retval;
        !           233: {
        !           234:        register struct file *fp;
        !           235:        register struct iovec *iov;
        !           236:        int i, count, flag, error;
        !           237: 
        !           238:        if (error = fdgetf(p, fdes, &fp))
        !           239:                return (error);
        !           240: 
        !           241:        if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
        !           242:                return(EBADF);
        !           243:        }
        !           244:        uio->uio_resid = 0;
        !           245:        uio->uio_segflg = UIO_USERSPACE;
        !           246:        uio->uio_procp = p;
        !           247:        iov = uio->uio_iov;
        !           248:        for (i = 0; i < uio->uio_iovcnt; i++) {
        !           249:                if (iov->iov_len < 0) {
        !           250:                        return(EINVAL);
        !           251:                }
        !           252:                uio->uio_resid += iov->iov_len;
        !           253:                if (uio->uio_resid < 0) {
        !           254:                        return(EINVAL);
        !           255:                }
        !           256:                iov++;
        !           257:        }
        !           258:        count = uio->uio_resid;
        !           259:        if (rw == UIO_READ) {
        !           260:                if (error = (*fp->f_ops->fo_read)(fp, uio, fp->f_cred))
        !           261:                                if (uio->uio_resid != count && (error == ERESTART ||
        !           262:                                        error == EINTR || error == EWOULDBLOCK))
        !           263:                                                error = 0;
        !           264:        } else {
        !           265:                if (error = (*fp->f_ops->fo_write)(fp, uio, fp->f_cred)) {
        !           266:                        if (uio->uio_resid != count && (error == ERESTART ||
        !           267:                        error == EINTR || error == EWOULDBLOCK))
        !           268:                                error = 0;
        !           269:                        if (error == EPIPE)
        !           270:                                psignal(p, SIGPIPE);
        !           271:                }
        !           272:        }
        !           273:        *retval = count - uio->uio_resid;
        !           274:        return(error);
        !           275: }
        !           276: 
        !           277: /*
        !           278:  * Ioctl system call
        !           279:  */
        !           280: struct ioctl_args {
        !           281:        int fd;
        !           282:        u_long com;
        !           283:        caddr_t data;
        !           284: };
        !           285: /* ARGSUSED */
        !           286: ioctl(p, uap, retval)
        !           287:        struct proc *p;
        !           288:        register struct ioctl_args *uap;
        !           289:        register_t *retval;
        !           290: {
        !           291:        register struct file *fp;
        !           292:        register u_long com;
        !           293:        register int error;
        !           294:        register u_int size;
        !           295:        caddr_t data, memp;
        !           296:        int tmp;
        !           297: #define STK_PARAMS     128
        !           298:        char stkbuf[STK_PARAMS];
        !           299: 
        !           300:        if (error = fdgetf(p, uap->fd, &fp))
        !           301:                return (error);
        !           302: 
        !           303:        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
        !           304:                return (EBADF);
        !           305:                
        !           306:        /*### LD 6/11/97 Hack Alert: this is to get AppleTalk to work
        !           307:         * while implementing an ATioctl system call
        !           308:         */
        !           309: #if NETAT
        !           310:        {
        !           311:                extern int appletalk_inited;
        !           312: 
        !           313:                if (appletalk_inited && ((uap->com & 0x0000FFFF) == 0xff99)) {
        !           314: #ifdef APPLETALK_DEBUG
        !           315:                        kprintf("ioctl: special AppleTalk \n");
        !           316: #endif
        !           317:                        error = (*fp->f_ops->fo_ioctl)(fp, uap->com, uap->data, p);
        !           318:                        return(error);
        !           319:                }
        !           320:        }
        !           321: 
        !           322: #endif /* NETAT */
        !           323: 
        !           324: 
        !           325:        switch (com = uap->com) {
        !           326:        case FIONCLEX:
        !           327:                *fdflags(p, uap->fd) &= ~UF_EXCLOSE;
        !           328:                return (0);
        !           329:        case FIOCLEX:
        !           330:                *fdflags(p, uap->fd) |= UF_EXCLOSE;
        !           331:                return (0);
        !           332:        }
        !           333: 
        !           334:        /*
        !           335:         * Interpret high order word to find amount of data to be
        !           336:         * copied to/from the user's address space.
        !           337:         */
        !           338:        size = IOCPARM_LEN(com);
        !           339:        if (size > IOCPARM_MAX)
        !           340:                return (ENOTTY);
        !           341:        memp = NULL;
        !           342:        if (size > sizeof (stkbuf)) {
        !           343:                if ((memp = (caddr_t)kalloc(size)) == 0)
        !           344:                        return(ENOMEM);
        !           345:                data = memp;
        !           346:        } else
        !           347:                data = stkbuf;
        !           348:        if (com&IOC_IN) {
        !           349:                if (size) {
        !           350:                        error = copyin(uap->data, data, (u_int)size);
        !           351:                        if (error) {
        !           352:                                if (memp)
        !           353:                                        kfree(memp, size);
        !           354:                                return (error);
        !           355:                        }
        !           356:                } else
        !           357:                        *(caddr_t *)data = uap->data;
        !           358:        } else if ((com&IOC_OUT) && size)
        !           359:                /*
        !           360:                 * Zero the buffer so the user always
        !           361:                 * gets back something deterministic.
        !           362:                 */
        !           363:                bzero(data, size);
        !           364:        else if (com&IOC_VOID)
        !           365:                *(caddr_t *)data = uap->data;
        !           366: 
        !           367:        switch (com) {
        !           368: 
        !           369:        case FIONBIO:
        !           370:                if (tmp = *(int *)data)
        !           371:                        fp->f_flag |= FNONBLOCK;
        !           372:                else
        !           373:                        fp->f_flag &= ~FNONBLOCK;
        !           374:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
        !           375:                break;
        !           376: 
        !           377:        case FIOASYNC:
        !           378:                if (tmp = *(int *)data)
        !           379:                        fp->f_flag |= FASYNC;
        !           380:                else
        !           381:                        fp->f_flag &= ~FASYNC;
        !           382:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
        !           383:                break;
        !           384: 
        !           385:        case FIOSETOWN:
        !           386:                tmp = *(int *)data;
        !           387:                if (fp->f_type == DTYPE_SOCKET) {
        !           388:                        ((struct socket *)fp->f_data)->so_pgid = tmp;
        !           389:                        error = 0;
        !           390:                        break;
        !           391:                }
        !           392:                if (tmp <= 0) {
        !           393:                        tmp = -tmp;
        !           394:                } else {
        !           395:                        struct proc *p1 = pfind(tmp);
        !           396:                        if (p1 == 0) {
        !           397:                                error = ESRCH;
        !           398:                                break;
        !           399:                        }
        !           400:                        tmp = p1->p_pgrp->pg_id;
        !           401:                }
        !           402:                error = (*fp->f_ops->fo_ioctl)
        !           403:                        (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
        !           404:                break;
        !           405: 
        !           406:        case FIOGETOWN:
        !           407:                if (fp->f_type == DTYPE_SOCKET) {
        !           408:                        error = 0;
        !           409:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
        !           410:                        break;
        !           411:                }
        !           412:                error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
        !           413:                *(int *)data = -*(int *)data;
        !           414:                break;
        !           415: 
        !           416:        default:
        !           417:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
        !           418:                /*
        !           419:                 * Copy any data to user, size was
        !           420:                 * already set and checked above.
        !           421:                 */
        !           422:                if (error == 0 && (com&IOC_OUT) && size)
        !           423:                        error = copyout(data, uap->data, (u_int)size);
        !           424:                break;
        !           425:        }
        !           426:        if (memp)
        !           427:                kfree(memp, size);
        !           428:        return (error);
        !           429: }
        !           430: 
        !           431: 
        !           432: int    selwait, nselcoll;
        !           433: 
        !           434: /*
        !           435:  * Select system call.
        !           436:  */
        !           437: struct select_args {
        !           438:        u_int nd;
        !           439:        fd_set *in;
        !           440:        fd_set *ou;
        !           441:        fd_set *ex;
        !           442:        struct timeval *tv;
        !           443: };
        !           444: 
        !           445: int selcontinue(int error);
        !           446: 
        !           447: select(p, uap, retval)
        !           448:        register struct proc *p;
        !           449:        register struct select_args *uap;
        !           450:        register_t *retval;
        !           451: {
        !           452:        int s, ncoll, error = 0, timo;
        !           453:        u_int ni;
        !           454:        struct thread *th;
        !           455:        thread_act_t th_act;
        !           456:        struct uthread  *uth;
        !           457:        struct _select *sel;
        !           458: 
        !           459:        th = current_thread();
        !           460:        th_act = current_act();
        !           461:        uth = get_bsdthread_info(th_act);
        !           462:        sel = &uth->uu_state.ss_select;
        !           463: 
        !           464:        bzero((caddr_t)&sel->ibits[0], sizeof(sel->ibits));
        !           465:        bzero((caddr_t)&sel->obits[0], sizeof(sel->obits));
        !           466: 
        !           467:        if (uap->nd > FD_SETSIZE)
        !           468:                return (EINVAL);
        !           469:        if (uap->nd > p->p_fd->fd_nfiles) {
        !           470:                /* forgiving; slightly wrong */
        !           471:                uap->nd = p->p_fd->fd_nfiles;
        !           472:        }
        !           473:        ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
        !           474: 
        !           475: #define        getbits(name, x) \
        !           476:        if (uap->name && (error = copyin((caddr_t)uap->name, \
        !           477:            (caddr_t)&sel->ibits[x], ni))) \
        !           478:                goto contin;
        !           479:        getbits(in, 0);
        !           480:        getbits(ou, 1);
        !           481:        getbits(ex, 2);
        !           482: #undef getbits
        !           483: 
        !           484:        if (uap->tv) {
        !           485:                error = copyin((caddr_t)uap->tv, (caddr_t)&sel->atv,
        !           486:                        sizeof (sel->atv));
        !           487:                if (error)
        !           488:                        goto contin;
        !           489:                if (itimerfix(&sel->atv)) {
        !           490:                        error = EINVAL;
        !           491:                        goto contin;
        !           492:                }
        !           493:                s = splhigh();
        !           494:                timeradd(&sel->atv, &time, &sel->atv);
        !           495:                timo = hzto(&sel->atv);
        !           496:                splx(s);
        !           497:        } else
        !           498:                timo = 0;
        !           499:        sel->poll = timo;
        !           500: contin:
        !           501:        selcontinue(error);
        !           502: }
        !           503: 
        !           504: int
        !           505: selcontinue(error)
        !           506: {
        !           507:        int s, ncoll, timo;
        !           508:        u_int ni;
        !           509:        struct thread *th;
        !           510:        thread_act_t th_act;
        !           511:        struct uthread  *uth;
        !           512:        struct proc *p;
        !           513:        struct select_args *uap;
        !           514:        int *retval;
        !           515:        struct _select *sel;
        !           516: 
        !           517:        th = (struct thread *)current_thread();
        !           518:        th_act = current_act();
        !           519:        uth = get_bsdthread_info(th_act);
        !           520:        p = (struct proc *)get_bsdtask_info(current_task());
        !           521:        uap = (struct select_args *)get_bsduthreadarg(th_act);
        !           522:        retval = (int *)get_bsduthreadrval(th_act);
        !           523:        sel = &uth->uu_state.ss_select;
        !           524: 
        !           525: retry:
        !           526:        if (error != 0)
        !           527:          goto done;
        !           528:        ncoll = nselcoll;
        !           529:        p->p_flag |= P_SELECT;
        !           530:        error = selscan(p, &sel->ibits[0], &sel->obits[0], uap->nd, retval);
        !           531:        if (error || *retval)
        !           532:                goto done;
        !           533:        s = splhigh();
        !           534:        /* this should be timercmp(&time, &atv, >=) */
        !           535:        if (uap->tv && (time.tv_sec > sel->atv.tv_sec ||
        !           536:            time.tv_sec == sel->atv.tv_sec && time.tv_usec >= sel->atv.tv_usec)) {
        !           537:                splx(s);
        !           538:                goto done;
        !           539:        }
        !           540:        /*
        !           541:         * To effect a poll, the timeout argument should be
        !           542:         * non-nil, pointing to a zero-valued timeval structure.
        !           543:         */
        !           544:        timo = sel->poll;
        !           545: 
        !           546:        if (uap->tv && (timo == 0)) {
        !           547:                splx(s);
        !           548:                goto done;
        !           549:        }
        !           550:        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
        !           551:                splx(s);
        !           552:                goto retry;
        !           553:        }
        !           554:        p->p_flag &= ~P_SELECT;
        !           555: 
        !           556: #if 1
        !           557:         error = tsleep0((caddr_t)&selwait, PSOCK | PCATCH, "select", timo, selcontinue);
        !           558:         /* NOTREACHED */
        !           559: #else
        !           560:         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
        !           561: #endif
        !           562:        splx(s);
        !           563:        if (error == 0)
        !           564:                goto retry;
        !           565: done:
        !           566:        p->p_flag &= ~P_SELECT;
        !           567:        /* select is not restarted after signals... */
        !           568:        if (error == ERESTART)
        !           569:                error = EINTR;
        !           570:        if (error == EWOULDBLOCK)
        !           571:                error = 0;
        !           572:        ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
        !           573: #define        putbits(name, x) \
        !           574:        if (uap->name && (error2 = copyout((caddr_t)&sel->obits[x], \
        !           575:            (caddr_t)uap->name, ni))) \
        !           576:                error = error2;
        !           577:        if (error == 0) {
        !           578:                int error2;
        !           579: 
        !           580:                putbits(in, 0);
        !           581:                putbits(ou, 1);
        !           582:                putbits(ex, 2);
        !           583: #undef putbits
        !           584:        }
        !           585: 
        !           586:         unix_syscall_return(error);
        !           587: }
        !           588: 
        !           589: selscan(p, ibits, obits, nfd, retval)
        !           590:        struct proc *p;
        !           591:        fd_set *ibits, *obits;
        !           592:        int nfd;
        !           593:        register_t *retval;
        !           594: {
        !           595:        register struct filedesc *fdp = p->p_fd;
        !           596:        register int msk, i, j, fd;
        !           597:        register fd_mask bits;
        !           598:        struct file *fp;
        !           599:        int n = 0;
        !           600:        static int flag[3] = { FREAD, FWRITE, 0 };
        !           601: 
        !           602:        /* Problems when reboot; due to MacOSX signal probs
        !           603:         * in Beaker1C ; verify that the p->p_fd is valid
        !           604:         */
        !           605:        if (fdp == NULL) {
        !           606:                *retval=0;
        !           607:                return(EIO);
        !           608:        }
        !           609: 
        !           610:        for (msk = 0; msk < 3; msk++) {
        !           611:                for (i = 0; i < nfd; i += NFDBITS) {
        !           612:                        bits = ibits[msk].fds_bits[i/NFDBITS];
        !           613:                        while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
        !           614:                                bits &= ~(1 << j);
        !           615:                                fp = fdp->fd_ofiles[fd];
        !           616:                                if (fp == NULL || (fdp->fd_ofileflags[fd] &
        !           617:                                                                UF_RESERVED))
        !           618:                                        return (EBADF);
        !           619:                                if (fp->f_ops && (*fp->f_ops->fo_select)(fp, flag[msk], p)) {
        !           620:                                        FD_SET(fd, &obits[msk]);
        !           621:                                        n++;
        !           622:                                }
        !           623:                        }
        !           624:                }
        !           625:        }
        !           626:        *retval = n;
        !           627:        return (0);
        !           628: }
        !           629: 
        !           630: /*ARGSUSED*/
        !           631: seltrue(dev, flag, p)
        !           632:        dev_t dev;
        !           633:        int flag;
        !           634:        struct proc *p;
        !           635: {
        !           636: 
        !           637:        return (1);
        !           638: }
        !           639: 
        !           640: /*
        !           641:  * Record a select request.
        !           642:  */
        !           643: void
        !           644: selrecord(selector, sip)
        !           645:        struct proc *selector;
        !           646:        struct selinfo *sip;
        !           647: {
        !           648:        int             oldpri = splhigh();
        !           649:        thread_t        my_thread = current_thread();
        !           650:        thread_t        selthread;
        !           651: 
        !           652:        selthread = sip->si_thread;
        !           653:        
        !           654:        if (selthread == my_thread) {
        !           655:                splx(oldpri);
        !           656:                return;
        !           657:        }
        !           658:        
        !           659:        if (selthread && is_thread_active(selthread) &&
        !           660:            get_thread_waitevent(selthread) == (caddr_t)&selwait) {
        !           661:                        sip->si_flags |= SI_COLL;
        !           662:                        splx(oldpri);
        !           663:        }
        !           664:        else {
        !           665:                        sip->si_thread = my_thread;
        !           666:                        splx(oldpri);
        !           667:                        if (selthread) {
        !           668:                                /* thread_deallocate(selthread); */
        !           669:                                act_deallocate(getact_thread(selthread));
        !           670:                        }
        !           671:                        /* do I need act reference ??? */
        !           672:                        /* thread_reference(sip->si_thread); */
        !           673:                        act_reference(getact_thread(sip->si_thread));
        !           674:        }
        !           675: 
        !           676:        return;
        !           677: }
        !           678: 
        !           679: void
        !           680: selwakeup(sip)
        !           681:        register struct selinfo *sip;
        !           682: {
        !           683:        register thread_t       the_thread = (thread_t)sip->si_thread;
        !           684:        int oldpri;
        !           685:        struct proc *p;
        !           686:        thread_act_t th_act;
        !           687:        
        !           688:        if (the_thread == 0)
        !           689:                return;
        !           690: 
        !           691:        if (sip->si_flags & SI_COLL) {
        !           692:                nselcoll++;
        !           693:                sip->si_flags &= ~SI_COLL;
        !           694:                wakeup((caddr_t)&selwait);
        !           695:        }
        !           696:        
        !           697:        oldpri = splhigh();
        !           698: 
        !           699:        th_act = getact_thread(the_thread);
        !           700: 
        !           701:        if (is_thread_active(the_thread)) {
        !           702:                /* protect p_flag minimally at splsched() */
        !           703:                if (get_thread_waitevent(the_thread) == &selwait)
        !           704:                        clear_wait(the_thread, THREAD_AWAKENED, TRUE);
        !           705:                if (p=(struct proc *)(get_bsdtask_info(get_threadtask(th_act))))
        !           706:                        p->p_flag &= ~P_SELECT;
        !           707:        }
        !           708:        
        !           709:        th_act = getact_thread(the_thread);
        !           710: 
        !           711:        act_deallocate(th_act);
        !           712:        
        !           713:        sip->si_thread = 0;
        !           714:        
        !           715:        splx(oldpri);
        !           716:        
        !           717: }
        !           718: 
        !           719: void selthreadclear(sip)
        !           720:        register struct selinfo *sip;
        !           721: {
        !           722:        thread_act_t th_act;
        !           723: 
        !           724:        if (sip->si_thread) {
        !           725:                        th_act = getact_thread(sip->si_thread);
        !           726:                        act_deallocate(th_act);
        !           727:        }
        !           728: 
        !           729: }
        !           730: /*
        !           731:  * called upon socket close. deque and free all events for
        !           732:  * the socket
        !           733:  */
        !           734: evsofree(struct socket *sp)
        !           735: {
        !           736:   struct eventqelt *eqp, *next;
        !           737: 
        !           738:   if (sp == NULL) return;
        !           739: 
        !           740:   for (eqp = sp->so_evlist.tqh_first; eqp != NULL; eqp = next) {
        !           741:     next = eqp->ee_slist.tqe_next;
        !           742:     evprocdeque(eqp->ee_proc, eqp); // remove from proc q if there
        !           743:     TAILQ_REMOVE(&sp->so_evlist, eqp, ee_slist); // remove from socket q
        !           744:     FREE(eqp, M_TEMP);
        !           745:   }
        !           746: }
        !           747: 
        !           748: 
        !           749: #define DBG_EVENT 0x10
        !           750: 
        !           751: #define DBG_POST 0x10
        !           752: #define DBG_WATCH 0x11
        !           753: #define DBG_WAIT 0x12
        !           754: #define DBG_MOD 0x13
        !           755: #define DBG_EWAKEUP 0x14
        !           756: 
        !           757: #define DBG_MISC_POST MISCDBG_CODE(DBG_EVENT,DBG_POST)
        !           758: #define DBG_MISC_WATCH MISCDBG_CODE(DBG_EVENT,DBG_WATCH)
        !           759: #define DBG_MISC_WAIT MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
        !           760: #define DBG_MISC_MOD MISCDBG_CODE(DBG_EVENT,DBG_MOD)
        !           761: #define DBG_MISC_EWAKEUP MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
        !           762: 
        !           763: 
        !           764: 
        !           765: /*
        !           766:  * enque this event if it's not already queued. wakeup
        !           767:    the proc if we do queue this event to it.
        !           768:  */
        !           769: evprocenque(struct eventqelt *eqp)
        !           770: {
        !           771:   struct proc *p;
        !           772: 
        !           773:   assert(eqp);
        !           774:   if (eqp->ee_flags & EV_QUEUED) {
        !           775:     return;
        !           776:   }
        !           777:   eqp->ee_flags |= EV_QUEUED;
        !           778:   eqp->ee_eventmask = 0;  // disarm
        !           779:   p = eqp->ee_proc;
        !           780:   TAILQ_INSERT_TAIL(&p->p_evlist, eqp, ee_plist);
        !           781:   KERNEL_DEBUG(DBG_MISC_EWAKEUP,0,0,0,eqp,0);
        !           782:   wakeup(&p->p_evlist);
        !           783: }
        !           784: 
        !           785: /*
        !           786:  * given either a sockbuf or a socket run down the
        !           787:  * event list and queue ready events found
        !           788:  */
        !           789: postevent(struct socket *sp, struct sockbuf *sb, int event)
        !           790: {
        !           791:   int mask;
        !           792:   struct eventqelt *evq;
        !           793:   register struct tcpcb *tp;
        !           794: 
        !           795:   if (sb) sp = sb->sb_so;
        !           796:   if (!sp || sp->so_evlist.tqh_first == NULL) return;
        !           797: 
        !           798:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_START, 0,0,0,0,0);
        !           799: 
        !           800:   for (evq = sp->so_evlist.tqh_first;
        !           801:        evq != NULL; evq = evq->ee_slist.tqe_next) {
        !           802: 
        !           803:     mask = 0;
        !           804: 
        !           805:     /* ready for reading:
        !           806:        - byte cnt >= receive low water mark
        !           807:        - read-half of conn closed
        !           808:        - conn pending for listening sock
        !           809:        - socket error pending
        !           810: 
        !           811:        ready for writing
        !           812:        - byte cnt avail >= send low water mark
        !           813:        - write half of conn closed
        !           814:        - socket error pending
        !           815:        - non-blocking conn completed successfully
        !           816: 
        !           817:        exception pending
        !           818:        - out of band data
        !           819:        - sock at out of band mark
        !           820: 
        !           821:     */
        !           822:     switch (event & EV_DMASK) {
        !           823: 
        !           824:     case EV_RWBYTES:
        !           825:     case EV_OOB:
        !           826:     case EV_RWBYTES|EV_OOB:
        !           827:       if (event & EV_OOB) {
        !           828:       if ((evq->ee_eventmask & EV_EX)) {
        !           829:        if (sp->so_oobmark || ((sp->so_state & SS_RCVATMARK))) {
        !           830:          mask |= EV_EX|EV_OOB;
        !           831:        }
        !           832:       }
        !           833:       }
        !           834:       if (event & EV_RWBYTES) {
        !           835:       if ((evq->ee_eventmask & EV_RE) && soreadable(sp)) {
        !           836:        if ((sp->so_type == SOCK_STREAM) && (sp->so_error == ECONNREFUSED) ||
        !           837:            (sp->so_error == ECONNRESET)) {
        !           838:          if ((sp->so_pcb == 0) ||
        !           839:              !(tp = sototcpcb(sp)) ||
        !           840:              (tp->t_state == TCPS_CLOSED)) {
        !           841:            mask |= EV_RE|EV_RESET;
        !           842:            break;
        !           843:          }
        !           844:        }
        !           845:        if (sp->so_state & SS_CANTRCVMORE) {
        !           846:          mask |= EV_RE|EV_FIN;
        !           847:          evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
        !           848:          break;
        !           849:        }
        !           850:        mask |= EV_RE;
        !           851:        evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
        !           852:       }
        !           853: 
        !           854:       if ((evq->ee_eventmask & EV_WR) && sowriteable(sp)) {
        !           855:        if ((sp->so_type == SOCK_STREAM) &&(sp->so_error == ECONNREFUSED) ||
        !           856:            (sp->so_error == ECONNRESET)) {
        !           857:          if ((sp->so_pcb == 0) ||
        !           858:              !(tp = sototcpcb(sp)) ||
        !           859:              (tp->t_state == TCPS_CLOSED)) {
        !           860:          mask |= EV_WR|EV_RESET;
        !           861:          break;
        !           862:          }
        !           863:        }
        !           864:        mask |= EV_WR;
        !           865:        evq->ee_req.er_wcnt = sbspace(&sp->so_snd);
        !           866:       }
        !           867:       }
        !           868:     break;
        !           869: 
        !           870:     case EV_RCONN:
        !           871:       if ((evq->ee_eventmask & EV_RE)) {
        !           872:        evq->ee_req.er_rcnt = sp->so_qlen + 1;  // incl this one
        !           873:        mask |= EV_RE|EV_RCONN;
        !           874:       }
        !           875:       break;
        !           876: 
        !           877:     case EV_WCONN:
        !           878:       if ((evq->ee_eventmask & EV_WR)) {
        !           879:        mask |= EV_WR|EV_WCONN;
        !           880:       }
        !           881:       break;
        !           882: 
        !           883:     case EV_RCLOSED:
        !           884:       if ((evq->ee_eventmask & EV_RE)) {
        !           885:        mask |= EV_RE|EV_RCLOSED;
        !           886:       }
        !           887:       break;
        !           888: 
        !           889:     case EV_WCLOSED:
        !           890:       if ((evq->ee_eventmask & EV_WR)) {
        !           891:        mask |= EV_WR|EV_WCLOSED;
        !           892:       }
        !           893:       break;
        !           894: 
        !           895:     case EV_FIN:
        !           896:       if (evq->ee_eventmask & EV_RE) {
        !           897:        mask |= EV_RE|EV_FIN;
        !           898:       }
        !           899:       break;
        !           900: 
        !           901:     case EV_RESET:
        !           902:     case EV_TIMEOUT:
        !           903:       if (evq->ee_eventmask & EV_RE) {
        !           904:        mask |= EV_RE | event;
        !           905:       } 
        !           906:       if (evq->ee_eventmask & EV_WR) {
        !           907:        mask |= EV_WR | event;
        !           908:       }
        !           909:       break;
        !           910: 
        !           911:     default:
        !           912:       return;
        !           913:     } /* switch */
        !           914: 
        !           915:     if (mask) {
        !           916:       evq->ee_req.er_eventbits |= mask;
        !           917:       evprocenque(evq);
        !           918:     }
        !           919:   }
        !           920:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_END, 0,0,0,0,0);
        !           921: }
        !           922: 
        !           923: /*
        !           924:  * remove and return the first event (eqp=NULL) or a specific
        !           925:  * event, or return NULL if no events found
        !           926:  */
        !           927: struct eventqelt *
        !           928: evprocdeque(struct proc *p, struct eventqelt *eqp)
        !           929: {
        !           930: 
        !           931:   
        !           932:   if (eqp && ((eqp->ee_flags & EV_QUEUED) == NULL))
        !           933:     return(NULL);
        !           934:   if (p->p_evlist.tqh_first == NULL)
        !           935:     return(NULL);
        !           936:   if (eqp == NULL) {  // remove first
        !           937:     eqp = p->p_evlist.tqh_first;
        !           938:   }
        !           939:   TAILQ_REMOVE(&p->p_evlist, eqp, ee_plist);
        !           940:   eqp->ee_flags &= ~EV_QUEUED;
        !           941:   return(eqp);
        !           942: }
        !           943: 
        !           944: struct evwatch_args {
        !           945:   struct eventreq  *u_req;
        !           946:   int               u_eventmask;
        !           947: };
        !           948: 
        !           949: 
        !           950: /*
        !           951:  * watchevent system call. user passes us an event to watch
        !           952:  * for. we malloc an event object, initialize it, and queue
        !           953:  * it to the open socket. when the event occurs, postevent()
        !           954:  * will enque it back to our proc where we can retrieve it
        !           955:  * via waitevent().
        !           956:  *
        !           957:  * should this prevent duplicate events on same socket?
        !           958:  */
        !           959: int
        !           960: watchevent(p, uap, retval)
        !           961:      struct proc *p;
        !           962:      struct evwatch_args *uap;
        !           963:      register_t *retval;
        !           964: {
        !           965:   struct eventqelt *eqp = (struct eventqelt *)0;
        !           966:   struct eventqelt *np;
        !           967:   struct eventreq *erp;
        !           968:   struct file *fp;
        !           969:   struct socket *sp;
        !           970:   int error;
        !           971: 
        !           972:   // get a qelt and fill with users req
        !           973:   MALLOC(eqp, struct eventqelt *, sizeof(struct eventqelt), M_TEMP, M_WAITOK);
        !           974:   if (!eqp) panic("can't MALLOC eqp");
        !           975:   erp = &eqp->ee_req;
        !           976:   // get users request pkt
        !           977:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
        !           978:                     sizeof(struct eventreq))) {
        !           979:     FREE(eqp, M_TEMP);
        !           980:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
        !           981:     return(error);
        !           982:   }
        !           983:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_START, 0,
        !           984:               erp->er_handle,uap->u_eventmask,eqp,0);
        !           985:   // validate, freeing qelt if errors
        !           986:   error = 0;
        !           987:   if (erp->er_type != EV_FD) {
        !           988:     error = EINVAL;
        !           989:   } else  if (erp->er_handle < 0) {
        !           990:     error = EBADF;
        !           991:   } else  if (erp->er_handle > p->p_fd->fd_nfiles) {
        !           992:     error = EBADF;
        !           993:   } else if ((fp = *fdfile(p, erp->er_handle)) == NULL) {
        !           994:     error = EBADF;
        !           995:   } else if (fp->f_type != DTYPE_SOCKET) {
        !           996:     error = EINVAL;
        !           997:   }
        !           998:   if (error) {
        !           999:     FREE(eqp,M_TEMP);
        !          1000:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
        !          1001:     return(error);
        !          1002:   }
        !          1003: 
        !          1004:   erp->er_rcnt = erp->er_wcnt = erp->er_eventbits = 0;
        !          1005:   eqp->ee_proc = p;
        !          1006:   eqp->ee_eventmask = uap->u_eventmask & EV_MASK;
        !          1007:   eqp->ee_flags = 0;
        !          1008: 
        !          1009:   sp = (struct socket *)fp->f_data;
        !          1010:   assert(sp != NULL);
        !          1011: 
        !          1012:   // only allow one watch per file per proc
        !          1013:   for (np = sp->so_evlist.tqh_first; np != NULL; np = np->ee_slist.tqe_next) {
        !          1014:     if (np->ee_proc == p) {
        !          1015:       FREE(eqp,M_TEMP);
        !          1016:       KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
        !          1017:       return(EINVAL);
        !          1018:     }
        !          1019:   }
        !          1020: 
        !          1021:   TAILQ_INSERT_TAIL(&sp->so_evlist, eqp, ee_slist);
        !          1022:   postevent(sp, 0, EV_RWBYTES); // catch existing events
        !          1023:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
        !          1024:   return(0);
        !          1025: }
        !          1026: 
        !          1027: struct evwait_args {
        !          1028:   struct eventreq *u_req;
        !          1029:   struct timeval *tv;
        !          1030: };
        !          1031: 
        !          1032: /*
        !          1033:  * waitevent system call.
        !          1034:  * grabs the next waiting event for this proc and returns
        !          1035:  * it. if no events, user can request to sleep with timeout
        !          1036:  * or poll mode (tv=NULL);
        !          1037:  */
        !          1038: int
        !          1039: waitevent(p, uap, retval)
        !          1040:      struct proc *p;
        !          1041:      struct evwait_args *uap;
        !          1042:      register_t *retval;
        !          1043: {
        !          1044:   int error = 0;
        !          1045:   struct eventqelt *eqp;
        !          1046:   int timo;
        !          1047:   struct timeval atv;
        !          1048:   int s;
        !          1049: 
        !          1050:        if (uap->tv) {
        !          1051:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
        !          1052:                        sizeof (atv));
        !          1053:                if (error)
        !          1054:                        return(error);
        !          1055:                if (itimerfix(&atv)) {
        !          1056:                        error = EINVAL;
        !          1057:                        return(error);
        !          1058:                }
        !          1059:                s = splhigh();
        !          1060:                timeradd(&atv, &time, &atv);
        !          1061:                timo = hzto(&atv);
        !          1062:                splx(s);
        !          1063:        } else
        !          1064:                timo = 0;
        !          1065: 
        !          1066:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_START, 0,0,0,0,0);
        !          1067: 
        !          1068: retry:
        !          1069:   s = splhigh();
        !          1070:   if ((eqp = evprocdeque(p,NULL)) != NULL) {
        !          1071:     splx(s);
        !          1072:     error = copyout((caddr_t)&eqp->ee_req, (caddr_t)uap->u_req,
        !          1073:                    sizeof(struct eventreq));
        !          1074:     KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,
        !          1075:                 eqp->ee_req.er_handle,eqp->ee_req.er_eventbits,eqp,0);
        !          1076:     return(error);
        !          1077:   } else {
        !          1078:     if (uap->tv && (timo == 0)) {
        !          1079:         splx(s);
        !          1080:         *retval = 1;  // poll failed
        !          1081:        return(error);
        !          1082:     }
        !          1083: 
        !          1084:     KERNEL_DEBUG(DBG_MISC_WAIT, 1,0,0,0,0);
        !          1085:     error = tsleep(&p->p_evlist, PSOCK | PCATCH, "waitevent", timo);
        !          1086:     KERNEL_DEBUG(DBG_MISC_WAIT, 0,0,2,p->p_evlist.tqh_first,0);
        !          1087:     splx(s);
        !          1088:     if (error == 0)
        !          1089:       goto retry;
        !          1090:     if (error == ERESTART)
        !          1091:       error = EINTR;
        !          1092:     if (error == EWOULDBLOCK) {
        !          1093:       *retval = 1;
        !          1094:       error = 0;
        !          1095:     }
        !          1096:   }
        !          1097:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,0,0,0,0);
        !          1098:   return(error);
        !          1099: }
        !          1100: 
        !          1101: struct modwatch_args {
        !          1102:   struct eventreq *u_req;
        !          1103:   int               u_eventmask;
        !          1104: };
        !          1105: 
        !          1106: /*
        !          1107:  * modwatch system call. user passes in event to modify.
        !          1108:  * if we find it we reset the event bits and que/deque event
        !          1109:  * it needed.
        !          1110:  */
        !          1111: int
        !          1112: modwatch(p, uap, retval)
        !          1113:      struct proc *p;
        !          1114:      struct modwatch_args *uap;
        !          1115:      register_t *retval;
        !          1116: {
        !          1117:   struct eventreq er;
        !          1118:   struct eventreq *erp = &er;
        !          1119:   struct eventqelt *evq;
        !          1120:   int error;
        !          1121:   struct file *fp;
        !          1122:   struct socket *sp;
        !          1123:   int flag;
        !          1124: 
        !          1125: 
        !          1126:   // get users request pkt
        !          1127:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
        !          1128:                     sizeof(struct eventreq))) return(error);
        !          1129: 
        !          1130:   if (erp->er_type != EV_FD) return(EINVAL);
        !          1131:   if (erp->er_handle < 0) return(EBADF);
        !          1132:   if (erp->er_handle > p->p_fd->fd_nfiles) return(EBADF);
        !          1133:   if ((fp = *fdfile(p, erp->er_handle)) == NULL)
        !          1134:     return(EBADF);
        !          1135:   if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock
        !          1136:   sp = (struct socket *)fp->f_data;
        !          1137:   assert(sp != NULL);
        !          1138: 
        !          1139:   // locate event if possible
        !          1140:   for (evq = sp->so_evlist.tqh_first;
        !          1141:        evq != NULL; evq = evq->ee_slist.tqe_next) {
        !          1142:     if (evq->ee_proc == p) break;
        !          1143:   }
        !          1144:   if (evq == NULL) {
        !          1145:     return(EINVAL);
        !          1146:   }
        !          1147: 
        !          1148: 
        !          1149:     if (uap->u_eventmask == EV_RM) {
        !          1150:     evprocdeque(p, evq);
        !          1151:     TAILQ_REMOVE(&sp->so_evlist, evq, ee_slist);
        !          1152:     FREE(evq, M_TEMP);
        !          1153:     return(0);
        !          1154:     }
        !          1155: 
        !          1156:   switch (uap->u_eventmask & EV_MASK) {
        !          1157:  
        !          1158:   case 0:
        !          1159:     flag = 0;
        !          1160:     break;
        !          1161: 
        !          1162:   case EV_RE:
        !          1163:   case EV_WR:
        !          1164:   case EV_RE|EV_WR:
        !          1165:     flag = EV_RWBYTES;
        !          1166:     break;
        !          1167: 
        !          1168:   case EV_EX:
        !          1169:     flag = EV_OOB;
        !          1170:     break;
        !          1171: 
        !          1172:   case EV_EX|EV_RE:
        !          1173:   case EV_EX|EV_WR:
        !          1174:   case EV_EX|EV_RE|EV_WR:
        !          1175:     flag = EV_OOB|EV_RWBYTES;
        !          1176:     break;
        !          1177: 
        !          1178:   default:
        !          1179:     return(EINVAL);
        !          1180:   }
        !          1181: 
        !          1182:    evq->ee_eventmask = uap->u_eventmask & EV_MASK;
        !          1183:    evprocdeque(p, evq);
        !          1184:    evq->ee_req.er_eventbits = 0;
        !          1185:    postevent(sp, 0, flag);
        !          1186:    return(0);
        !          1187: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.