Annotation of Net2/kern/sys_generic.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.3 ! root       33:  *     from: @(#)sys_generic.c 7.30 (Berkeley) 5/30/91
        !            34:  *     sys_generic.c,v 1.8 1993/07/15 22:26:11 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "systm.h"
                     39: #include "filedesc.h"
                     40: #include "ioctl.h"
                     41: #include "file.h"
1.1.1.3 ! root       42: #include "select.h"
1.1       root       43: #include "socketvar.h"
                     44: #include "proc.h"
                     45: #include "uio.h"
                     46: #include "kernel.h"
                     47: #include "stat.h"
                     48: #include "malloc.h"
                     49: #ifdef KTRACE
                     50: #include "ktrace.h"
                     51: #endif
                     52: 
1.1.1.3 ! root       53: struct read_args {
        !            54:        int     fdes;
        !            55:        char    *cbuf;
        !            56:        unsigned count;
        !            57: };
        !            58: 
1.1       root       59: /*
                     60:  * Read system call.
                     61:  */
                     62: /* ARGSUSED */
                     63: read(p, uap, retval)
                     64:        struct proc *p;
1.1.1.3 ! root       65:        register struct read_args *uap;
1.1       root       66:        int *retval;
                     67: {
                     68:        register struct file *fp;
                     69:        register struct filedesc *fdp = p->p_fd;
                     70:        struct uio auio;
                     71:        struct iovec aiov;
                     72:        long cnt, error = 0;
                     73: #ifdef KTRACE
                     74:        struct iovec ktriov;
                     75: #endif
                     76: 
                     77:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                     78:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                     79:            (fp->f_flag & FREAD) == 0)
                     80:                return (EBADF);
                     81:        aiov.iov_base = (caddr_t)uap->cbuf;
                     82:        aiov.iov_len = uap->count;
                     83:        auio.uio_iov = &aiov;
                     84:        auio.uio_iovcnt = 1;
                     85:        auio.uio_resid = uap->count;
                     86:        auio.uio_rw = UIO_READ;
                     87:        auio.uio_segflg = UIO_USERSPACE;
                     88:        auio.uio_procp = p;
                     89: #ifdef KTRACE
                     90:        /*
                     91:         * if tracing, save a copy of iovec
                     92:         */
                     93:        if (KTRPOINT(p, KTR_GENIO))
                     94:                ktriov = aiov;
                     95: #endif
                     96:        cnt = uap->count;
                     97:        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                     98:                if (auio.uio_resid != cnt && (error == ERESTART ||
                     99:                    error == EINTR || error == EWOULDBLOCK))
                    100:                        error = 0;
                    101:        cnt -= auio.uio_resid;
                    102: #ifdef KTRACE
                    103:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
                    104:                ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
                    105: #endif
                    106:        *retval = cnt;
                    107:        return (error);
                    108: }
                    109: 
                    110: /*
                    111:  * Scatter read system call.
                    112:  */
1.1.1.3 ! root      113: 
        !           114: struct readv_args {
        !           115:        int     fdes;
        !           116:        struct  iovec *iovp;
        !           117:        unsigned iovcnt;
        !           118: };
        !           119: 
1.1       root      120: /* ARGSUSED */
                    121: readv(p, uap, retval)
                    122:        struct proc *p;
