123391Smckusick /* 229110Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323391Smckusick * All rights reserved. The Berkeley software License Agreement 423391Smckusick * specifies the terms and conditions for redistribution. 523391Smckusick * 6*47545Skarels * @(#)tty_subr.c 7.6 (Berkeley) 03/17/91 723391Smckusick */ 81892Swnj 917097Sbloom #include "param.h" 1017097Sbloom #include "systm.h" 1117097Sbloom #include "buf.h" 1217576Sbloom #include "ioctl.h" 1317097Sbloom #include "tty.h" 1417097Sbloom #include "clist.h" 1532Sbill 161890Swnj char cwaiting; 171890Swnj 1835811Smarc #define setquote(cp) \ 1935811Smarc setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2035811Smarc (int)(cp)&CROUND) 2135811Smarc #define isquote(cp) \ 2235811Smarc isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2335811Smarc (int)(cp)&CROUND) 2435811Smarc #define cbptr(x) ((struct cblock *)(x)) 2535811Smarc 2632Sbill /* 27*47545Skarels * Initialize clist by freeing all character blocks. 28*47545Skarels */ 29*47545Skarels cinit() 30*47545Skarels { 31*47545Skarels register int ccp; 32*47545Skarels register struct cblock *cp; 33*47545Skarels 34*47545Skarels ccp = (int) cfree; 35*47545Skarels ccp = (ccp + CROUND) & ~CROUND; 36*47545Skarels for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) { 37*47545Skarels cp->c_next = cfreelist; 38*47545Skarels cfreelist = cp; 39*47545Skarels cfreecount += CBSIZE; 40*47545Skarels } 41*47545Skarels } 42*47545Skarels 43*47545Skarels /* 4432Sbill * Character list get/put 4532Sbill */ 4632Sbill getc(p) 4712754Ssam register struct clist *p; 4832Sbill { 4932Sbill register struct cblock *bp; 5032Sbill register int c, s; 5132Sbill 5217542Skarels s = spltty(); 5332Sbill if (p->c_cc <= 0) { 5432Sbill c = -1; 5532Sbill p->c_cc = 0; 5632Sbill p->c_cf = p->c_cl = NULL; 5732Sbill } else { 5835811Smarc c = *p->c_cf & 0377; 5935811Smarc if (isquote(p->c_cf)) 6035811Smarc c |= TTY_QUOTE; 6135811Smarc p->c_cf++; 6232Sbill if (--p->c_cc<=0) { 6335811Smarc bp = cbptr(p->c_cf-1); 6435811Smarc bp = cbptr((int)bp & ~CROUND); 6532Sbill p->c_cf = NULL; 6632Sbill p->c_cl = NULL; 6732Sbill bp->c_next = cfreelist; 6832Sbill cfreelist = bp; 691890Swnj cfreecount += CBSIZE; 701890Swnj if (cwaiting) { 711890Swnj wakeup(&cwaiting); 721890Swnj cwaiting = 0; 731890Swnj } 7432Sbill } else if (((int)p->c_cf & CROUND) == 0){ 7535811Smarc bp = cbptr(p->c_cf); 7632Sbill bp--; 7732Sbill p->c_cf = bp->c_next->c_info; 7832Sbill bp->c_next = cfreelist; 7932Sbill cfreelist = bp; 801890Swnj cfreecount += CBSIZE; 811890Swnj if (cwaiting) { 821890Swnj wakeup(&cwaiting); 831890Swnj cwaiting = 0; 841890Swnj } 8532Sbill } 8632Sbill } 8732Sbill splx(s); 8826279Skarels return (c); 8932Sbill } 9032Sbill 9132Sbill /* 9232Sbill * copy clist to buffer. 9332Sbill * return number of bytes moved. 9432Sbill */ 9532Sbill q_to_b(q, cp, cc) 969761Ssam register struct clist *q; 979761Ssam register char *cp; 9832Sbill { 9932Sbill register struct cblock *bp; 10032Sbill register int s; 10117542Skarels register nc; 10232Sbill char *acp; 10332Sbill 10432Sbill if (cc <= 0) 10526279Skarels return (0); 10617542Skarels s = spltty(); 10732Sbill if (q->c_cc <= 0) { 10832Sbill q->c_cc = 0; 10932Sbill q->c_cf = q->c_cl = NULL; 1101890Swnj splx(s); 11126279Skarels return (0); 11232Sbill } 11332Sbill acp = cp; 11432Sbill 11517542Skarels while (cc) { 11626279Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 11717542Skarels nc = MIN(nc, cc); 11817542Skarels nc = MIN(nc, q->c_cc); 11917542Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 12017542Skarels q->c_cf += nc; 12117542Skarels q->c_cc -= nc; 12217542Skarels cc -= nc; 12317542Skarels cp += nc; 12417542Skarels if (q->c_cc <= 0) { 12535811Smarc bp = cbptr(q->c_cf - 1); 12635811Smarc bp = cbptr((int)bp & ~CROUND); 12732Sbill q->c_cf = q->c_cl = NULL; 12832Sbill bp->c_next = cfreelist; 12932Sbill cfreelist = bp; 1301890Swnj cfreecount += CBSIZE; 1311890Swnj if (cwaiting) { 1321890Swnj wakeup(&cwaiting); 1331890Swnj cwaiting = 0; 1341890Swnj } 13532Sbill break; 13632Sbill } 13732Sbill if (((int)q->c_cf & CROUND) == 0) { 13835811Smarc bp = cbptr(q->c_cf); 13932Sbill bp--; 14032Sbill q->c_cf = bp->c_next->c_info; 14132Sbill bp->c_next = cfreelist; 14232Sbill cfreelist = bp; 1431890Swnj cfreecount += CBSIZE; 1441890Swnj if (cwaiting) { 1451890Swnj wakeup(&cwaiting); 1461890Swnj cwaiting = 0; 1471890Swnj } 14832Sbill } 14932Sbill } 15032Sbill splx(s); 15126279Skarels return (cp-acp); 15232Sbill } 15332Sbill 15432Sbill /* 15532Sbill * Return count of contiguous characters 15632Sbill * in clist starting at q->c_cf. 15732Sbill * Stop counting if flag&character is non-null. 15832Sbill */ 15932Sbill ndqb(q, flag) 1609761Ssam register struct clist *q; 16132Sbill { 1629761Ssam register cc; 1639761Ssam int s; 16432Sbill 16517542Skarels s = spltty(); 16632Sbill if (q->c_cc <= 0) { 16732Sbill cc = -q->c_cc; 16832Sbill goto out; 16932Sbill } 17032Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 17132Sbill cc -= (int)q->c_cf; 17232Sbill if (q->c_cc < cc) 17332Sbill cc = q->c_cc; 17432Sbill if (flag) { 17532Sbill register char *p, *end; 17632Sbill 17732Sbill p = q->c_cf; 17832Sbill end = p; 17932Sbill end += cc; 18032Sbill while (p < end) { 18132Sbill if (*p & flag) { 1821890Swnj cc = (int)p; 1831890Swnj cc -= (int)q->c_cf; 18432Sbill break; 18532Sbill } 18632Sbill p++; 18732Sbill } 18832Sbill } 18932Sbill out: 19032Sbill splx(s); 19126279Skarels return (cc); 19232Sbill } 19332Sbill 19432Sbill /* 1951890Swnj * Flush cc bytes from q. 19632Sbill */ 19732Sbill ndflush(q, cc) 19812754Ssam register struct clist *q; 19912754Ssam register cc; 20032Sbill { 20112754Ssam register struct cblock *bp; 20212754Ssam char *end; 20312754Ssam int rem, s; 20432Sbill 20517542Skarels s = spltty(); 20626279Skarels if (q->c_cc <= 0) 20732Sbill goto out; 2081890Swnj while (cc>0 && q->c_cc) { 20935811Smarc bp = cbptr((int)q->c_cf & ~CROUND); 2101890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 2111890Swnj end = q->c_cl; 2121890Swnj } else { 2131890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 2141890Swnj } 2151890Swnj rem = end - q->c_cf; 2161890Swnj if (cc >= rem) { 2171890Swnj cc -= rem; 2181890Swnj q->c_cc -= rem; 21932Sbill q->c_cf = bp->c_next->c_info; 2201890Swnj bp->c_next = cfreelist; 2211890Swnj cfreelist = bp; 2221890Swnj cfreecount += CBSIZE; 2231890Swnj if (cwaiting) { 2241890Swnj wakeup(&cwaiting); 2251890Swnj cwaiting = 0; 2261890Swnj } 22732Sbill } else { 2281890Swnj q->c_cc -= cc; 2291890Swnj q->c_cf += cc; 2301890Swnj if (q->c_cc <= 0) { 2311890Swnj bp->c_next = cfreelist; 2321890Swnj cfreelist = bp; 2331890Swnj cfreecount += CBSIZE; 2341890Swnj if (cwaiting) { 2351890Swnj wakeup(&cwaiting); 2361890Swnj cwaiting = 0; 2371890Swnj } 2381890Swnj } 2391890Swnj break; 24032Sbill } 2411890Swnj } 2421890Swnj if (q->c_cc <= 0) { 24332Sbill q->c_cf = q->c_cl = NULL; 2441890Swnj q->c_cc = 0; 24532Sbill } 24632Sbill out: 24732Sbill splx(s); 24832Sbill } 249172Sbill 2501890Swnj 25132Sbill putc(c, p) 25212754Ssam register struct clist *p; 25332Sbill { 25432Sbill register struct cblock *bp; 25532Sbill register char *cp; 25632Sbill register s; 25732Sbill 25817542Skarels s = spltty(); 25935811Smarc if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ 26032Sbill if ((bp = cfreelist) == NULL) { 26132Sbill splx(s); 26226279Skarels return (-1); 26332Sbill } 26432Sbill cfreelist = bp->c_next; 2651890Swnj cfreecount -= CBSIZE; 26632Sbill bp->c_next = NULL; 26735811Smarc bzero(bp->c_quote, CBQSIZE); 26832Sbill p->c_cf = cp = bp->c_info; 26932Sbill } else if (((int)cp & CROUND) == 0) { 27035811Smarc bp = cbptr(cp) - 1; /* pointer arith */ 27132Sbill if ((bp->c_next = cfreelist) == NULL) { 27232Sbill splx(s); 27326279Skarels return (-1); 27432Sbill } 27532Sbill bp = bp->c_next; 27632Sbill cfreelist = bp->c_next; 2771890Swnj cfreecount -= CBSIZE; 27832Sbill bp->c_next = NULL; 27932Sbill cp = bp->c_info; 28032Sbill } 28135811Smarc if (c&TTY_QUOTE) 28235811Smarc setquote(cp); 28332Sbill *cp++ = c; 28432Sbill p->c_cc++; 28532Sbill p->c_cl = cp; 28632Sbill splx(s); 28726279Skarels return (0); 28832Sbill } 28932Sbill 29032Sbill /* 29132Sbill * copy buffer to clist. 29232Sbill * return number of bytes not transfered. 29332Sbill */ 29432Sbill b_to_q(cp, cc, q) 29512754Ssam register char *cp; 29612754Ssam struct clist *q; 29712754Ssam register int cc; 29832Sbill { 29932Sbill register char *cq; 30032Sbill register struct cblock *bp; 30117542Skarels register s, nc; 30217542Skarels int acc; 30332Sbill 30432Sbill if (cc <= 0) 30526279Skarels return (0); 30617542Skarels acc = cc; 30717542Skarels s = spltty(); 30817542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 30917542Skarels if ((bp = cfreelist) == NULL) 31017542Skarels goto out; 31117542Skarels cfreelist = bp->c_next; 31217542Skarels cfreecount -= CBSIZE; 31335811Smarc bzero(bp->c_quote, CBQSIZE); 31417542Skarels bp->c_next = NULL; 31517542Skarels q->c_cf = cq = bp->c_info; 31617542Skarels } 31717542Skarels 31817542Skarels while (cc) { 31932Sbill if (((int)cq & CROUND) == 0) { 32035811Smarc bp = cbptr(cq) - 1; 32117542Skarels if ((bp->c_next = cfreelist) == NULL) 32217542Skarels goto out; 32332Sbill bp = bp->c_next; 32432Sbill cfreelist = bp->c_next; 3251890Swnj cfreecount -= CBSIZE; 32635811Smarc bzero(bp->c_quote, CBQSIZE); 32732Sbill bp->c_next = NULL; 32817542Skarels cq = bp->c_info; 32932Sbill } 33026279Skarels nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 33117542Skarels (void) bcopy(cp, cq, (unsigned)nc); 33217542Skarels cp += nc; 33317542Skarels cq += nc; 33417542Skarels cc -= nc; 33532Sbill } 33617542Skarels out: 33717542Skarels q->c_cl = cq; 33817542Skarels q->c_cc += acc - cc; 33917542Skarels splx(s); 34017368Ssam return (cc); 34132Sbill } 34232Sbill 34332Sbill /* 344172Sbill * Given a non-NULL pointter into the list (like c_cf which 345172Sbill * always points to a real character if non-NULL) return the pointer 346172Sbill * to the next character in the list or return NULL if no more chars. 347172Sbill * 348172Sbill * Callers must not allow getc's to happen between nextc's so that the 349172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 350172Sbill */ 351172Sbill char * 35235811Smarc nextc(p, cp, c) 35312754Ssam register struct clist *p; 35412754Ssam register char *cp; 35535811Smarc register int *c; 356172Sbill { 357172Sbill 358172Sbill if (p->c_cc && ++cp != p->c_cl) { 35935811Smarc if (((int)cp & CROUND) == 0) { 36035811Smarc cp = (cbptr(cp))[-1].c_next->c_info; 36135811Smarc } 36235811Smarc *c = *cp; 36335811Smarc if (isquote(cp)) 36435811Smarc *c |= TTY_QUOTE; 365172Sbill return (cp); 366172Sbill } 367172Sbill return (0); 368172Sbill } 369172Sbill 370172Sbill /* 371172Sbill * Remove the last character in the list and return it. 372172Sbill */ 373172Sbill unputc(p) 37412754Ssam register struct clist *p; 375172Sbill { 376172Sbill register struct cblock *bp; 377172Sbill register int c, s; 378172Sbill struct cblock *obp; 379172Sbill 38017542Skarels s = spltty(); 381172Sbill if (p->c_cc <= 0) 382172Sbill c = -1; 383172Sbill else { 384172Sbill c = *--p->c_cl; 38535811Smarc if (isquote(p->c_cl)) 38635811Smarc c |= TTY_QUOTE; 387172Sbill if (--p->c_cc <= 0) { 38835811Smarc bp = cbptr(p->c_cl); 38935811Smarc bp = cbptr((int)bp & ~CROUND); 390172Sbill p->c_cl = p->c_cf = NULL; 391172Sbill bp->c_next = cfreelist; 392172Sbill cfreelist = bp; 3931890Swnj cfreecount += CBSIZE; 39435811Smarc } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { 395172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 39635811Smarc 39735811Smarc bp = cbptr(p->c_cf); 39835811Smarc bp = cbptr((int)bp & ~CROUND); 39935811Smarc while (bp->c_next != cbptr(p->c_cl)) 400172Sbill bp = bp->c_next; 401172Sbill obp = bp; 402172Sbill p->c_cl = (char *)(bp + 1); 403172Sbill bp = bp->c_next; 404172Sbill bp->c_next = cfreelist; 405172Sbill cfreelist = bp; 4061890Swnj cfreecount += CBSIZE; 407172Sbill obp->c_next = NULL; 408172Sbill } 409172Sbill } 410172Sbill splx(s); 411172Sbill return (c); 412172Sbill } 413172Sbill 414172Sbill /* 415172Sbill * Put the chars in the from que 416172Sbill * on the end of the to que. 417172Sbill */ 418172Sbill catq(from, to) 41912754Ssam struct clist *from, *to; 420172Sbill { 42135811Smarc #ifdef notdef 42217542Skarels char bbuf[CBSIZE*4]; 42335811Smarc #endif 42417542Skarels register s, c; 425172Sbill 42617542Skarels s = spltty(); 42717542Skarels if (to->c_cc == 0) { 42817542Skarels *to = *from; 42917542Skarels from->c_cc = 0; 43017542Skarels from->c_cf = NULL; 43117542Skarels from->c_cl = NULL; 43217542Skarels splx(s); 43317542Skarels return; 43417542Skarels } 43517542Skarels splx(s); 43635811Smarc #ifdef notdef 43717542Skarels while (from->c_cc > 0) { 43817542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 43917542Skarels (void) b_to_q(bbuf, c, to); 44017542Skarels } 44135811Smarc #endif 44235811Smarc /* XXX - FIX */ 44335811Smarc while ((c = getc(from)) >= 0) 44435811Smarc putc(c, to); 445172Sbill } 446172Sbill 44717542Skarels #ifdef unneeded 448172Sbill /* 44926279Skarels * Integer (short) get/put using clists. 45032Sbill */ 45117542Skarels typedef u_short word_t; 4529761Ssam 45332Sbill getw(p) 4548955Sroot register struct clist *p; 45532Sbill { 45617542Skarels register int s, c; 45717542Skarels register struct cblock *bp; 45832Sbill 45917542Skarels if (p->c_cc <= 1) 46017542Skarels return(-1); 46117542Skarels if (p->c_cc & 01) { 46217542Skarels c = getc(p); 46333398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 46426279Skarels return (c | (getc(p)<<8)); 46526279Skarels #else 46626279Skarels return (getc(p) | (c<<8)); 46726279Skarels #endif 46817542Skarels } 46917542Skarels s = spltty(); 47035811Smarc #if BYTE_ORDER == LITTLE_ENDIAN 47129947Skarels c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; 47226279Skarels #else 47326279Skarels c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 47426279Skarels #endif 47526279Skarels p->c_cf += sizeof (word_t); 47626279Skarels p->c_cc -= sizeof (word_t); 47717542Skarels if (p->c_cc <= 0) { 47835811Smarc bp = cbptr(p->c_cf-1); 47935811Smarc bp = cbptr((int)bp & ~CROUND); 48017542Skarels p->c_cf = NULL; 48117542Skarels p->c_cl = NULL; 48217542Skarels bp->c_next = cfreelist; 48317542Skarels cfreelist = bp; 48417542Skarels cfreecount += CBSIZE; 48517542Skarels if (cwaiting) { 48617542Skarels wakeup(&cwaiting); 48717542Skarels cwaiting = 0; 48817542Skarels } 48917542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 49035811Smarc bp = cbptr(p->c_cf); 49117542Skarels bp--; 49217542Skarels p->c_cf = bp->c_next->c_info; 49317542Skarels bp->c_next = cfreelist; 49417542Skarels cfreelist = bp; 49517542Skarels cfreecount += CBSIZE; 49617542Skarels if (cwaiting) { 49717542Skarels wakeup(&cwaiting); 49817542Skarels cwaiting = 0; 49917542Skarels } 50017542Skarels } 50117542Skarels splx(s); 50217542Skarels return (c); 50332Sbill } 50432Sbill 50532Sbill putw(c, p) 5068955Sroot register struct clist *p; 50717542Skarels word_t c; 50832Sbill { 50932Sbill register s; 51017542Skarels register struct cblock *bp; 51117542Skarels register char *cp; 51232Sbill 51317542Skarels s = spltty(); 51432Sbill if (cfreelist==NULL) { 51532Sbill splx(s); 51632Sbill return(-1); 51732Sbill } 51817542Skarels if (p->c_cc & 01) { 51933398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 52017542Skarels (void) putc(c, p); 52117542Skarels (void) putc(c>>8, p); 52226279Skarels #else 52326279Skarels (void) putc(c>>8, p); 52426279Skarels (void) putc(c, p); 52526279Skarels #endif 52617542Skarels } else { 52717542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 52817542Skarels if ((bp = cfreelist) == NULL) { 52917542Skarels splx(s); 53017542Skarels return (-1); 53117542Skarels } 53217542Skarels cfreelist = bp->c_next; 53317542Skarels cfreecount -= CBSIZE; 53417542Skarels bp->c_next = NULL; 53517542Skarels p->c_cf = cp = bp->c_info; 53617542Skarels } else if (((int)cp & CROUND) == 0) { 53735811Smarc bp = cbptr(cp) - 1; 53817542Skarels if ((bp->c_next = cfreelist) == NULL) { 53917542Skarels splx(s); 54017542Skarels return (-1); 54117542Skarels } 54217542Skarels bp = bp->c_next; 54317542Skarels cfreelist = bp->c_next; 54417542Skarels cfreecount -= CBSIZE; 54517542Skarels bp->c_next = NULL; 54617542Skarels cp = bp->c_info; 54717542Skarels } 54826279Skarels #if defined(vax) 54917542Skarels *(word_t *)cp = c; 55026279Skarels #else 55126279Skarels ((u_char *)cp)[0] = c>>8; 55226279Skarels ((u_char *)cp)[1] = c; 55326279Skarels #endif 55426279Skarels p->c_cl = cp + sizeof (word_t); 55526279Skarels p->c_cc += sizeof (word_t); 55617542Skarels } 55732Sbill splx(s); 5589761Ssam return (0); 55932Sbill } 56017542Skarels #endif unneeded 561