xref: /csrg-svn/sys/kern/tty_subr.c (revision 35811)
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