1.1.1.3 ! root      123:        register struct readv_args *uap;
1.1       root      124:        int *retval;
                    125: {
                    126:        register struct file *fp;
                    127:        register struct filedesc *fdp = p->p_fd;
                    128:        struct uio auio;
                    129:        register struct iovec *iov;
                    130:        struct iovec *saveiov;
                    131:        struct iovec aiov[UIO_SMALLIOV];
                    132:        long i, cnt, error = 0;
                    133:        unsigned iovlen;
                    134: #ifdef KTRACE
                    135:        struct iovec *ktriov = NULL;
                    136: #endif
                    137: 
                    138:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    139:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    140:            (fp->f_flag & FREAD) == 0)
                    141:                return (EBADF);
                    142:        /* note: can't use iovlen until iovcnt is validated */
                    143:        iovlen = uap->iovcnt * sizeof (struct iovec);
                    144:        if (uap->iovcnt > UIO_SMALLIOV) {
                    145:                if (uap->iovcnt > UIO_MAXIOV)
                    146:                        return (EINVAL);
                    147:                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                    148:                saveiov = iov;
                    149:        } else
                    150:                iov = aiov;
                    151:        auio.uio_iov = iov;
                    152:        auio.uio_iovcnt = uap->iovcnt;
                    153:        auio.uio_rw = UIO_READ;
                    154:        auio.uio_segflg = UIO_USERSPACE;
                    155:        auio.uio_procp = p;
                    156:        if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                    157:                goto done;
                    158:        auio.uio_resid = 0;
                    159:        for (i = 0; i < uap->iovcnt; i++) {
                    160:                if (iov->iov_len < 0) {
                    161:                        error = EINVAL;
                    162:                        goto done;
                    163:                }
                    164:                auio.uio_resid += iov->iov_len;
                    165:                if (auio.uio_resid < 0) {
                    166:                        error = EINVAL;
                    167:                        goto done;
                    168:                }
                    169:                iov++;
                    170:        }
                    171: #ifdef KTRACE
                    172:        /*
                    173:         * if tracing, save a copy of iovec
                    174:         */
                    175:        if (KTRPOINT(p, KTR_GENIO))  {
                    176:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    177:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    178:        }
                    179: #endif
                    180:        cnt = auio.uio_resid;
                    181:        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                    182:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    183:                    error == EINTR || error == EWOULDBLOCK))
                    184:                        error = 0;
                    185:        cnt -= auio.uio_resid;
                    186: #ifdef KTRACE
                    187:        if (ktriov != NULL) {
                    188:                if (error == 0)
                    189:                        ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
                    190:                            cnt, error);
                    191:                FREE(ktriov, M_TEMP);
                    192:        }
                    193: #endif
                    194:        *retval = cnt;
                    195: done:
                    196:        if (uap->iovcnt > UIO_SMALLIOV)
                    197:                FREE(saveiov, M_IOV);
                    198:        return (error);
                    199: }
                    200: 
                    201: /*
                    202:  * Write system call
                    203:  */
1.1.1.3 ! root      204: 
        !           205: struct write_args {
        !           206:        int     fdes;
        !           207:        char    *cbuf;
        !           208:        unsigned count;
        !           209: };
        !           210: 
1.1       root      211: write(p, uap, retval)
                    212:        struct proc *p;
1.1.1.3 ! root      213:        register struct write_args *uap;
1.1       root      214:        int *retval;
                    215: {
                    216:        register struct file *fp;
                    217:        register struct filedesc *fdp = p->p_fd;
                    218:        struct uio auio;
                    219:        struct iovec aiov;
                    220:        long cnt, error = 0;
                    221: #ifdef KTRACE
                    222:        struct iovec ktriov;
                    223: #endif
                    224: 
                    225:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    226:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    227:            (fp->f_flag & FWRITE) == 0)
                    228:                return (EBADF);
                    229:        aiov.iov_base = (caddr_t)uap->cbuf;
                    230:        aiov.iov_len = uap->count;
                    231:        auio.uio_iov = &aiov;
                    232:        auio.uio_iovcnt = 1;
                    233:        auio.uio_resid = uap->count;
                    234:        auio.uio_rw = UIO_WRITE;
                    235:        auio.uio_segflg = UIO_USERSPACE;
                    236:        auio.uio_procp = p;
                    237: #ifdef KTRACE
                    238:        /*
                    239:         * if tracing, save a copy of iovec
                    240:         */
                    241:        if (KTRPOINT(p, KTR_GENIO))
                    242:                ktriov = aiov;
                    243: #endif
                    244:        cnt = uap->count;
                    245:        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                    246:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    247:                    error == EINTR || error == EWOULDBLOCK))
                    248:                        error = 0;
                    249:                if (error == EPIPE)
                    250:                        psignal(p, SIGPIPE);
                    251:        }
                    252:        cnt -= auio.uio_resid;
                    253: #ifdef KTRACE
                    254:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
                    255:                ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
                    256:                    &ktriov, cnt, error);
                    257: #endif
                    258:        *retval = cnt;
                    259:        return (error);
                    260: }
                    261: 
                    262: /*
                    263:  * Gather write system call
                    264:  */
