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

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:  *
                     33:  *     @(#)sys_generic.c       7.30 (Berkeley) 5/30/91
                     34:  */
                     35: 
                     36: #include "param.h"
                     37: #include "systm.h"
                     38: #include "filedesc.h"
                     39: #include "ioctl.h"
                     40: #include "file.h"
                     41: #include "socketvar.h"
                     42: #include "proc.h"
                     43: #include "uio.h"
                     44: #include "kernel.h"
                     45: #include "stat.h"
                     46: #include "malloc.h"
                     47: #ifdef KTRACE
                     48: #include "ktrace.h"
                     49: #endif
                     50: 
                     51: /*
                     52:  * Read system call.
                     53:  */
                     54: /* ARGSUSED */
                     55: read(p, uap, retval)
                     56:        struct proc *p;
                     57:        register struct args {
                     58:                int     fdes;
                     59:                char    *cbuf;
                     60:                unsigned count;
                     61:        } *uap;
                     62:        int *retval;
                     63: {
                     64:        register struct file *fp;
                     65:        register struct filedesc *fdp = p->p_fd;
                     66:        struct uio auio;
                     67:        struct iovec aiov;
                     68:        long cnt, error = 0;
                     69: #ifdef KTRACE
                     70:        struct iovec ktriov;
                     71: #endif
                     72: 
                     73:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                     74:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                     75:            (fp->f_flag & FREAD) == 0)
                     76:                return (EBADF);
                     77:        aiov.iov_base = (caddr_t)uap->cbuf;
                     78:        aiov.iov_len = uap->count;
                     79:        auio.uio_iov = &aiov;
                     80:        auio.uio_iovcnt = 1;
                     81:        auio.uio_resid = uap->count;
                     82:        auio.uio_rw = UIO_READ;
                     83:        auio.uio_segflg = UIO_USERSPACE;
                     84:        auio.uio_procp = p;
                     85: #ifdef KTRACE
                     86:        /*
                     87:         * if tracing, save a copy of iovec
                     88:         */
                     89:        if (KTRPOINT(p, KTR_GENIO))
                     90:                ktriov = aiov;
                     91: #endif
                     92:        cnt = uap->count;
                     93:        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                     94:                if (auio.uio_resid != cnt && (error == ERESTART ||
                     95:                    error == EINTR || error == EWOULDBLOCK))
                     96:                        error = 0;
                     97:        cnt -= auio.uio_resid;
                     98: #ifdef KTRACE
                     99:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
                    100:                ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
                    101: #endif
                    102:        *retval = cnt;
                    103:        return (error);
                    104: }
                    105: 
                    106: /*
                    107:  * Scatter read system call.
                    108:  */
                    109: /* ARGSUSED */
                    110: readv(p, uap, retval)
                    111:        struct proc *p;
                    112:        register struct args {
                    113:                int     fdes;
                    114:                struct  iovec *iovp;
                    115:                unsigned iovcnt;
                    116:        } *uap;
                    117:        int *retval;
                    118: {
                    119:        register struct file *fp;
                    120:        register struct filedesc *fdp = p->p_fd;
                    121:        struct uio auio;
                    122:        register struct iovec *iov;
                    123:        struct iovec *saveiov;
                    124:        struct iovec aiov[UIO_SMALLIOV];
                    125:        long i, cnt, error = 0;
                    126:        unsigned iovlen;
                    127: #ifdef KTRACE
                    128:        struct iovec *ktriov = NULL;
                    129: #endif
                    130: 
                    131:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    132:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    133:            (fp->f_flag & FREAD) == 0)
                    134:                return (EBADF);
                    135:        /* note: can't use iovlen until iovcnt is validated */
                    136:        iovlen = uap->iovcnt * sizeof (struct iovec);
                    137:        if (uap->iovcnt > UIO_SMALLIOV) {
                    138:                if (uap->iovcnt > UIO_MAXIOV)
                    139:                        return (EINVAL);
                    140:                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                    141:                saveiov = iov;
                    142:        } else
                    143:                iov = aiov;
                    144:        auio.uio_iov = iov;
                    145:        auio.uio_iovcnt = uap->iovcnt;
                    146:        auio.uio_rw = UIO_READ;
                    147:        auio.uio_segflg = UIO_USERSPACE;
                    148:        auio.uio_procp = p;
                    149:        if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                    150:                goto done;
                    151:        auio.uio_resid = 0;
                    152:        for (i = 0; i < uap->iovcnt; i++) {
                    153:                if (iov->iov_len < 0) {
                    154:                        error = EINVAL;
                    155:                        goto done;
                    156:                }
                    157:                auio.uio_resid += iov->iov_len;
                    158:                if (auio.uio_resid < 0) {
                    159:                        error = EINVAL;
                    160:                        goto done;
                    161:                }
                    162:                iov++;
                    163:        }
                    164: #ifdef KTRACE
                    165:        /*
                    166:         * if tracing, save a copy of iovec
                    167:         */
                    168:        if (KTRPOINT(p, KTR_GENIO))  {
                    169:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    170:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    171:        }
                    172: #endif
                    173:        cnt = auio.uio_resid;
                    174:        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                    175:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    176:                    error == EINTR || error == EWOULDBLOCK))
                    177:                        error = 0;
                    178:        cnt -= auio.uio_resid;
                    179: #ifdef KTRACE
                    180:        if (ktriov != NULL) {
                    181:                if (error == 0)
                    182:                        ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
                    183:                            cnt, error);
                    184:                FREE(ktriov, M_TEMP);
                    185:        }
                    186: #endif
                    187:        *retval = cnt;
                    188: done:
                    189:        if (uap->iovcnt > UIO_SMALLIOV)
                    190:                FREE(saveiov, M_IOV);
                    191:        return (error);
                    192: }
                    193: 
                    194: /*
                    195:  * Write system call
                    196:  */
                    197: write(p, uap, retval)
                    198:        struct proc *p;
                    199:        register struct args {
                    200:                int     fdes;
                    201:                char    *cbuf;
                    202:                unsigned count;
                    203:        } *uap;
                    204:        int *retval;
                    205: {
                    206:        register struct file *fp;
                    207:        register struct filedesc *fdp = p->p_fd;
                    208:        struct uio auio;
                    209:        struct iovec aiov;
                    210:        long cnt, error = 0;
                    211: #ifdef KTRACE
                    212:        struct iovec ktriov;
                    213: #endif
                    214: 
                    215:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    216:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    217:            (fp->f_flag & FWRITE) == 0)
                    218:                return (EBADF);
                    219:        aiov.iov_base = (caddr_t)uap->cbuf;
                    220:        aiov.iov_len = uap->count;
                    221:        auio.uio_iov = &aiov;
                    222:        auio.uio_iovcnt = 1;
                    223:        auio.uio_resid = uap->count;
                    224:        auio.uio_rw = UIO_WRITE;
                    225:        auio.uio_segflg = UIO_USERSPACE;
                    226:        auio.uio_procp = p;
                    227: #ifdef KTRACE
                    228:        /*
                    229:         * if tracing, save a copy of iovec
                    230:         */
                    231:        if (KTRPOINT(p, KTR_GENIO))
                    232:                ktriov = aiov;
                    233: #endif
                    234:        cnt = uap->count;
                    235:        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                    236:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    237:                    error == EINTR || error == EWOULDBLOCK))
                    238:                        error = 0;
                    239:                if (error == EPIPE)
                    240:                        psignal(p, SIGPIPE);
                    241:        }
                    242:        cnt -= auio.uio_resid;
                    243: #ifdef KTRACE
                    244:        if (KTRPOINT(p, KTR_GENIO) && error == 0)
                    245:                ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
                    246:                    &ktriov, cnt, error);
                    247: #endif
                    248:        *retval = cnt;
                    249:        return (error);
                    250: }
                    251: 
                    252: /*
                    253:  * Gather write system call
                    254:  */
                    255: writev(p, uap, retval)
                    256:        struct proc *p;
                    257:        register struct args {
                    258:                int     fdes;
                    259:                struct  iovec *iovp;
                    260:                unsigned iovcnt;
                    261:        } *uap;
                    262:        int *retval;
                    263: {
                    264:        register struct file *fp;
                    265:        register struct filedesc *fdp = p->p_fd;
                    266:        struct uio auio;
                    267:        register struct iovec *iov;
                    268:        struct iovec *saveiov;
                    269:        struct iovec aiov[UIO_SMALLIOV];
                    270:        long i, cnt, error = 0;
                    271:        unsigned iovlen;
                    272: #ifdef KTRACE
                    273:        struct iovec *ktriov = NULL;
                    274: #endif
                    275: 
                    276:        if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
                    277:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
                    278:            (fp->f_flag & FWRITE) == 0)
                    279:                return (EBADF);
                    280:        /* note: can't use iovlen until iovcnt is validated */
                    281:        iovlen = uap->iovcnt * sizeof (struct iovec);
                    282:        if (uap->iovcnt > UIO_SMALLIOV) {
                    283:                if (uap->iovcnt > UIO_MAXIOV)
                    284:                        return (EINVAL);
                    285:                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                    286:                saveiov = iov;
                    287:        } else
                    288:                iov = aiov;
                    289:        auio.uio_iov = iov;
                    290:        auio.uio_iovcnt = uap->iovcnt;
                    291:        auio.uio_rw = UIO_WRITE;
                    292:        auio.uio_segflg = UIO_USERSPACE;
                    293:        auio.uio_procp = p;
                    294:        if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                    295:                goto done;
                    296:        auio.uio_resid = 0;
                    297:        for (i = 0; i < uap->iovcnt; i++) {
                    298:                if (iov->iov_len < 0) {
                    299:                        error = EINVAL;
                    300:                        goto done;
                    301:                }
                    302:                auio.uio_resid += iov->iov_len;
                    303:                if (auio.uio_resid < 0) {
                    304:                        error = EINVAL;
                    305:                        goto done;
                    306:                }
                    307:                iov++;
                    308:        }
                    309: #ifdef KTRACE
                    310:        /*
                    311:         * if tracing, save a copy of iovec
                    312:         */
                    313:        if (KTRPOINT(p, KTR_GENIO))  {
                    314:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    315:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    316:        }
                    317: #endif
                    318:        cnt = auio.uio_resid;
                    319:        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                    320:                if (auio.uio_resid != cnt && (error == ERESTART ||
                    321:                    error == EINTR || error == EWOULDBLOCK))
                    322:                        error = 0;
                    323:                if (error == EPIPE)
                    324:                        psignal(p, SIGPIPE);
                    325:        }
                    326:        cnt -= auio.uio_resid;
                    327: #ifdef KTRACE
                    328:        if (ktriov != NULL) {
                    329:                if (error == 0)
                    330:                        ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
                    331:                                ktriov, cnt, error);
                    332:                FREE(ktriov, M_TEMP);
                    333:        }
                    334: #endif
                    335:        *retval = cnt;
                    336: done:
                    337:        if (uap->iovcnt > UIO_SMALLIOV)
                    338:                FREE(saveiov, M_IOV);
                    339:        return (error);
                    340: }
                    341: 
                    342: /*
                    343:  * Ioctl system call
                    344:  */
                    345: /* ARGSUSED */
                    346: ioctl(p, uap, retval)
                    347:        struct proc *p;
                    348:        register struct args {
                    349:                int     fdes;
                    350:                int     cmd;
                    351:                caddr_t cmarg;
                    352:        } *uap;
                    353:        int *retval;
                    354: {
                    355:        register struct file *fp;
                    356:        register struct filedesc *fdp = p->p_fd;
                    357:        register int com, error;
                    358:        register u_int size;
                    359:        caddr_t memp = 0;
                    360: #define STK_PARAMS     128
                    361:        char stkbuf[STK_PARAMS];
                    362:        caddr_t data = stkbuf;
                    363:        int tmp;
                    364: 
                    365:        if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
                    366:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
                    367:                return (EBADF);
                    368:        if ((fp->f_flag & (FREAD|FWRITE)) == 0)
                    369:                return (EBADF);
                    370:        com = uap->cmd;
                    371: 
                    372:        if (com == FIOCLEX) {
                    373:                fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
                    374:                return (0);
                    375:        }
                    376:        if (com == FIONCLEX) {
                    377:                fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
                    378:                return (0);
                    379:        }
                    380: 
                    381:        /*
                    382:         * Interpret high order word to find
                    383:         * amount of data to be copied to/from the
                    384:         * user's address space.
                    385:         */
                    386:        size = IOCPARM_LEN(com);
                    387:        if (size > IOCPARM_MAX)
                    388:                return (ENOTTY);
                    389:        if (size > sizeof (stkbuf)) {
                    390:                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
                    391:                data = memp;
                    392:        }
                    393:        if (com&IOC_IN) {
                    394:                if (size) {
                    395:                        error = copyin(uap->cmarg, data, (u_int)size);
                    396:                        if (error) {
                    397:                                if (memp)
                    398:                                        free(memp, M_IOCTLOPS);
                    399:                                return (error);
                    400:                        }
                    401:                } else
                    402:                        *(caddr_t *)data = uap->cmarg;
                    403:        } else if ((com&IOC_OUT) && size)
                    404:                /*
                    405:                 * Zero the buffer so the user always
                    406:                 * gets back something deterministic.
                    407:                 */
                    408:                bzero(data, size);
                    409:        else if (com&IOC_VOID)
                    410:                *(caddr_t *)data = uap->cmarg;
                    411: 
                    412:        switch (com) {
                    413: 
                    414:        case FIONBIO:
                    415:                if (tmp = *(int *)data)
                    416:                        fp->f_flag |= FNONBLOCK;
                    417:                else
                    418:                        fp->f_flag &= ~FNONBLOCK;
                    419:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    420:                break;
                    421: 
                    422:        case FIOASYNC:
                    423:                if (tmp = *(int *)data)
                    424:                        fp->f_flag |= FASYNC;
                    425:                else
                    426:                        fp->f_flag &= ~FASYNC;
                    427:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                    428:                break;
                    429: 
                    430:        case FIOSETOWN:
                    431:                tmp = *(int *)data;
                    432:                if (fp->f_type == DTYPE_SOCKET) {
                    433:                        ((struct socket *)fp->f_data)->so_pgid = tmp;
                    434:                        error = 0;
                    435:                        break;
                    436:                }
                    437:                if (tmp <= 0) {
                    438:                        tmp = -tmp;
                    439:                } else {
                    440:                        struct proc *p1 = pfind(tmp);
                    441:                        if (p1 == 0) {
                    442:                                error = ESRCH;
                    443:                                break;
                    444:                        }
                    445:                        tmp = p1->p_pgrp->pg_id;
                    446:                }
                    447:                error = (*fp->f_ops->fo_ioctl)
                    448:                        (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
                    449:                break;
                    450: 
                    451:        case FIOGETOWN:
                    452:                if (fp->f_type == DTYPE_SOCKET) {
                    453:                        error = 0;
                    454:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                    455:                        break;
                    456:                }
                    457:                error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
                    458:                *(int *)data = -*(int *)data;
                    459:                break;
                    460: 
                    461:        default:
                    462:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
                    463:                /*
                    464:                 * Copy any data to user, size was
                    465:                 * already set and checked above.
                    466:                 */
                    467:                if (error == 0 && (com&IOC_OUT) && size)
                    468:                        error = copyout(data, uap->cmarg, (u_int)size);
                    469:                break;
                    470:        }
                    471:        if (memp)
                    472:                free(memp, M_IOCTLOPS);
                    473:        return (error);
                    474: }
                    475: 
                    476: int    selwait, nselcoll;
                    477: 
                    478: /*
                    479:  * Select system call.
                    480:  */
                    481: select(p, uap, retval)
                    482:        register struct proc *p;
                    483:        register struct args {
                    484:                int     nd;
                    485:                fd_set  *in, *ou, *ex;
                    486:                struct  timeval *tv;
                    487:        } *uap;
                    488:        int *retval;
                    489: {
                    490:        fd_set ibits[3], obits[3];
                    491:        struct timeval atv;
                    492:        int s, ncoll, ni, error = 0, timo;
                    493: 
                    494:        bzero((caddr_t)ibits, sizeof(ibits));
                    495:        bzero((caddr_t)obits, sizeof(obits));
                    496:        if (uap->nd > p->p_fd->fd_nfiles)
                    497:                uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
                    498:        ni = howmany(uap->nd, NFDBITS);
                    499: 
                    500: #define        getbits(name, x) \
                    501:        if (uap->name) { \
                    502:                error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
                    503:                    (unsigned)(ni * sizeof(fd_mask))); \
                    504:                if (error) \
                    505:                        goto done; \
                    506:        }
                    507:        getbits(in, 0);
                    508:        getbits(ou, 1);
                    509:        getbits(ex, 2);
                    510: #undef getbits
                    511: 
                    512:        if (uap->tv) {
                    513:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    514:                        sizeof (atv));
                    515:                if (error)
                    516:                        goto done;
                    517:                if (itimerfix(&atv)) {
                    518:                        error = EINVAL;
                    519:                        goto done;
                    520:                }
                    521:                s = splhigh(); timevaladd(&atv, &time); splx(s);
                    522:                timo = hzto(&atv);
                    523:        } else
                    524:                timo = 0;
                    525: retry:
                    526:        ncoll = nselcoll;
                    527:        p->p_flag |= SSEL;
                    528:        error = selscan(p, ibits, obits, uap->nd, retval);
                    529:        if (error || *retval)
                    530:                goto done;
                    531:        s = splhigh();
                    532:        /* this should be timercmp(&time, &atv, >=) */
                    533:        if (uap->tv && (time.tv_sec > atv.tv_sec ||
                    534:            time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
                    535:                splx(s);
                    536:                goto done;
                    537:        }
                    538:        if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
                    539:                splx(s);
                    540:                goto retry;
                    541:        }
                    542:        p->p_flag &= ~SSEL;
                    543:        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
                    544:        splx(s);
                    545:        if (error == 0)
                    546:                goto retry;
                    547: done:
                    548:        p->p_flag &= ~SSEL;
                    549:        /* select is not restarted after signals... */
                    550:        if (error == ERESTART)
                    551:                error = EINTR;
                    552:        if (error == EWOULDBLOCK)
                    553:                error = 0;
                    554: #define        putbits(name, x) \
                    555:        if (uap->name) { \
                    556:                int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
                    557:                    (unsigned)(ni * sizeof(fd_mask))); \
                    558:                if (error2) \
                    559:                        error = error2; \
                    560:        }
                    561:        if (error == 0) {
                    562:                putbits(in, 0);
                    563:                putbits(ou, 1);
                    564:                putbits(ex, 2);
                    565: #undef putbits
                    566:        }
                    567:        return (error);
                    568: }
                    569: 
                    570: selscan(p, ibits, obits, nfd, retval)
                    571:        struct proc *p;
                    572:        fd_set *ibits, *obits;
                    573:        int nfd, *retval;
                    574: {
                    575:        register struct filedesc *fdp = p->p_fd;
                    576:        register int which, i, j;
                    577:        register fd_mask bits;
                    578:        int flag;
                    579:        struct file *fp;
                    580:        int error = 0, n = 0;
                    581: 
                    582:        for (which = 0; which < 3; which++) {
                    583:                switch (which) {
                    584: 
                    585:                case 0:
                    586:                        flag = FREAD; break;
                    587: 
                    588:                case 1:
                    589:                        flag = FWRITE; break;
                    590: 
                    591:                case 2:
                    592:                        flag = 0; break;
                    593:                }
                    594:                for (i = 0; i < nfd; i += NFDBITS) {
                    595:                        bits = ibits[which].fds_bits[i/NFDBITS];
                    596:                        while ((j = ffs(bits)) && i + --j < nfd) {
                    597:                                bits &= ~(1 << j);
                    598:                                fp = fdp->fd_ofiles[i + j];
                    599:                                if (fp == NULL) {
                    600:                                        error = EBADF;
                    601:                                        break;
                    602:                                }
                    603:                                if ((*fp->f_ops->fo_select)(fp, flag, p)) {
                    604:                                        FD_SET(i + j, &obits[which]);
                    605:                                        n++;
                    606:                                }
                    607:                        }
                    608:                }
                    609:        }
                    610:        *retval = n;
                    611:        return (error);
                    612: }
                    613: 
                    614: /*ARGSUSED*/
                    615: #ifdef __STDC__
                    616: seltrue(dev_t dev, int which, struct proc *p)
                    617: #else
                    618: seltrue(dev, flag, p)
                    619:        dev_t dev;
                    620:        int flag;
                    621:        struct proc *p;
                    622: #endif
                    623: {
                    624: 
                    625:        return (1);
                    626: }
                    627: 
                    628: selwakeup(p, coll)
                    629:        register struct proc *p;
                    630:        int coll;
                    631: {
                    632: 
                    633:        if (coll) {
                    634:                nselcoll++;
                    635:                wakeup((caddr_t)&selwait);
                    636:        }
                    637:        if (p) {
                    638:                int s = splhigh();
                    639:                if (p->p_wchan == (caddr_t)&selwait) {
                    640:                        if (p->p_stat == SSLEEP)
                    641:                                setrun(p);
                    642:                        else
                    643:                                unsleep(p);
                    644:                } else if (p->p_flag & SSEL)
                    645:                        p->p_flag &= ~SSEL;
                    646:                splx(s);
                    647:        }
                    648: }

unix.superglobalmegacorp.com

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