1*49589Sbostic /*- 2*49589Sbostic * Copyright (c) 1982, 1986 The Regents of the University of California. 3*49589Sbostic * All rights reserved. 423391Smckusick * 5*49589Sbostic * %sccs.include.proprietary.c% 6*49589Sbostic * 7*49589Sbostic * @(#)tty_subr.c 7.7 (Berkeley) 05/09/91 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; 9932Sbill { 10032Sbill register struct cblock *bp; 10132Sbill register int s; 10217542Skarels register 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; 16232Sbill { 1639761Ssam register cc; 1649761Ssam int 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; 20012754Ssam register 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) 25312754Ssam register struct clist *p; 25432Sbill { 25532Sbill register struct cblock *bp; 25632Sbill register char *cp; 25732Sbill register s; 25832Sbill 25917542Skarels s = spltty(); 26035811Smarc if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ 26132Sbill if ((bp = cfreelist) == NULL) { 26232Sbill splx(s); 26326279Skarels return (-1); 26432Sbill } 26532Sbill cfreelist = bp->c_next; 2661890Swnj cfreecount -= CBSIZE; 26732Sbill bp->c_next = NULL; 26835811Smarc bzero(bp->c_quote, CBQSIZE); 26932Sbill p->c_cf = cp = bp->c_info; 27032Sbill } else if (((int)cp & CROUND) == 0) { 27135811Smarc bp = cbptr(cp) - 1; /* pointer arith */ 27232Sbill if ((bp->c_next = cfreelist) == NULL) { 27332Sbill splx(s); 27426279Skarels return (-1); 27532Sbill } 27632Sbill bp = bp->c_next; 27732Sbill cfreelist = bp->c_next; 2781890Swnj cfreecount -= CBSIZE; 27932Sbill bp->c_next = NULL; 28032Sbill cp = bp->c_info; 28132Sbill } 28235811Smarc if (c&TTY_QUOTE) 28335811Smarc setquote(cp); 28432Sbill *cp++ = c; 28532Sbill p->c_cc++; 28632Sbill p->c_cl = cp; 28732Sbill splx(s); 28826279Skarels return (0); 28932Sbill } 29032Sbill 29132Sbill /* 29232Sbill * copy buffer to clist. 29332Sbill * return number of bytes not transfered. 29432Sbill */ 29532Sbill b_to_q(cp, cc, q) 29612754Ssam register char *cp; 29712754Ssam struct clist *q; 29812754Ssam register int cc; 29932Sbill { 30032Sbill register char *cq; 30132Sbill register struct cblock *bp; 30217542Skarels register s, nc; 30317542Skarels int acc; 30432Sbill 30532Sbill if (cc <= 0) 30626279Skarels return (0); 30717542Skarels acc = cc; 30817542Skarels s = spltty(); 30917542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 31017542Skarels if ((bp = cfreelist) == NULL) 31117542Skarels goto out; 31217542Skarels cfreelist = bp->c_next; 31317542Skarels cfreecount -= CBSIZE; 31435811Smarc bzero(bp->c_quote, CBQSIZE); 31517542Skarels bp->c_next = NULL; 31617542Skarels q->c_cf = cq = bp->c_info; 31717542Skarels } 31817542Skarels 31917542Skarels while (cc) { 32032Sbill if (((int)cq & CROUND) == 0) { 32135811Smarc bp = cbptr(cq) - 1; 32217542Skarels if ((bp->c_next = cfreelist) == NULL) 32317542Skarels goto out; 32432Sbill bp = bp->c_next; 32532Sbill cfreelist = bp->c_next; 3261890Swnj cfreecount -= CBSIZE; 32735811Smarc bzero(bp->c_quote, CBQSIZE); 32832Sbill bp->c_next = NULL; 32917542Skarels cq = bp->c_info; 33032Sbill } 33126279Skarels nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 33217542Skarels (void) bcopy(cp, cq, (unsigned)nc); 33317542Skarels cp += nc; 33417542Skarels cq += nc; 33517542Skarels cc -= nc; 33632Sbill } 33717542Skarels out: 33817542Skarels q->c_cl = cq; 33917542Skarels q->c_cc += acc - cc; 34017542Skarels splx(s); 34117368Ssam return (cc); 34232Sbill } 34332Sbill 34432Sbill /* 345172Sbill * Given a non-NULL pointter into the list (like c_cf which 346172Sbill * always points to a real character if non-NULL) return the pointer 347172Sbill * to the next character in the list or return NULL if no more chars. 348172Sbill * 349172Sbill * Callers must not allow getc's to happen between nextc's so that the 350172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 351172Sbill */ 352172Sbill char * 35335811Smarc nextc(p, cp, c) 35412754Ssam register struct clist *p; 35512754Ssam register char *cp; 35635811Smarc register int *c; 357172Sbill { 358172Sbill 359172Sbill if (p->c_cc && ++cp != p->c_cl) { 36035811Smarc if (((int)cp & CROUND) == 0) { 36135811Smarc cp = (cbptr(cp))[-1].c_next->c_info; 36235811Smarc } 36335811Smarc *c = *cp; 36435811Smarc if (isquote(cp)) 36535811Smarc *c |= TTY_QUOTE; 366172Sbill return (cp); 367172Sbill } 368172Sbill return (0); 369172Sbill } 370172Sbill 371172Sbill /* 372172Sbill * Remove the last character in the list and return it. 373172Sbill */ 374172Sbill unputc(p) 37512754Ssam register struct clist *p; 376172Sbill { 377172Sbill register struct cblock *bp; 378172Sbill register int c, s; 379172Sbill struct cblock *obp; 380172Sbill 38117542Skarels s = spltty(); 382172Sbill if (p->c_cc <= 0) 383172Sbill c = -1; 384172Sbill else { 385172Sbill c = *--p->c_cl; 38635811Smarc if (isquote(p->c_cl)) 38735811Smarc c |= TTY_QUOTE; 388172Sbill if (--p->c_cc <= 0) { 38935811Smarc bp = cbptr(p->c_cl); 39035811Smarc bp = cbptr((int)bp & ~CROUND); 391172Sbill p->c_cl = p->c_cf = NULL; 392172Sbill bp->c_next = cfreelist; 393172Sbill cfreelist = bp; 3941890Swnj cfreecount += CBSIZE; 39535811Smarc } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { 396172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 39735811Smarc 39835811Smarc bp = cbptr(p->c_cf); 39935811Smarc bp = cbptr((int)bp & ~CROUND); 40035811Smarc while (bp->c_next != cbptr(p->c_cl)) 401172Sbill bp = bp->c_next; 402172Sbill obp = bp; 403172Sbill p->c_cl = (char *)(bp + 1); 404172Sbill bp = bp->c_next; 405172Sbill bp->c_next = cfreelist; 406172Sbill cfreelist = bp; 4071890Swnj cfreecount += CBSIZE; 408172Sbill obp->c_next = NULL; 409172Sbill } 410172Sbill } 411172Sbill splx(s); 412172Sbill return (c); 413172Sbill } 414172Sbill 415172Sbill /* 416172Sbill * Put the chars in the from que 417172Sbill * on the end of the to que. 418172Sbill */ 419172Sbill catq(from, to) 42012754Ssam struct clist *from, *to; 421172Sbill { 42235811Smarc #ifdef notdef 42317542Skarels char bbuf[CBSIZE*4]; 42435811Smarc #endif 42517542Skarels register s, c; 426172Sbill 42717542Skarels s = spltty(); 42817542Skarels if (to->c_cc == 0) { 42917542Skarels *to = *from; 43017542Skarels from->c_cc = 0; 43117542Skarels from->c_cf = NULL; 43217542Skarels from->c_cl = NULL; 43317542Skarels splx(s); 43417542Skarels return; 43517542Skarels } 43617542Skarels splx(s); 43735811Smarc #ifdef notdef 43817542Skarels while (from->c_cc > 0) { 43917542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 44017542Skarels (void) b_to_q(bbuf, c, to); 44117542Skarels } 44235811Smarc #endif 44335811Smarc /* XXX - FIX */ 44435811Smarc while ((c = getc(from)) >= 0) 44535811Smarc putc(c, to); 446172Sbill } 447172Sbill 44817542Skarels #ifdef unneeded 449172Sbill /* 45026279Skarels * Integer (short) get/put using clists. 45132Sbill */ 45217542Skarels typedef u_short word_t; 4539761Ssam 45432Sbill getw(p) 4558955Sroot register struct clist *p; 45632Sbill { 45717542Skarels register int s, c; 45817542Skarels register struct cblock *bp; 45932Sbill 46017542Skarels if (p->c_cc <= 1) 46117542Skarels return(-1); 46217542Skarels if (p->c_cc & 01) { 46317542Skarels c = getc(p); 46433398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 46526279Skarels return (c | (getc(p)<<8)); 46626279Skarels #else 46726279Skarels return (getc(p) | (c<<8)); 46826279Skarels #endif 46917542Skarels } 47017542Skarels s = spltty(); 47135811Smarc #if BYTE_ORDER == LITTLE_ENDIAN 47229947Skarels c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; 47326279Skarels #else 47426279Skarels c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 47526279Skarels #endif 47626279Skarels p->c_cf += sizeof (word_t); 47726279Skarels p->c_cc -= sizeof (word_t); 47817542Skarels if (p->c_cc <= 0) { 47935811Smarc bp = cbptr(p->c_cf-1); 48035811Smarc bp = cbptr((int)bp & ~CROUND); 48117542Skarels p->c_cf = NULL; 48217542Skarels p->c_cl = NULL; 48317542Skarels bp->c_next = cfreelist; 48417542Skarels cfreelist = bp; 48517542Skarels cfreecount += CBSIZE; 48617542Skarels if (cwaiting) { 48717542Skarels wakeup(&cwaiting); 48817542Skarels cwaiting = 0; 48917542Skarels } 49017542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 49135811Smarc bp = cbptr(p->c_cf); 49217542Skarels bp--; 49317542Skarels p->c_cf = bp->c_next->c_info; 49417542Skarels bp->c_next = cfreelist; 49517542Skarels cfreelist = bp; 49617542Skarels cfreecount += CBSIZE; 49717542Skarels if (cwaiting) { 49817542Skarels wakeup(&cwaiting); 49917542Skarels cwaiting = 0; 50017542Skarels } 50117542Skarels } 50217542Skarels splx(s); 50317542Skarels return (c); 50432Sbill } 50532Sbill 50632Sbill putw(c, p) 5078955Sroot register struct clist *p; 50817542Skarels word_t c; 50932Sbill { 51032Sbill register s; 51117542Skarels register struct cblock *bp; 51217542Skarels register char *cp; 51332Sbill 51417542Skarels s = spltty(); 51532Sbill if (cfreelist==NULL) { 51632Sbill splx(s); 51732Sbill return(-1); 51832Sbill } 51917542Skarels if (p->c_cc & 01) { 52033398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 52117542Skarels (void) putc(c, p); 52217542Skarels (void) putc(c>>8, p); 52326279Skarels #else 52426279Skarels (void) putc(c>>8, p); 52526279Skarels (void) putc(c, p); 52626279Skarels #endif 52717542Skarels } else { 52817542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 52917542Skarels if ((bp = cfreelist) == NULL) { 53017542Skarels splx(s); 53117542Skarels return (-1); 53217542Skarels } 53317542Skarels cfreelist = bp->c_next; 53417542Skarels cfreecount -= CBSIZE; 53517542Skarels bp->c_next = NULL; 53617542Skarels p->c_cf = cp = bp->c_info; 53717542Skarels } else if (((int)cp & CROUND) == 0) { 53835811Smarc bp = cbptr(cp) - 1; 53917542Skarels if ((bp->c_next = cfreelist) == NULL) { 54017542Skarels splx(s); 54117542Skarels return (-1); 54217542Skarels } 54317542Skarels bp = bp->c_next; 54417542Skarels cfreelist = bp->c_next; 54517542Skarels cfreecount -= CBSIZE; 54617542Skarels bp->c_next = NULL; 54717542Skarels cp = bp->c_info; 54817542Skarels } 54926279Skarels #if defined(vax) 55017542Skarels *(word_t *)cp = c; 55126279Skarels #else 55226279Skarels ((u_char *)cp)[0] = c>>8; 55326279Skarels ((u_char *)cp)[1] = c; 55426279Skarels #endif 55526279Skarels p->c_cl = cp + sizeof (word_t); 55626279Skarels p->c_cc += sizeof (word_t); 55717542Skarels } 55832Sbill splx(s); 5599761Ssam return (0); 56032Sbill } 56117542Skarels #endif unneeded 562