1.1.1.3 ! root      265: 
        !           266: struct writev_args {
        !           267:        int     fdes;
        !           268:        struct  iovec *iovp;
        !           269:        unsigned iovcnt;
        !           270: };
        !           271: 
1.1       root      272: writev(p, uap, retval)
                    273:        struct proc *p;
1.1.1.3 ! root      274:        register struct writev_args *uap;
1.1       root      275:        int *retval;
                    276: {
                    277:        register struct file *fp;
                    278:        register struct filedesc *fdp = p->p_fd;
                    279:        struct uio auio;
                    280:        register struct iovec *iov;
                    281:        struct iovec *saveiov;
                    282:        struct iovec aiov[UIO_SMALLIOV];
                    283:        long i, cnt, error = 0;
                    284:        unsigned iovlen;
                    285: #ifdef KTRACE
                    286:        struct iovec *ktriov = NULL;
                    287: #endif
                    288: 
                    289:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    290:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    291:            (fp->f_flag & FWRITE) == 0)
                    292:                return (EBADF);
                    293:        /* note: can't use iovlen until iovcnt is validated */
                    294:        iovlen = uap->iovcnt * sizeof (struct iovec);
                    295:        if (uap->iovcnt > UIO_SMALLIOV) {
                    296:                if (uap->iovcnt > UIO_MAXIOV)
                    297:                        return (EINVAL);
                    298:                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                    299:                saveiov = iov;
                    300:        } else
                    301:                iov = aiov;
                    302:        auio.uio_iov = iov;
                    303:        auio.uio_iovcnt = uap->iovcnt;
                    304:        auio.uio_rw = UIO_WRITE;
                    305:        auio.uio_segflg = UIO_USERSPACE;
                    306:        auio.uio_procp = p;
                    307:        if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                    308:                goto done;
                    309:        auio.uio_resid = 0;
                    310:        for (i = 0; i < uap->iovcnt; i++) {
                    311:                if (iov->iov_len < 0) {
                    312:                        error = EINVAL;
                    313:                        goto done;
                    314:                }
                    315:                auio.uio_resid += iov->iov_len;
                    316:                if (auio.uio_resid < 0) {
                    317:                        error = EINVAL;
                    318:                        goto done;
                    319:                }
                    320:                iov++;
                    321:        }
                    322: #ifdef KTRACE
                    323:        /*
                    324:         * if tracing, save a copy of iovec
                    325:         */
                    326:        if (KTRPOINT(p, KTR_GENIO))  {
                    327:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    328:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    329:        }
                    330: #endif
                    331:        cnt = auio.uio_resid;
                    332:        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                    333:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    334:                    error == EINTR || error == EWOULDBLOCK))
                    335:                        error = 0;
                    336:                if (error == EPIPE)
                    337:                        psignal(p, SIGPIPE);
                    338:        }
                    339:        cnt -= auio.uio_resid;
                    340: #ifdef KTRACE
                    341:        if (ktriov != NULL) {
                    342:                if (error == 0)
                    343:                        ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
                    344:                                ktriov, cnt, error);
                    345:                FREE(ktriov, M_TEMP);
                    346:        }
                    347: #endif
                    348:        *retval = cnt;
                    349: done:
                    350:        if (uap->iovcnt > UIO_SMALLIOV)
                    351:                FREE(saveiov, M_IOV);
                    352:        return (error);
                    353: }
                    354: 
                    355: /*
                    356:  * Ioctl system call
                    357:  */
1.1.1.3 ! root      358: 
        !           359: struct ioctl_args {
        !           360:        int     fdes;
        !           361:        int     cmd;
        !           362:        caddr_t cmarg;
        !           363: };
        !           364: 
1.1       root      365: /* ARGSUSED */
                    366: ioctl(p, uap, retval)
                    367:        struct proc *p;
