[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

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