[BACK]Return to tty_subr.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/tty_subr.c, Revision 1.1

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

CVSweb