1.1.1.3 ! root      368:        register struct ioctl_args *uap;
1.1       root      369:        int *retval;
                    370: {
                    371:        register struct file *fp;
                    372:        register struct filedesc *fdp = p->p_fd;
                    373:        register int com, error;
                    374:        register u_int size;
                    375:        caddr_t memp = 0;
                    376: #define STK_PARAMS     128
                    377:        char stkbuf[STK_PARAMS];
                    378:        caddr_t data = stkbuf;
                    379:        int tmp;
                    380: 
                    381:        if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
                    382:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
                    383:                return (EBADF);
                    384:        if ((fp->f_flag & (FREAD|FWRITE)) == 0)
                    385:                return (EBADF);
                    386:        com = uap->cmd;
                    387: 
                    388:        if (com == FIOCLEX) {
                    389:                fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
                    390:                return (0);
                    391:        }
                    392:        if (com == FIONCLEX) {
                    393:                fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
                    394:                return (0);
                    395:        }
                    396: 
                    397:        /*
                    398:         * Interpret high order word to find
                    399:         * amount of data to be copied to/from the
                    400:         * user's address space.
                    401:         */
                    402:        size = IOCPARM_LEN(com);
                    403:        if (size > IOCPARM_MAX)
                    404:                return (ENOTTY);
                    405:        if (size > sizeof (stkbuf)) {
                    406:                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
                    407:                data = memp;
                    408:        }
                    409:        if (com&IOC_IN) {
                    410:                if (size) {
                    411:                        error = copyin(uap->cmarg, data, (u_int)size);
                    412:                        if (error) {
                    413:                                if (memp)
                    414:                                        free(memp, M_IOCTLOPS);
                    415:                                return (error);
                    416:                        }
                    417:                } else
                    418:                        *(caddr_t *)data = uap->cmarg;
                    419:        } else if ((com&IOC_OUT) && size)
                    420:                /*
                    421:                 * Zero the buffer so the user always
                    422:                 * gets back something deterministic.
                    423:                 */
                    424:                bzero(data, size);
                    425:        else if (com&IOC_VOID)
                    426:                *(caddr_t *)data = uap->cmarg;
                    427: 
                    428:        switch (com) {
                    429: 
                    430:        case FIONBIO:
                    431:                if (tmp = *(int *)data)
                    432:                        fp->f_flag |= FNONBLOCK;
                    433:                else
                    434:                        fp->f_flag &= ~FNONBLOCK;
                    435:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    436:                break;
                    437: 
                    438:        case FIOASYNC:
                    439:                if (tmp = *(int *)data)
                    440:                        fp->f_flag |= FASYNC;
                    441:                else
                    442:                        fp->f_flag &= ~FASYNC;
                    443:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                    444:                break;
                    445: 
                    446:        case FIOSETOWN:
                    447:                tmp = *(int *)data;
                    448:                if (fp->f_type == DTYPE_SOCKET) {
                    449:                        ((struct socket *)fp->f_data)->so_pgid = tmp;
                    450:                        error = 0;
                    451:                        break;
                    452:                }
                    453:                if (tmp <= 0) {
                    454:                        tmp = -tmp;
                    455:                } else {
                    456:                        struct proc *p1 = pfind(tmp);
                    457:                        if (p1 == 0) {
                    458:                                error = ESRCH;
                    459:                                break;
                    460:                        }
                    461:                        tmp = p1->p_pgrp->pg_id;
                    462:                }
                    463:                error = (*fp->f_ops->fo_ioctl)
                    464:                        (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
                    465:                break;
                    466: 
                    467:        case FIOGETOWN:
                    468:                if (fp->f_type == DTYPE_SOCKET) {
                    469:                        error = 0;
                    470:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                    471:                        break;
                    472:                }
                    473:                error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
                    474:                *(int *)data = -*(int *)data;
                    475:                break;
                    476: 
                    477:        default:
                    478:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
                    479:                /*
                    480:                 * Copy any data to user, size was
                    481:                 * already set and checked above.
                    482:                 */
                    483:                if (error == 0 && (com&IOC_OUT) && size)
                    484:                        error = copyout(data, uap->cmarg, (u_int)size);
                    485:                break;
                    486:        }
                    487:        if (memp)
                    488:                free(memp, M_IOCTLOPS);
                    489:        return (error);
                    490: }
                    491: 
                    492: int    selwait, nselcoll;
                    493: 
                    494: /*
                    495:  * Select system call.
                    496:  */
1.1.1.3 ! root      497: 
        !           498: struct select_args {
        !           499:        u_int   nd;
        !           500:        fd_set  *in, *ou, *ex;
        !           501:        struct  timeval *tv;
        !           502: };
        !           503: 
1.1       root      504: select(p, uap, retval)
                    505:        register struct proc *p;
1.1.1.3 ! root      506:        register struct select_args *uap;
1.1       root      507:        int *retval;
                    508: {
                    509:        fd_set ibits[3], obits[3];
                    510:        struct timeval atv;
1.1.1.3 ! root      511:        int s, ncoll, error = 0, timo;
        !           512:        u_int ni;
1.1       root      513: 
                    514:        bzero((caddr_t)ibits, sizeof(ibits));
                    515:        bzero((caddr_t)obits, sizeof(obits));
                    516:        if (uap->nd > p->p_fd->fd_nfiles)
                    517:                uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
                    518:        ni = howmany(uap->nd, NFDBITS);
                    519: 
                    520: #define        getbits(name, x) \
                    521:        if (uap->name) { \
                    522:                error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
                    523:                    (unsigned)(ni * sizeof(fd_mask))); \
                    524:                if (error) \
                    525:                        goto done; \
                    526:        }
                    527:        getbits(in, 0);
                    528:        getbits(ou, 1);
                    529:        getbits(ex, 2);
                    530: #undef getbits
                    531: 
                    532:        if (uap->tv) {
                    533:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    534:                        sizeof (atv));
                    535:                if (error)
                    536:                        goto done;
                    537:                if (itimerfix(&atv)) {
                    538:                        error = EINVAL;
                    539:                        goto done;
                    540:                }
1.1.1.3 ! root      541:                s = splclock();
        !           542:                timevaladd(&atv, &time);
        !           543:                splx(s);
1.1       root      544:                timo = hzto(&atv);
1.1.1.3 ! root      545:                /*
        !           546:                 * avoid sleeping forever if user doesn't want that...
        !           547:                 */
        !           548:                if (timo == 0)
        !           549:                        timo = 1;
1.1       root      550:        } else
                    551:                timo = 0;
                    552: retry:
                    553:        ncoll = nselcoll;
                    554:        p->p_flag |= SSEL;
                    555:        error = selscan(p, ibits, obits, uap->nd, retval);
                    556:        if (error || *retval)
                    557:                goto done;
                    558:        s = splhigh();
                    559:        /* this should be timercmp(&time, &atv, >=) */
                    560:        if (uap->tv && (time.tv_sec > atv.tv_sec ||
                    561:            time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
                    562:                splx(s);
                    563:                goto done;
                    564:        }
                    565:        if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
                    566:                splx(s);
                    567:                goto retry;
                    568:        }
                    569:        p->p_flag &= ~SSEL;
                    570:        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
                    571:        splx(s);
                    572:        if (error == 0)
                    573:                goto retry;
                    574: done:
                    575:        p->p_flag &= ~SSEL;
                    576:        /* select is not restarted after signals... */
                    577:        if (error == ERESTART)
                    578:                error = EINTR;
                    579:        if (error == EWOULDBLOCK)
                    580:                error = 0;
                    581: #define        putbits(name, x) \
                    582:        if (uap->name) { \
                    583:                int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
                    584:                    (unsigned)(ni * sizeof(fd_mask))); \
                    585:                if (error2) \
                    586:                        error = error2; \
                    587:        }
                    588:        if (error == 0) {
                    589:                putbits(in, 0);
                    590:                putbits(ou, 1);
                    591:                putbits(ex, 2);
                    592: #undef putbits
                    593:        }
                    594:        return (error);
                    595: }
                    596: 
