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*35811Smarc * @(#)tty_subr.c 7.4 (Berkeley) 10/18/88 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 18*35811Smarc #define setquote(cp) \ 19*35811Smarc setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 20*35811Smarc (int)(cp)&CROUND) 21*35811Smarc #define isquote(cp) \ 22*35811Smarc isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 23*35811Smarc (int)(cp)&CROUND) 24*35811Smarc #define cbptr(x) ((struct cblock *)(x)) 25*35811Smarc 2632Sbill /* 2732Sbill * Character list get/put 2832Sbill */ 2932Sbill getc(p) 3012754Ssam register struct clist *p; 3132Sbill { 3232Sbill register struct cblock *bp; 3332Sbill register int c, s; 3432Sbill 3517542Skarels s = spltty(); 3632Sbill if (p->c_cc <= 0) { 3732Sbill c = -1; 3832Sbill p->c_cc = 0; 3932Sbill p->c_cf = p->c_cl = NULL; 4032Sbill } else { 41*35811Smarc c = *p->c_cf & 0377; 42*35811Smarc if (isquote(p->c_cf)) 43*35811Smarc c |= TTY_QUOTE; 44*35811Smarc p->c_cf++; 4532Sbill if (--p->c_cc<=0) { 46*35811Smarc bp = cbptr(p->c_cf-1); 47*35811Smarc bp = cbptr((int)bp & ~CROUND); 4832Sbill p->c_cf = NULL; 4932Sbill p->c_cl = NULL; 5032Sbill bp->c_next = cfreelist; 5132Sbill cfreelist = bp; 521890Swnj cfreecount += CBSIZE; 531890Swnj if (cwaiting) { 541890Swnj wakeup(&cwaiting); 551890Swnj cwaiting = 0; 561890Swnj } 5732Sbill } else if (((int)p->c_cf & CROUND) == 0){ 58*35811Smarc bp = cbptr(p->c_cf); 5932Sbill bp--; 6032Sbill p->c_cf = bp->c_next->c_info; 6132Sbill bp->c_next = cfreelist; 6232Sbill cfreelist = bp; 631890Swnj cfreecount += CBSIZE; 641890Swnj if (cwaiting) { 651890Swnj wakeup(&cwaiting); 661890Swnj cwaiting = 0; 671890Swnj } 6832Sbill } 6932Sbill } 7032Sbill splx(s); 7126279Skarels return (c); 7232Sbill } 7332Sbill 7432Sbill /* 7532Sbill * copy clist to buffer. 7632Sbill * return number of bytes moved. 7732Sbill */ 7832Sbill q_to_b(q, cp, cc) 799761Ssam register struct clist *q; 809761Ssam register char *cp; 8132Sbill { 8232Sbill register struct cblock *bp; 8332Sbill register int s; 8417542Skarels register nc; 8532Sbill char *acp; 8632Sbill 8732Sbill if (cc <= 0) 8826279Skarels return (0); 8917542Skarels s = spltty(); 9032Sbill if (q->c_cc <= 0) { 9132Sbill q->c_cc = 0; 9232Sbill q->c_cf = q->c_cl = NULL; 931890Swnj splx(s); 9426279Skarels return (0); 9532Sbill } 9632Sbill acp = cp; 9732Sbill 9817542Skarels while (cc) { 9926279Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 10017542Skarels nc = MIN(nc, cc); 10117542Skarels nc = MIN(nc, q->c_cc); 10217542Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 10317542Skarels q->c_cf += nc; 10417542Skarels q->c_cc -= nc; 10517542Skarels cc -= nc; 10617542Skarels cp += nc; 10717542Skarels if (q->c_cc <= 0) { 108*35811Smarc bp = cbptr(q->c_cf - 1); 109*35811Smarc bp = cbptr((int)bp & ~CROUND); 11032Sbill q->c_cf = q->c_cl = NULL; 11132Sbill bp->c_next = cfreelist; 11232Sbill cfreelist = bp; 1131890Swnj cfreecount += CBSIZE; 1141890Swnj if (cwaiting) { 1151890Swnj wakeup(&cwaiting); 1161890Swnj cwaiting = 0; 1171890Swnj } 11832Sbill break; 11932Sbill } 12032Sbill if (((int)q->c_cf & CROUND) == 0) { 121*35811Smarc bp = cbptr(q->c_cf); 12232Sbill bp--; 12332Sbill q->c_cf = bp->c_next->c_info; 12432Sbill bp->c_next = cfreelist; 12532Sbill cfreelist = bp; 1261890Swnj cfreecount += CBSIZE; 1271890Swnj if (cwaiting) { 1281890Swnj wakeup(&cwaiting); 1291890Swnj cwaiting = 0; 1301890Swnj } 13132Sbill } 13232Sbill } 13332Sbill splx(s); 13426279Skarels return (cp-acp); 13532Sbill } 13632Sbill 13732Sbill /* 13832Sbill * Return count of contiguous characters 13932Sbill * in clist starting at q->c_cf. 14032Sbill * Stop counting if flag&character is non-null. 14132Sbill */ 14232Sbill ndqb(q, flag) 1439761Ssam register struct clist *q; 14432Sbill { 1459761Ssam register cc; 1469761Ssam int s; 14732Sbill 14817542Skarels s = spltty(); 14932Sbill if (q->c_cc <= 0) { 15032Sbill cc = -q->c_cc; 15132Sbill goto out; 15232Sbill } 15332Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 15432Sbill cc -= (int)q->c_cf; 15532Sbill if (q->c_cc < cc) 15632Sbill cc = q->c_cc; 15732Sbill if (flag) { 15832Sbill register char *p, *end; 15932Sbill 16032Sbill p = q->c_cf; 16132Sbill end = p; 16232Sbill end += cc; 16332Sbill while (p < end) { 16432Sbill if (*p & flag) { 1651890Swnj cc = (int)p; 1661890Swnj cc -= (int)q->c_cf; 16732Sbill break; 16832Sbill } 16932Sbill p++; 17032Sbill } 17132Sbill } 17232Sbill out: 17332Sbill splx(s); 17426279Skarels return (cc); 17532Sbill } 17632Sbill 17732Sbill /* 1781890Swnj * Flush cc bytes from q. 17932Sbill */ 18032Sbill ndflush(q, cc) 18112754Ssam register struct clist *q; 18212754Ssam register cc; 18332Sbill { 18412754Ssam register struct cblock *bp; 18512754Ssam char *end; 18612754Ssam int rem, s; 18732Sbill 18817542Skarels s = spltty(); 18926279Skarels if (q->c_cc <= 0) 19032Sbill goto out; 1911890Swnj while (cc>0 && q->c_cc) { 192*35811Smarc bp = cbptr((int)q->c_cf & ~CROUND); 1931890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1941890Swnj end = q->c_cl; 1951890Swnj } else { 1961890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1971890Swnj } 1981890Swnj rem = end - q->c_cf; 1991890Swnj if (cc >= rem) { 2001890Swnj cc -= rem; 2011890Swnj q->c_cc -= rem; 20232Sbill q->c_cf = bp->c_next->c_info; 2031890Swnj bp->c_next = cfreelist; 2041890Swnj cfreelist = bp; 2051890Swnj cfreecount += CBSIZE; 2061890Swnj if (cwaiting) { 2071890Swnj wakeup(&cwaiting); 2081890Swnj cwaiting = 0; 2091890Swnj } 21032Sbill } else { 2111890Swnj q->c_cc -= cc; 2121890Swnj q->c_cf += cc; 2131890Swnj if (q->c_cc <= 0) { 2141890Swnj bp->c_next = cfreelist; 2151890Swnj cfreelist = bp; 2161890Swnj cfreecount += CBSIZE; 2171890Swnj if (cwaiting) { 2181890Swnj wakeup(&cwaiting); 2191890Swnj cwaiting = 0; 2201890Swnj } 2211890Swnj } 2221890Swnj break; 22332Sbill } 2241890Swnj } 2251890Swnj if (q->c_cc <= 0) { 22632Sbill q->c_cf = q->c_cl = NULL; 2271890Swnj q->c_cc = 0; 22832Sbill } 22932Sbill out: 23032Sbill splx(s); 23132Sbill } 232172Sbill 2331890Swnj 23432Sbill putc(c, p) 23512754Ssam register struct clist *p; 23632Sbill { 23732Sbill register struct cblock *bp; 23832Sbill register char *cp; 23932Sbill register s; 24032Sbill 24117542Skarels s = spltty(); 242*35811Smarc if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ 24332Sbill if ((bp = cfreelist) == NULL) { 24432Sbill splx(s); 24526279Skarels return (-1); 24632Sbill } 24732Sbill cfreelist = bp->c_next; 2481890Swnj cfreecount -= CBSIZE; 24932Sbill bp->c_next = NULL; 250*35811Smarc bzero(bp->c_quote, CBQSIZE); 25132Sbill p->c_cf = cp = bp->c_info; 25232Sbill } else if (((int)cp & CROUND) == 0) { 253*35811Smarc bp = cbptr(cp) - 1; /* pointer arith */ 25432Sbill if ((bp->c_next = cfreelist) == NULL) { 25532Sbill splx(s); 25626279Skarels return (-1); 25732Sbill } 25832Sbill bp = bp->c_next; 25932Sbill cfreelist = bp->c_next; 2601890Swnj cfreecount -= CBSIZE; 26132Sbill bp->c_next = NULL; 26232Sbill cp = bp->c_info; 26332Sbill } 264*35811Smarc if (c&TTY_QUOTE) 265*35811Smarc setquote(cp); 26632Sbill *cp++ = c; 26732Sbill p->c_cc++; 26832Sbill p->c_cl = cp; 26932Sbill splx(s); 27026279Skarels return (0); 27132Sbill } 27232Sbill 27332Sbill /* 27432Sbill * copy buffer to clist. 27532Sbill * return number of bytes not transfered. 27632Sbill */ 27732Sbill b_to_q(cp, cc, q) 27812754Ssam register char *cp; 27912754Ssam struct clist *q; 28012754Ssam register int cc; 28132Sbill { 28232Sbill register char *cq; 28332Sbill register struct cblock *bp; 28417542Skarels register s, nc; 28517542Skarels int acc; 28632Sbill 28732Sbill if (cc <= 0) 28826279Skarels return (0); 28917542Skarels acc = cc; 29017542Skarels s = spltty(); 29117542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 29217542Skarels if ((bp = cfreelist) == NULL) 29317542Skarels goto out; 29417542Skarels cfreelist = bp->c_next; 29517542Skarels cfreecount -= CBSIZE; 296*35811Smarc bzero(bp->c_quote, CBQSIZE); 29717542Skarels bp->c_next = NULL; 29817542Skarels q->c_cf = cq = bp->c_info; 29917542Skarels } 30017542Skarels 30117542Skarels while (cc) { 30232Sbill if (((int)cq & CROUND) == 0) { 303*35811Smarc bp = cbptr(cq) - 1; 30417542Skarels if ((bp->c_next = cfreelist) == NULL) 30517542Skarels goto out; 30632Sbill bp = bp->c_next; 30732Sbill cfreelist = bp->c_next; 3081890Swnj cfreecount -= CBSIZE; 309*35811Smarc bzero(bp->c_quote, CBQSIZE); 31032Sbill bp->c_next = NULL; 31117542Skarels cq = bp->c_info; 31232Sbill } 31326279Skarels nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 31417542Skarels (void) bcopy(cp, cq, (unsigned)nc); 31517542Skarels cp += nc; 31617542Skarels cq += nc; 31717542Skarels cc -= nc; 31832Sbill } 31917542Skarels out: 32017542Skarels q->c_cl = cq; 32117542Skarels q->c_cc += acc - cc; 32217542Skarels splx(s); 32317368Ssam return (cc); 32432Sbill } 32532Sbill 32632Sbill /* 327172Sbill * Given a non-NULL pointter into the list (like c_cf which 328172Sbill * always points to a real character if non-NULL) return the pointer 329172Sbill * to the next character in the list or return NULL if no more chars. 330172Sbill * 331172Sbill * Callers must not allow getc's to happen between nextc's so that the 332172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 333172Sbill */ 334172Sbill char * 335*35811Smarc nextc(p, cp, c) 33612754Ssam register struct clist *p; 33712754Ssam register char *cp; 338*35811Smarc register int *c; 339172Sbill { 340172Sbill 341172Sbill if (p->c_cc && ++cp != p->c_cl) { 342*35811Smarc if (((int)cp & CROUND) == 0) { 343*35811Smarc cp = (cbptr(cp))[-1].c_next->c_info; 344*35811Smarc } 345*35811Smarc *c = *cp; 346*35811Smarc if (isquote(cp)) 347*35811Smarc *c |= TTY_QUOTE; 348172Sbill return (cp); 349172Sbill } 350172Sbill return (0); 351172Sbill } 352172Sbill 353172Sbill /* 354172Sbill * Remove the last character in the list and return it. 355172Sbill */ 356172Sbill unputc(p) 35712754Ssam register struct clist *p; 358172Sbill { 359172Sbill register struct cblock *bp; 360172Sbill register int c, s; 361172Sbill struct cblock *obp; 362*35811Smarc register int first = 1; 363172Sbill 36417542Skarels s = spltty(); 365172Sbill if (p->c_cc <= 0) 366172Sbill c = -1; 367172Sbill else { 368172Sbill c = *--p->c_cl; 369*35811Smarc if (isquote(p->c_cl)) 370*35811Smarc c |= TTY_QUOTE; 371172Sbill if (--p->c_cc <= 0) { 372*35811Smarc bp = cbptr(p->c_cl); 373*35811Smarc bp = cbptr((int)bp & ~CROUND); 374172Sbill p->c_cl = p->c_cf = NULL; 375172Sbill bp->c_next = cfreelist; 376172Sbill cfreelist = bp; 3771890Swnj cfreecount += CBSIZE; 378*35811Smarc } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { 379172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 380*35811Smarc 381*35811Smarc bp = cbptr(p->c_cf); 382*35811Smarc bp = cbptr((int)bp & ~CROUND); 383*35811Smarc while (bp->c_next != cbptr(p->c_cl)) 384172Sbill bp = bp->c_next; 385172Sbill obp = bp; 386172Sbill p->c_cl = (char *)(bp + 1); 387172Sbill bp = bp->c_next; 388172Sbill bp->c_next = cfreelist; 389172Sbill cfreelist = bp; 3901890Swnj cfreecount += CBSIZE; 391172Sbill obp->c_next = NULL; 392172Sbill } 393172Sbill } 394172Sbill splx(s); 395172Sbill return (c); 396172Sbill } 397172Sbill 398172Sbill /* 399172Sbill * Put the chars in the from que 400172Sbill * on the end of the to que. 401172Sbill */ 402172Sbill catq(from, to) 40312754Ssam struct clist *from, *to; 404172Sbill { 405*35811Smarc #ifdef notdef 40617542Skarels char bbuf[CBSIZE*4]; 407*35811Smarc #endif 40817542Skarels register s, c; 409172Sbill 41017542Skarels s = spltty(); 41117542Skarels if (to->c_cc == 0) { 41217542Skarels *to = *from; 41317542Skarels from->c_cc = 0; 41417542Skarels from->c_cf = NULL; 41517542Skarels from->c_cl = NULL; 41617542Skarels splx(s); 41717542Skarels return; 41817542Skarels } 41917542Skarels splx(s); 420*35811Smarc #ifdef notdef 42117542Skarels while (from->c_cc > 0) { 42217542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 42317542Skarels (void) b_to_q(bbuf, c, to); 42417542Skarels } 425*35811Smarc #endif 426*35811Smarc /* XXX - FIX */ 427*35811Smarc while ((c = getc(from)) >= 0) 428*35811Smarc putc(c, to); 429172Sbill } 430172Sbill 43117542Skarels #ifdef unneeded 432172Sbill /* 43326279Skarels * Integer (short) get/put using clists. 43432Sbill */ 43517542Skarels typedef u_short word_t; 4369761Ssam 43732Sbill getw(p) 4388955Sroot register struct clist *p; 43932Sbill { 44017542Skarels register int s, c; 44117542Skarels register struct cblock *bp; 44232Sbill 44317542Skarels if (p->c_cc <= 1) 44417542Skarels return(-1); 44517542Skarels if (p->c_cc & 01) { 44617542Skarels c = getc(p); 44733398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 44826279Skarels return (c | (getc(p)<<8)); 44926279Skarels #else 45026279Skarels return (getc(p) | (c<<8)); 45126279Skarels #endif 45217542Skarels } 45317542Skarels s = spltty(); 454*35811Smarc #if BYTE_ORDER == LITTLE_ENDIAN 45529947Skarels c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; 45626279Skarels #else 45726279Skarels c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 45826279Skarels #endif 45926279Skarels p->c_cf += sizeof (word_t); 46026279Skarels p->c_cc -= sizeof (word_t); 46117542Skarels if (p->c_cc <= 0) { 462*35811Smarc bp = cbptr(p->c_cf-1); 463*35811Smarc bp = cbptr((int)bp & ~CROUND); 46417542Skarels p->c_cf = NULL; 46517542Skarels p->c_cl = NULL; 46617542Skarels bp->c_next = cfreelist; 46717542Skarels cfreelist = bp; 46817542Skarels cfreecount += CBSIZE; 46917542Skarels if (cwaiting) { 47017542Skarels wakeup(&cwaiting); 47117542Skarels cwaiting = 0; 47217542Skarels } 47317542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 474*35811Smarc bp = cbptr(p->c_cf); 47517542Skarels bp--; 47617542Skarels p->c_cf = bp->c_next->c_info; 47717542Skarels bp->c_next = cfreelist; 47817542Skarels cfreelist = bp; 47917542Skarels cfreecount += CBSIZE; 48017542Skarels if (cwaiting) { 48117542Skarels wakeup(&cwaiting); 48217542Skarels cwaiting = 0; 48317542Skarels } 48417542Skarels } 48517542Skarels splx(s); 48617542Skarels return (c); 48732Sbill } 48832Sbill 48932Sbill putw(c, p) 4908955Sroot register struct clist *p; 49117542Skarels word_t c; 49232Sbill { 49332Sbill register s; 49417542Skarels register struct cblock *bp; 49517542Skarels register char *cp; 49632Sbill 49717542Skarels s = spltty(); 49832Sbill if (cfreelist==NULL) { 49932Sbill splx(s); 50032Sbill return(-1); 50132Sbill } 50217542Skarels if (p->c_cc & 01) { 50333398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 50417542Skarels (void) putc(c, p); 50517542Skarels (void) putc(c>>8, p); 50626279Skarels #else 50726279Skarels (void) putc(c>>8, p); 50826279Skarels (void) putc(c, p); 50926279Skarels #endif 51017542Skarels } else { 51117542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 51217542Skarels if ((bp = cfreelist) == NULL) { 51317542Skarels splx(s); 51417542Skarels return (-1); 51517542Skarels } 51617542Skarels cfreelist = bp->c_next; 51717542Skarels cfreecount -= CBSIZE; 51817542Skarels bp->c_next = NULL; 51917542Skarels p->c_cf = cp = bp->c_info; 52017542Skarels } else if (((int)cp & CROUND) == 0) { 521*35811Smarc bp = cbptr(cp) - 1; 52217542Skarels if ((bp->c_next = cfreelist) == NULL) { 52317542Skarels splx(s); 52417542Skarels return (-1); 52517542Skarels } 52617542Skarels bp = bp->c_next; 52717542Skarels cfreelist = bp->c_next; 52817542Skarels cfreecount -= CBSIZE; 52917542Skarels bp->c_next = NULL; 53017542Skarels cp = bp->c_info; 53117542Skarels } 53226279Skarels #if defined(vax) 53317542Skarels *(word_t *)cp = c; 53426279Skarels #else 53526279Skarels ((u_char *)cp)[0] = c>>8; 53626279Skarels ((u_char *)cp)[1] = c; 53726279Skarels #endif 53826279Skarels p->c_cl = cp + sizeof (word_t); 53926279Skarels p->c_cc += sizeof (word_t); 54017542Skarels } 54132Sbill splx(s); 5429761Ssam return (0); 54332Sbill } 54417542Skarels #endif unneeded 545