149589Sbostic /*- 249589Sbostic * Copyright (c) 1982, 1986 The Regents of the University of California. 349589Sbostic * All rights reserved. 423391Smckusick * 549589Sbostic * %sccs.include.proprietary.c% 649589Sbostic * 7*52501Storek * @(#)tty_subr.c 7.8 (Berkeley) 02/14/92 823391Smckusick */ 91892Swnj 1017097Sbloom #include "param.h" 1117097Sbloom #include "systm.h" 1217097Sbloom #include "buf.h" 1317576Sbloom #include "ioctl.h" 1417097Sbloom #include "tty.h" 1517097Sbloom #include "clist.h" 1632Sbill 171890Swnj char cwaiting; 181890Swnj 1935811Smarc #define setquote(cp) \ 2035811Smarc setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2135811Smarc (int)(cp)&CROUND) 2235811Smarc #define isquote(cp) \ 2335811Smarc isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2435811Smarc (int)(cp)&CROUND) 2535811Smarc #define cbptr(x) ((struct cblock *)(x)) 2635811Smarc 2732Sbill /* 2847545Skarels * Initialize clist by freeing all character blocks. 2947545Skarels */ 3047545Skarels cinit() 3147545Skarels { 3247545Skarels register int ccp; 3347545Skarels register struct cblock *cp; 3447545Skarels 3547545Skarels ccp = (int) cfree; 3647545Skarels ccp = (ccp + CROUND) & ~CROUND; 3747545Skarels for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) { 3847545Skarels cp->c_next = cfreelist; 3947545Skarels cfreelist = cp; 4047545Skarels cfreecount += CBSIZE; 4147545Skarels } 4247545Skarels } 4347545Skarels 4447545Skarels /* 4532Sbill * Character list get/put 4632Sbill */ 4732Sbill getc(p) 4812754Ssam register struct clist *p; 4932Sbill { 5032Sbill register struct cblock *bp; 5132Sbill register int c, s; 5232Sbill 5317542Skarels s = spltty(); 5432Sbill if (p->c_cc <= 0) { 5532Sbill c = -1; 5632Sbill p->c_cc = 0; 5732Sbill p->c_cf = p->c_cl = NULL; 5832Sbill } else { 5935811Smarc c = *p->c_cf & 0377; 6035811Smarc if (isquote(p->c_cf)) 6135811Smarc c |= TTY_QUOTE; 6235811Smarc p->c_cf++; 6332Sbill if (--p->c_cc<=0) { 6435811Smarc bp = cbptr(p->c_cf-1); 6535811Smarc bp = cbptr((int)bp & ~CROUND); 6632Sbill p->c_cf = NULL; 6732Sbill p->c_cl = NULL; 6832Sbill bp->c_next = cfreelist; 6932Sbill cfreelist = bp; 701890Swnj cfreecount += CBSIZE; 711890Swnj if (cwaiting) { 721890Swnj wakeup(&cwaiting); 731890Swnj cwaiting = 0; 741890Swnj } 7532Sbill } else if (((int)p->c_cf & CROUND) == 0){ 7635811Smarc bp = cbptr(p->c_cf); 7732Sbill bp--; 7832Sbill p->c_cf = bp->c_next->c_info; 7932Sbill bp->c_next = cfreelist; 8032Sbill cfreelist = bp; 811890Swnj cfreecount += CBSIZE; 821890Swnj if (cwaiting) { 831890Swnj wakeup(&cwaiting); 841890Swnj cwaiting = 0; 851890Swnj } 8632Sbill } 8732Sbill } 8832Sbill splx(s); 8926279Skarels return (c); 9032Sbill } 9132Sbill 9232Sbill /* 9332Sbill * copy clist to buffer. 9432Sbill * return number of bytes moved. 9532Sbill */ 9632Sbill q_to_b(q, cp, cc) 979761Ssam register struct clist *q; 989761Ssam register char *cp; 99*52501Storek int cc; 10032Sbill { 10132Sbill register struct cblock *bp; 102*52501Storek register int s, nc; 10332Sbill char *acp; 10432Sbill 10532Sbill if (cc <= 0) 10626279Skarels return (0); 10717542Skarels s = spltty(); 10832Sbill if (q->c_cc <= 0) { 10932Sbill q->c_cc = 0; 11032Sbill q->c_cf = q->c_cl = NULL; 1111890Swnj splx(s); 11226279Skarels return (0); 11332Sbill } 11432Sbill acp = cp; 11532Sbill 11617542Skarels while (cc) { 11726279Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 11817542Skarels nc = MIN(nc, cc); 11917542Skarels nc = MIN(nc, q->c_cc); 12017542Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 12117542Skarels q->c_cf += nc; 12217542Skarels q->c_cc -= nc; 12317542Skarels cc -= nc; 12417542Skarels cp += nc; 12517542Skarels if (q->c_cc <= 0) { 12635811Smarc bp = cbptr(q->c_cf - 1); 12735811Smarc bp = cbptr((int)bp & ~CROUND); 12832Sbill q->c_cf = q->c_cl = NULL; 12932Sbill bp->c_next = cfreelist; 13032Sbill cfreelist = bp; 1311890Swnj cfreecount += CBSIZE; 1321890Swnj if (cwaiting) { 1331890Swnj wakeup(&cwaiting); 1341890Swnj cwaiting = 0; 1351890Swnj } 13632Sbill break; 13732Sbill } 13832Sbill if (((int)q->c_cf & CROUND) == 0) { 13935811Smarc bp = cbptr(q->c_cf); 14032Sbill bp--; 14132Sbill q->c_cf = bp->c_next->c_info; 14232Sbill bp->c_next = cfreelist; 14332Sbill cfreelist = bp; 1441890Swnj cfreecount += CBSIZE; 1451890Swnj if (cwaiting) { 1461890Swnj wakeup(&cwaiting); 1471890Swnj cwaiting = 0; 1481890Swnj } 14932Sbill } 15032Sbill } 15132Sbill splx(s); 15226279Skarels return (cp-acp); 15332Sbill } 15432Sbill 15532Sbill /* 15632Sbill * Return count of contiguous characters 15732Sbill * in clist starting at q->c_cf. 15832Sbill * Stop counting if flag&character is non-null. 15932Sbill */ 16032Sbill ndqb(q, flag) 1619761Ssam register struct clist *q; 162*52501Storek int flag; 16332Sbill { 164*52501Storek register int cc, s; 16532Sbill 16617542Skarels s = spltty(); 16732Sbill if (q->c_cc <= 0) { 16832Sbill cc = -q->c_cc; 16932Sbill goto out; 17032Sbill } 17132Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 17232Sbill cc -= (int)q->c_cf; 17332Sbill if (q->c_cc < cc) 17432Sbill cc = q->c_cc; 17532Sbill if (flag) { 17632Sbill register char *p, *end; 17732Sbill 17832Sbill p = q->c_cf; 17932Sbill end = p; 18032Sbill end += cc; 18132Sbill while (p < end) { 18232Sbill if (*p & flag) { 1831890Swnj cc = (int)p; 1841890Swnj cc -= (int)q->c_cf; 18532Sbill break; 18632Sbill } 18732Sbill p++; 18832Sbill } 18932Sbill } 19032Sbill out: 19132Sbill splx(s); 19226279Skarels return (cc); 19332Sbill } 19432Sbill 19532Sbill /* 1961890Swnj * Flush cc bytes from q. 19732Sbill */ 19832Sbill ndflush(q, cc) 19912754Ssam register struct clist *q; 200*52501Storek register int cc; 20132Sbill { 20212754Ssam register struct cblock *bp; 20312754Ssam char *end; 20412754Ssam int rem, s; 20532Sbill 20617542Skarels s = spltty(); 20726279Skarels if (q->c_cc <= 0) 20832Sbill goto out; 2091890Swnj while (cc>0 && q->c_cc) { 21035811Smarc bp = cbptr((int)q->c_cf & ~CROUND); 2111890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 2121890Swnj end = q->c_cl; 2131890Swnj } else { 2141890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 2151890Swnj } 2161890Swnj rem = end - q->c_cf; 2171890Swnj if (cc >= rem) { 2181890Swnj cc -= rem; 2191890Swnj q->c_cc -= rem; 22032Sbill q->c_cf = bp->c_next->c_info; 2211890Swnj bp->c_next = cfreelist; 2221890Swnj cfreelist = bp; 2231890Swnj cfreecount += CBSIZE; 2241890Swnj if (cwaiting) { 2251890Swnj wakeup(&cwaiting); 2261890Swnj cwaiting = 0; 2271890Swnj } 22832Sbill } else { 2291890Swnj q->c_cc -= cc; 2301890Swnj q->c_cf += cc; 2311890Swnj if (q->c_cc <= 0) { 2321890Swnj bp->c_next = cfreelist; 2331890Swnj cfreelist = bp; 2341890Swnj cfreecount += CBSIZE; 2351890Swnj if (cwaiting) { 2361890Swnj wakeup(&cwaiting); 2371890Swnj cwaiting = 0; 2381890Swnj } 2391890Swnj } 2401890Swnj break; 24132Sbill } 2421890Swnj } 2431890Swnj if (q->c_cc <= 0) { 24432Sbill q->c_cf = q->c_cl = NULL; 2451890Swnj q->c_cc = 0; 24632Sbill } 24732Sbill out: 24832Sbill splx(s); 24932Sbill } 250172Sbill 2511890Swnj 25232Sbill putc(c, p) 253*52501Storek int c; 25412754Ssam register struct clist *p; 25532Sbill { 25632Sbill register struct cblock *bp; 25732Sbill register char *cp; 258*52501Storek register int s; 25932Sbill 26017542Skarels s = spltty(); 26135811Smarc if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ 26232Sbill if ((bp = cfreelist) == NULL) { 26332Sbill splx(s); 26426279Skarels return (-1); 26532Sbill } 26632Sbill cfreelist = bp->c_next; 2671890Swnj cfreecount -= CBSIZE; 26832Sbill bp->c_next = NULL; 26935811Smarc bzero(bp->c_quote, CBQSIZE); 27032Sbill p->c_cf = cp = bp->c_info; 27132Sbill } else if (((int)cp & CROUND) == 0) { 27235811Smarc bp = cbptr(cp) - 1; /* pointer arith */ 27332Sbill if ((bp->c_next = cfreelist) == NULL) { 27432Sbill splx(s); 27526279Skarels return (-1); 27632Sbill } 27732Sbill bp = bp->c_next; 27832Sbill cfreelist = bp->c_next; 2791890Swnj cfreecount -= CBSIZE; 28032Sbill bp->c_next = NULL; 28132Sbill cp = bp->c_info; 28232Sbill } 28335811Smarc if (c&TTY_QUOTE) 28435811Smarc setquote(cp); 28532Sbill *cp++ = c; 28632Sbill p->c_cc++; 28732Sbill p->c_cl = cp; 28832Sbill splx(s); 28926279Skarels return (0); 29032Sbill } 29132Sbill 29232Sbill /* 29332Sbill * copy buffer to clist. 29432Sbill * return number of bytes not transfered. 29532Sbill */ 29632Sbill b_to_q(cp, cc, q) 29712754Ssam register char *cp; 29812754Ssam struct clist *q; 29912754Ssam register int cc; 30032Sbill { 30132Sbill register char *cq; 30232Sbill register struct cblock *bp; 303*52501Storek register int s, nc; 30417542Skarels int acc; 30532Sbill 30632Sbill if (cc <= 0) 30726279Skarels return (0); 30817542Skarels acc = cc; 30917542Skarels s = spltty(); 31017542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 31117542Skarels if ((bp = cfreelist) == NULL) 31217542Skarels goto out; 31317542Skarels cfreelist = bp->c_next; 31417542Skarels cfreecount -= CBSIZE; 31535811Smarc bzero(bp->c_quote, CBQSIZE); 31617542Skarels bp->c_next = NULL; 31717542Skarels q->c_cf = cq = bp->c_info; 31817542Skarels } 31917542Skarels 32017542Skarels while (cc) { 32132Sbill if (((int)cq & CROUND) == 0) { 32235811Smarc bp = cbptr(cq) - 1; 32317542Skarels if ((bp->c_next = cfreelist) == NULL) 32417542Skarels goto out; 32532Sbill bp = bp->c_next; 32632Sbill cfreelist = bp->c_next; 3271890Swnj cfreecount -= CBSIZE; 32835811Smarc bzero(bp->c_quote, CBQSIZE); 32932Sbill bp->c_next = NULL; 33017542Skarels cq = bp->c_info; 33132Sbill } 33226279Skarels nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 33317542Skarels (void) bcopy(cp, cq, (unsigned)nc); 33417542Skarels cp += nc; 33517542Skarels cq += nc; 33617542Skarels cc -= nc; 33732Sbill } 33817542Skarels out: 33917542Skarels q->c_cl = cq; 34017542Skarels q->c_cc += acc - cc; 34117542Skarels splx(s); 34217368Ssam return (cc); 34332Sbill } 34432Sbill 34532Sbill /* 346172Sbill * Given a non-NULL pointter into the list (like c_cf which 347172Sbill * always points to a real character if non-NULL) return the pointer 348172Sbill * to the next character in the list or return NULL if no more chars. 349172Sbill * 350172Sbill * Callers must not allow getc's to happen between nextc's so that the 351172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 352172Sbill */ 353172Sbill char * 35435811Smarc nextc(p, cp, c) 35512754Ssam register struct clist *p; 35612754Ssam register char *cp; 35735811Smarc register int *c; 358172Sbill { 359172Sbill 360172Sbill if (p->c_cc && ++cp != p->c_cl) { 36135811Smarc if (((int)cp & CROUND) == 0) { 36235811Smarc cp = (cbptr(cp))[-1].c_next->c_info; 36335811Smarc } 36435811Smarc *c = *cp; 36535811Smarc if (isquote(cp)) 36635811Smarc *c |= TTY_QUOTE; 367172Sbill return (cp); 368172Sbill } 369172Sbill return (0); 370172Sbill } 371172Sbill 372172Sbill /* 373172Sbill * Remove the last character in the list and return it. 374172Sbill */ 375172Sbill unputc(p) 37612754Ssam register struct clist *p; 377172Sbill { 378172Sbill register struct cblock *bp; 379172Sbill register int c, s; 380172Sbill struct cblock *obp; 381172Sbill 38217542Skarels s = spltty(); 383172Sbill if (p->c_cc <= 0) 384172Sbill c = -1; 385172Sbill else { 386172Sbill c = *--p->c_cl; 38735811Smarc if (isquote(p->c_cl)) 38835811Smarc c |= TTY_QUOTE; 389172Sbill if (--p->c_cc <= 0) { 39035811Smarc bp = cbptr(p->c_cl); 39135811Smarc bp = cbptr((int)bp & ~CROUND); 392172Sbill p->c_cl = p->c_cf = NULL; 393172Sbill bp->c_next = cfreelist; 394172Sbill cfreelist = bp; 3951890Swnj cfreecount += CBSIZE; 39635811Smarc } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { 397172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 39835811Smarc 39935811Smarc bp = cbptr(p->c_cf); 40035811Smarc bp = cbptr((int)bp & ~CROUND); 40135811Smarc while (bp->c_next != cbptr(p->c_cl)) 402172Sbill bp = bp->c_next; 403172Sbill obp = bp; 404172Sbill p->c_cl = (char *)(bp + 1); 405172Sbill bp = bp->c_next; 406172Sbill bp->c_next = cfreelist; 407172Sbill cfreelist = bp; 4081890Swnj cfreecount += CBSIZE; 409172Sbill obp->c_next = NULL; 410172Sbill } 411172Sbill } 412172Sbill splx(s); 413172Sbill return (c); 414172Sbill } 415172Sbill 416172Sbill /* 417172Sbill * Put the chars in the from que 418172Sbill * on the end of the to que. 419172Sbill */ 420172Sbill catq(from, to) 42112754Ssam struct clist *from, *to; 422172Sbill { 42335811Smarc #ifdef notdef 42417542Skarels char bbuf[CBSIZE*4]; 42535811Smarc #endif 426*52501Storek register int s, c; 427172Sbill 42817542Skarels s = spltty(); 42917542Skarels if (to->c_cc == 0) { 43017542Skarels *to = *from; 43117542Skarels from->c_cc = 0; 43217542Skarels from->c_cf = NULL; 43317542Skarels from->c_cl = NULL; 43417542Skarels splx(s); 43517542Skarels return; 43617542Skarels } 43717542Skarels splx(s); 43835811Smarc #ifdef notdef 43917542Skarels while (from->c_cc > 0) { 44017542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 44117542Skarels (void) b_to_q(bbuf, c, to); 44217542Skarels } 44335811Smarc #endif 44435811Smarc /* XXX - FIX */ 44535811Smarc while ((c = getc(from)) >= 0) 44635811Smarc putc(c, to); 447172Sbill } 448172Sbill 44917542Skarels #ifdef unneeded 450172Sbill /* 45126279Skarels * Integer (short) get/put using clists. 45232Sbill */ 45317542Skarels typedef u_short word_t; 4549761Ssam 45532Sbill getw(p) 4568955Sroot register struct clist *p; 45732Sbill { 45817542Skarels register int s, c; 45917542Skarels register struct cblock *bp; 46032Sbill 46117542Skarels if (p->c_cc <= 1) 46217542Skarels return(-1); 46317542Skarels if (p->c_cc & 01) { 46417542Skarels c = getc(p); 46533398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 46626279Skarels return (c | (getc(p)<<8)); 46726279Skarels #else 46826279Skarels return (getc(p) | (c<<8)); 46926279Skarels #endif 47017542Skarels } 47117542Skarels s = spltty(); 47235811Smarc #if BYTE_ORDER == LITTLE_ENDIAN 47329947Skarels c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; 47426279Skarels #else 47526279Skarels c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 47626279Skarels #endif 47726279Skarels p->c_cf += sizeof (word_t); 47826279Skarels p->c_cc -= sizeof (word_t); 47917542Skarels if (p->c_cc <= 0) { 48035811Smarc bp = cbptr(p->c_cf-1); 48135811Smarc bp = cbptr((int)bp & ~CROUND); 48217542Skarels p->c_cf = NULL; 48317542Skarels p->c_cl = NULL; 48417542Skarels bp->c_next = cfreelist; 48517542Skarels cfreelist = bp; 48617542Skarels cfreecount += CBSIZE; 48717542Skarels if (cwaiting) { 48817542Skarels wakeup(&cwaiting); 48917542Skarels cwaiting = 0; 49017542Skarels } 49117542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 49235811Smarc bp = cbptr(p->c_cf); 49317542Skarels bp--; 49417542Skarels p->c_cf = bp->c_next->c_info; 49517542Skarels bp->c_next = cfreelist; 49617542Skarels cfreelist = bp; 49717542Skarels cfreecount += CBSIZE; 49817542Skarels if (cwaiting) { 49917542Skarels wakeup(&cwaiting); 50017542Skarels cwaiting = 0; 50117542Skarels } 50217542Skarels } 50317542Skarels splx(s); 50417542Skarels return (c); 50532Sbill } 50632Sbill 50732Sbill putw(c, p) 5088955Sroot register struct clist *p; 50917542Skarels word_t c; 51032Sbill { 511*52501Storek register int s; 51217542Skarels register struct cblock *bp; 51317542Skarels register char *cp; 51432Sbill 51517542Skarels s = spltty(); 51632Sbill if (cfreelist==NULL) { 51732Sbill splx(s); 51832Sbill return(-1); 51932Sbill } 52017542Skarels if (p->c_cc & 01) { 52133398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 52217542Skarels (void) putc(c, p); 52317542Skarels (void) putc(c>>8, p); 52426279Skarels #else 52526279Skarels (void) putc(c>>8, p); 52626279Skarels (void) putc(c, p); 52726279Skarels #endif 52817542Skarels } else { 52917542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 53017542Skarels if ((bp = cfreelist) == NULL) { 53117542Skarels splx(s); 53217542Skarels return (-1); 53317542Skarels } 53417542Skarels cfreelist = bp->c_next; 53517542Skarels cfreecount -= CBSIZE; 53617542Skarels bp->c_next = NULL; 53717542Skarels p->c_cf = cp = bp->c_info; 53817542Skarels } else if (((int)cp & CROUND) == 0) { 53935811Smarc bp = cbptr(cp) - 1; 54017542Skarels if ((bp->c_next = cfreelist) == NULL) { 54117542Skarels splx(s); 54217542Skarels return (-1); 54317542Skarels } 54417542Skarels bp = bp->c_next; 54517542Skarels cfreelist = bp->c_next; 54617542Skarels cfreecount -= CBSIZE; 54717542Skarels bp->c_next = NULL; 54817542Skarels cp = bp->c_info; 54917542Skarels } 55026279Skarels #if defined(vax) 55117542Skarels *(word_t *)cp = c; 55226279Skarels #else 55326279Skarels ((u_char *)cp)[0] = c>>8; 55426279Skarels ((u_char *)cp)[1] = c; 55526279Skarels #endif 55626279Skarels p->c_cl = cp + sizeof (word_t); 55726279Skarels p->c_cc += sizeof (word_t); 55817542Skarels } 55932Sbill splx(s); 5609761Ssam return (0); 56132Sbill } 56217542Skarels #endif unneeded 563