1.1.1.2   root      597: int
1.1.1.3 ! root      598: selscan(p, ibits, obits, nfd, retval)
        !           599:        struct proc *p;
        !           600:        fd_set *ibits;
        !           601:        fd_set *obits;
        !           602:        int nfd;
        !           603:        int *retval;
1.1       root      604: {
                    605:        register struct filedesc *fdp = p->p_fd;
                    606:        register int which, i, j;
                    607:        register fd_mask bits;
                    608:        int flag;
                    609:        struct file *fp;
                    610:        int error = 0, n = 0;
                    611: 
                    612:        for (which = 0; which < 3; which++) {
                    613:                switch (which) {
                    614: 
                    615:                case 0:
                    616:                        flag = FREAD; break;
                    617: 
                    618:                case 1:
                    619:                        flag = FWRITE; break;
                    620: 
                    621:                case 2:
                    622:                        flag = 0; break;
                    623:                }
                    624:                for (i = 0; i < nfd; i += NFDBITS) {
                    625:                        bits = ibits[which].fds_bits[i/NFDBITS];
                    626:                        while ((j = ffs(bits)) && i + --j < nfd) {
                    627:                                bits &= ~(1 << j);
                    628:                                fp = fdp->fd_ofiles[i + j];
                    629:                                if (fp == NULL) {
                    630:                                        error = EBADF;
                    631:                                        break;
                    632:                                }
                    633:                                if ((*fp->f_ops->fo_select)(fp, flag, p)) {
                    634:                                        FD_SET(i + j, &obits[which]);
                    635:                                        n++;
                    636:                                }
                    637:                        }
                    638:                }
                    639:        }
                    640:        *retval = n;
                    641:        return (error);
                    642: }
                    643: 
                    644: /*ARGSUSED*/
