Annotation of XNU/bsd/kern/tty_subr.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) 1997 Apple Computer, Inc. All Rights Reserved */
        !            23: /*
        !            24:  * Copyright (c) 1993, 1994 Theo de Raadt
        !            25:  * All rights reserved.
        !            26:  *
        !            27:  * Redistribution and use in source and binary forms, with or without
        !            28:  * modification, are permitted provided that the following conditions
        !            29:  * are met:
        !            30:  * 1. Redistributions of source code must retain the above copyright
        !            31:  *    notice unmodified, this list of conditions, and the following
        !            32:  *    disclaimer.
        !            33:  * 2. Redistributions in binary form must reproduce the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer in the
        !            35:  *    documentation and/or other materials provided with the distribution.
        !            36:  *
        !            37:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            38:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            39:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            40:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            41:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            42:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            43:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            44:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            45:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            46:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            47:  * SUCH DAMAGE.
        !            48:  *
        !            49:  */
        !            50: 
        !            51: #ifdef NeXT
        !            52: /*
        !            53:  * We use the NetBSD based clist system, it is much more efficient than the
        !            54:  * old style clist stuff used by free bsd.
        !            55:  */
        !            56: 
        !            57: #include <sys/param.h>
        !            58: #include <sys/systm.h>
        !            59: #include <sys/buf.h>
        !            60: #include <sys/ioctl.h>
        !            61: #include <sys/tty.h>
        !            62: #include <sys/malloc.h>
        !            63: 
        !            64: #include <machine/spl.h>
        !            65: 
        !            66: /*
        !            67:  * At compile time, choose:
        !            68:  * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
        !            69:  * defined we allocate an array of bits -- 1/8th as much memory but
        !            70:  * setbit(), clrbit(), and isset() take more cpu. If QBITS is
        !            71:  * undefined, we just use an array of bytes.
        !            72:  * 
        !            73:  * If TTY_QUOTE functionality isn't required by a line discipline,
        !            74:  * it can free c_cq and set it to NULL. This speeds things up,
        !            75:  * and also does not use any extra memory. This is useful for (say)
        !            76:  * a SLIP line discipline that wants a 32K ring buffer for data
        !            77:  * but doesn't need quoting.
        !            78:  */
        !            79: #define QBITS
        !            80: 
        !            81: #ifdef QBITS
        !            82: #define QMEM(n)                ((((n)-1)/NBBY)+1)
        !            83: #else
        !            84: #define QMEM(n)                (n)
        !            85: #endif
        !            86: 
        !            87: 
        !            88: /*
        !            89:  * Initialize clists.
        !            90:  */
        !            91: void
        !            92: cinit()
        !            93: {
        !            94: }
        !            95: 
        !            96: /*
        !            97:  * Initialize a particular clist. Ok, they are really ring buffers,
        !            98:  * of the specified length, with/without quoting support.
        !            99:  */
        !           100: int
        !           101: clalloc(clp, size, quot)
        !           102:        struct clist *clp;
        !           103:        int size;
        !           104:        int quot;
        !           105: {
        !           106: 
        !           107:        MALLOC(clp->c_cs, u_char *, size, M_TTYS, M_WAITOK);
        !           108:        if (!clp->c_cs)
        !           109:                return (-1);
        !           110:        bzero(clp->c_cs, size);
        !           111: 
        !           112:        if(quot) {
        !           113:                MALLOC(clp->c_cq, u_char *, QMEM(size), M_TTYS, M_WAITOK);
        !           114:                if (!clp->c_cq) {
        !           115:                        FREE(clp->c_cs, M_TTYS);
        !           116:                        return (-1);
        !           117:                }
        !           118:                bzero(clp->c_cs, QMEM(size));
        !           119:        } else
        !           120:                clp->c_cq = (u_char *)0;
        !           121: 
        !           122:        clp->c_cf = clp->c_cl = (u_char *)0;
        !           123:        clp->c_ce = clp->c_cs + size;
        !           124:        clp->c_cn = size;
        !           125:        clp->c_cc = 0;
        !           126:        return (0);
        !           127: }
        !           128: 
        !           129: void
        !           130: clfree(clp)
        !           131:        struct clist *clp;
        !           132: {
        !           133:        if(clp->c_cs)
        !           134:                FREE(clp->c_cs, M_TTYS);
        !           135:        if(clp->c_cq)
        !           136:                FREE(clp->c_cq, M_TTYS);
        !           137:        clp->c_cs = clp->c_cq = (u_char *)0;
        !           138: }
        !           139: 
        !           140: 
        !           141: /*
        !           142:  * Get a character from a clist.
        !           143:  */
        !           144: int
        !           145: getc(clp)
        !           146:        struct clist *clp;
        !           147: {
        !           148:        register int c = -1;
        !           149:        int s;
        !           150: 
        !           151:        s = spltty();
        !           152:        if (clp->c_cc == 0)
        !           153:                goto out;
        !           154: 
        !           155:        c = *clp->c_cf & 0xff;
        !           156:        if (clp->c_cq) {
        !           157: #ifdef QBITS
        !           158:                if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
        !           159:                        c |= TTY_QUOTE;
        !           160: #else
        !           161:                if (*(clp->c_cf - clp->c_cs + clp->c_cq))
        !           162:                        c |= TTY_QUOTE;
        !           163: #endif
        !           164:        }
        !           165:        if (++clp->c_cf == clp->c_ce)
        !           166:                clp->c_cf = clp->c_cs;
        !           167:        if (--clp->c_cc == 0)
        !           168:                clp->c_cf = clp->c_cl = (u_char *)0;
        !           169: out:
        !           170:        splx(s);
        !           171:        return c;
        !           172: }
        !           173: 
        !           174: /*
        !           175:  * Copy clist to buffer.
        !           176:  * Return number of bytes moved.
        !           177:  */
        !           178: int
        !           179: q_to_b(clp, cp, count)
        !           180:        struct clist *clp;
        !           181:        u_char *cp;
        !           182:        int count;
        !           183: {
        !           184:        register int cc;
        !           185:        u_char *p = cp;
        !           186:        int s;
        !           187: 
        !           188:        s = spltty();
        !           189:        /* optimize this while loop */
        !           190:        while (count > 0 && clp->c_cc > 0) {
        !           191:                cc = clp->c_cl - clp->c_cf;
        !           192:                if (clp->c_cf >= clp->c_cl)
        !           193:                        cc = clp->c_ce - clp->c_cf;
        !           194:                if (cc > count)
        !           195:                        cc = count;
        !           196:                bcopy(clp->c_cf, p, cc);
        !           197:                count -= cc;
        !           198:                p += cc;
        !           199:                clp->c_cc -= cc;
        !           200:                clp->c_cf += cc;
        !           201:                if (clp->c_cf == clp->c_ce)
        !           202:                        clp->c_cf = clp->c_cs;
        !           203:        }
        !           204:        if (clp->c_cc == 0)
        !           205:                clp->c_cf = clp->c_cl = (u_char *)0;
        !           206:        splx(s);
        !           207:        return p - cp;
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Return count of contiguous characters in clist.
        !           212:  * Stop counting if flag&character is non-null.
        !           213:  */
        !           214: int
        !           215: ndqb(clp, flag)
        !           216:        struct clist *clp;
        !           217:        int flag;
        !           218: {
        !           219:        int count = 0;
        !           220:        register int i;
        !           221:        register int cc;
        !           222:        int s;
        !           223: 
        !           224:        s = spltty();
        !           225:        if ((cc = clp->c_cc) == 0)
        !           226:                goto out;
        !           227: 
        !           228:        if (flag == 0) {
        !           229:                count = clp->c_cl - clp->c_cf;
        !           230:                if (count <= 0)
        !           231:                        count = clp->c_ce - clp->c_cf;
        !           232:                goto out;
        !           233:        }
        !           234: 
        !           235:        i = clp->c_cf - clp->c_cs;
        !           236:        if (flag & TTY_QUOTE) {
        !           237:                while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
        !           238:                    isset(clp->c_cq, i))) {
        !           239:                        count++;
        !           240:                        if (i == clp->c_cn)
        !           241:                                break;
        !           242:                }
        !           243:        } else {
        !           244:                while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
        !           245:                        count++;
        !           246:                        if (i == clp->c_cn)
        !           247:                                break;
        !           248:                }
        !           249:        }
        !           250: out:
        !           251:        splx(s);
        !           252:        return count;
        !           253: }
        !           254: 
        !           255: /*
        !           256:  * Flush count bytes from clist.
        !           257:  */
        !           258: void
        !           259: ndflush(clp, count)
        !           260:        struct clist *clp;
        !           261:        int count;
        !           262: {
        !           263:        register int cc;
        !           264:        int s;
        !           265: 
        !           266:        s = spltty();
        !           267:        if (count == clp->c_cc) {
        !           268:                clp->c_cc = 0;
        !           269:                clp->c_cf = clp->c_cl = (u_char *)0;
        !           270:                goto out;
        !           271:        }
        !           272:        /* optimize this while loop */
        !           273:        while (count > 0 && clp->c_cc > 0) {
        !           274:                cc = clp->c_cl - clp->c_cf;
        !           275:                if (clp->c_cf >= clp->c_cl)
        !           276:                        cc = clp->c_ce - clp->c_cf;
        !           277:                if (cc > count)
        !           278:                        cc = count;
        !           279:                count -= cc;
        !           280:                clp->c_cc -= cc;
        !           281:                clp->c_cf += cc;
        !           282:                if (clp->c_cf == clp->c_ce)
        !           283:                        clp->c_cf = clp->c_cs;
        !           284:        }
        !           285:        if (clp->c_cc == 0)
        !           286:                clp->c_cf = clp->c_cl = (u_char *)0;
        !           287: out:
        !           288:        splx(s);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * Put a character into the output queue.
        !           293:  */
        !           294: int
        !           295: putc(c, clp)
        !           296:        int c;
        !           297:        struct clist *clp;
        !           298: {
        !           299:        register int i;
        !           300:        int s;
        !           301: 
        !           302:        s = spltty();
        !           303:        if (clp->c_cc == 0) {
        !           304:                if (!clp->c_cs) {
        !           305: #if DIAGNOSTIC
        !           306:                        //printf("putc: required clalloc\n");
        !           307: #endif
        !           308:                        if(clalloc(clp, 1024, 1)) {
        !           309: out:
        !           310:                                splx(s);
        !           311:                                return -1;
        !           312:                        }
        !           313:                }
        !           314:                clp->c_cf = clp->c_cl = clp->c_cs;
        !           315:        }
        !           316: 
        !           317:        if (clp->c_cc == clp->c_cn)
        !           318:                goto out;
        !           319: 
        !           320:        *clp->c_cl = c & 0xff;
        !           321:        i = clp->c_cl - clp->c_cs;
        !           322:        if (clp->c_cq) {
        !           323: #ifdef QBITS
        !           324:                if (c & TTY_QUOTE)
        !           325:                        setbit(clp->c_cq, i); 
        !           326:                else
        !           327:                        clrbit(clp->c_cq, i);
        !           328: #else
        !           329:                q = clp->c_cq + i;
        !           330:                *q = (c & TTY_QUOTE) ? 1 : 0;
        !           331: #endif
        !           332:        }
        !           333:        clp->c_cc++;
        !           334:        clp->c_cl++;
        !           335:        if (clp->c_cl == clp->c_ce)
        !           336:                clp->c_cl = clp->c_cs;
        !           337:        splx(s);
        !           338:        return 0;
        !           339: }
        !           340: 
        !           341: #ifdef QBITS
        !           342: /*
        !           343:  * optimized version of
        !           344:  *
        !           345:  * for (i = 0; i < len; i++)
        !           346:  *     clrbit(cp, off + len);
        !           347:  */
        !           348: void
        !           349: clrbits(cp, off, len)
        !           350:        u_char *cp;
        !           351:        int off;
        !           352:        int len;
        !           353: {
        !           354:        int sby, sbi, eby, ebi;
        !           355:        register int i;
        !           356:        u_char mask;
        !           357: 
        !           358:        if(len==1) {
        !           359:                clrbit(cp, off);
        !           360:                return;
        !           361:        }
        !           362: 
        !           363:        sby = off / NBBY;
        !           364:        sbi = off % NBBY;
        !           365:        eby = (off+len) / NBBY;
        !           366:        ebi = (off+len) % NBBY;
        !           367:        if (sby == eby) {
        !           368:                mask = ((1 << (ebi - sbi)) - 1) << sbi;
        !           369:                cp[sby] &= ~mask;
        !           370:        } else {
        !           371:                mask = (1<<sbi) - 1;
        !           372:                cp[sby++] &= mask;
        !           373: 
        !           374:                mask = (1<<ebi) - 1;
        !           375:                cp[eby] &= ~mask;
        !           376: 
        !           377:                for (i = sby; i < eby; i++)
        !           378:                        cp[i] = 0x00;
        !           379:        }
        !           380: }
        !           381: #endif
        !           382: 
        !           383: /*
        !           384:  * Copy buffer to clist.
        !           385:  * Return number of bytes not transfered.
        !           386:  */
        !           387: int
        !           388: b_to_q(cp, count, clp)
        !           389:        u_char *cp;
        !           390:        int count;
        !           391:        struct clist *clp;
        !           392: {
        !           393:        register int cc;
        !           394:        register u_char *p = cp;
        !           395:        int s;
        !           396: 
        !           397:        if (count <= 0)
        !           398:                return 0;
        !           399: 
        !           400:        s = spltty();
        !           401: 
        !           402:        if (clp->c_cc == 0) {
        !           403:                if (!clp->c_cs) {
        !           404: #if DIAGNOSTIC
        !           405:                        printf("b_to_q: required clalloc\n");
        !           406: #endif
        !           407:                        if(clalloc(clp, 1024, 1))
        !           408:                                goto out;
        !           409:                }
        !           410:                clp->c_cf = clp->c_cl = clp->c_cs;
        !           411:        }
        !           412: 
        !           413:        if (clp->c_cc == clp->c_cn)
        !           414:                goto out;
        !           415: 
        !           416:        /* optimize this while loop */
        !           417:        while (count > 0 && clp->c_cc < clp->c_cn) {
        !           418:                cc = clp->c_ce - clp->c_cl;
        !           419:                if (clp->c_cf > clp->c_cl)
        !           420:                        cc = clp->c_cf - clp->c_cl;
        !           421:                if (cc > count)
        !           422:                        cc = count;
        !           423:                bcopy(p, clp->c_cl, cc);
        !           424:                if (clp->c_cq) {
        !           425: #ifdef QBITS
        !           426:                        clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
        !           427: #else
        !           428:                        bzero(clp->c_cl - clp->c_cs + clp->c_cq, cc);
        !           429: #endif
        !           430:                }
        !           431:                p += cc;
        !           432:                count -= cc;
        !           433:                clp->c_cc += cc;
        !           434:                clp->c_cl += cc;
        !           435:                if (clp->c_cl == clp->c_ce)
        !           436:                        clp->c_cl = clp->c_cs;
        !           437:        }
        !           438: out:
        !           439:        splx(s);
        !           440:        return count;
        !           441: }
        !           442: 
        !           443: static int cc;
        !           444: 
        !           445: /*
        !           446:  * Given a non-NULL pointer into the clist return the pointer
        !           447:  * to the next character in the list or return NULL if no more chars.
        !           448:  *
        !           449:  * Callers must not allow getc's to happen between firstc's and getc's
        !           450:  * so that the pointer becomes invalid.  Note that interrupts are NOT
        !           451:  * masked.
        !           452:  */
        !           453: u_char *
        !           454: nextc(clp, cp, c)
        !           455:        struct clist *clp;
        !           456:        register u_char *cp;
        !           457:        int *c;
        !           458: {
        !           459: 
        !           460:        if (clp->c_cf == cp) {
        !           461:                /*
        !           462:                 * First time initialization.
        !           463:                 */
        !           464:                cc = clp->c_cc;
        !           465:        }
        !           466:        if (cc == 0 || cp == NULL)
        !           467:                return NULL;
        !           468:        if (--cc == 0)
        !           469:                return NULL;
        !           470:        if (++cp == clp->c_ce)
        !           471:                cp = clp->c_cs;
        !           472:        *c = *cp & 0xff;
        !           473:        if (clp->c_cq) {
        !           474: #ifdef QBITS
        !           475:                if (isset(clp->c_cq, cp - clp->c_cs))
        !           476:                        *c |= TTY_QUOTE;
        !           477: #else
        !           478:                if (*(clp->c_cf - clp->c_cs + clp->c_cq))
        !           479:                        *c |= TTY_QUOTE;
        !           480: #endif
        !           481:        }
        !           482:        return cp;
        !           483: }
        !           484: 
        !           485: /*
        !           486:  * Given a non-NULL pointer into the clist return the pointer
        !           487:  * to the first character in the list or return NULL if no more chars.
        !           488:  *
        !           489:  * Callers must not allow getc's to happen between firstc's and getc's
        !           490:  * so that the pointer becomes invalid.  Note that interrupts are NOT
        !           491:  * masked.
        !           492:  *
        !           493:  * *c is set to the NEXT character
        !           494:  */
        !           495: u_char *
        !           496: firstc(clp, c)
        !           497:        struct clist *clp;
        !           498:        int *c;
        !           499: {
        !           500:        register u_char *cp;
        !           501: 
        !           502:        cc = clp->c_cc;
        !           503:        if (cc == 0)
        !           504:                return NULL;
        !           505:        cp = clp->c_cf;
        !           506:        *c = *cp & 0xff;
        !           507:        if(clp->c_cq) {
        !           508: #ifdef QBITS
        !           509:                if (isset(clp->c_cq, cp - clp->c_cs))
        !           510:                        *c |= TTY_QUOTE;
        !           511: #else
        !           512:                if (*(cp - clp->c_cs + clp->c_cq))
        !           513:                        *c |= TTY_QUOTE;
        !           514: #endif
        !           515:        }
        !           516:        return clp->c_cf;
        !           517: }
        !           518: 
        !           519: /*
        !           520:  * Remove the last character in the clist and return it.
        !           521:  */
        !           522: int
        !           523: unputc(clp)
        !           524:        struct clist *clp;
        !           525: {
        !           526:        unsigned int c = -1;
        !           527:        int s;
        !           528: 
        !           529:        s = spltty();
        !           530:        if (clp->c_cc == 0)
        !           531:                goto out;
        !           532: 
        !           533:        if (clp->c_cl == clp->c_cs)
        !           534:                clp->c_cl = clp->c_ce - 1;
        !           535:        else
        !           536:                --clp->c_cl;
        !           537:        clp->c_cc--;
        !           538: 
        !           539:        c = *clp->c_cl & 0xff;
        !           540:        if (clp->c_cq) {
        !           541: #ifdef QBITS
        !           542:                if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
        !           543:                        c |= TTY_QUOTE;
        !           544: #else
        !           545:                if (*(clp->c_cf - clp->c_cs + clp->c_cq))
        !           546:                        c |= TTY_QUOTE;
        !           547: #endif
        !           548:        }
        !           549:        if (clp->c_cc == 0)
        !           550:                clp->c_cf = clp->c_cl = (u_char *)0;
        !           551: out:
        !           552:        splx(s);
        !           553:        return c;
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * Put the chars in the from queue on the end of the to queue.
        !           558:  */
        !           559: void
        !           560: catq(from, to)
        !           561:        struct clist *from, *to;
        !           562: {
        !           563:        int c;
        !           564: 
        !           565:        while ((c = getc(from)) != -1)
        !           566:                putc(c, to);
        !           567: }
        !           568: 
        !           569: #endif /* NeXT */

unix.superglobalmegacorp.com

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