1.1.1.2   root      645: int
1.1.1.3 ! root      646: seltrue(dev, which, p)
        !           647:        dev_t dev;
        !           648:        int which;
        !           649:        struct proc *p;
1.1       root      650: {
                    651: 
                    652:        return (1);
                    653: }
                    654: 
1.1.1.2   root      655: void
1.1.1.3 ! root      656: selrecord(p, si)
        !           657:        struct proc *p;
        !           658:        struct selinfo *si;
        !           659: {
        !           660:        struct proc *oldproc;
        !           661: 
        !           662:        /* if we're already sleeping on it, return */
        !           663:        if (si->si_pid == p->p_pid)
        !           664:            return;
        !           665: 
        !           666:        /* if somebody else is already selecting on it,
        !           667:         * collsion time...
        !           668:         */
        !           669:        if (si->si_pid && (oldproc = pfind(si->si_pid)) &&
        !           670:                oldproc->p_wchan == (caddr_t) &selwait) {
        !           671:            /* it's a bona fide collision */
        !           672:            si->si_coll = 1;
        !           673:        } else {
        !           674:            si->si_pid = p->p_pid;
        !           675:        }
        !           676: }
        !           677: 
        !           678: void
        !           679: selwakeup(si)
        !           680:        struct selinfo *si;
1.1       root      681: {
1.1.1.2   root      682:        register struct proc *p;
1.1       root      683: 
1.1.1.3 ! root      684:        if (!si->si_pid)
        !           685:                return;
        !           686:        if (si->si_coll) {
        !           687:                si->si_coll = 0;
1.1       root      688:                nselcoll++;
                    689:                wakeup((caddr_t)&selwait);
                    690:        }
1.1.1.3 ! root      691:        p = pfind(si->si_pid);
        !           692:        si->si_pid = 0;
        !           693:        if (p != NULL) {
1.1       root      694:                int s = splhigh();
                    695:                if (p->p_wchan == (caddr_t)&selwait) {
                    696:                        if (p->p_stat == SSLEEP)
                    697:                                setrun(p);
                    698:                        else
                    699:                                unsleep(p);
                    700:                } else if (p->p_flag & SSEL)
                    701:                        p->p_flag &= ~SSEL;
                    702:                splx(s);
                    703:        }
                    704: }

unix.superglobalmegacorp.com

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