must include proc before tty.h and socketvar.h
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
5dc2581e
KB
1/*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
da7c5cc6 6 *
063b2136 7 * @(#)tty_subr.c 7.9 (Berkeley) %G%
da7c5cc6 8 */
8f6119af 9
94368568
JB
10#include "param.h"
11#include "systm.h"
94368568 12#include "buf.h"
3358b36b 13#include "ioctl.h"
063b2136 14#include "proc.h"
94368568
JB
15#include "tty.h"
16#include "clist.h"
11bd398c 17
48575cec 18char cwaiting;
11bd398c 19
e39f9ea6
MT
20#define setquote(cp) \
21 setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
22 (int)(cp)&CROUND)
23#define isquote(cp) \
24 isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
25 (int)(cp)&CROUND)
26#define cbptr(x) ((struct cblock *)(x))
27
3789a403
MK
28/*
29 * Initialize clist by freeing all character blocks.
30 */
31cinit()
32{
33 register int ccp;
34 register struct cblock *cp;
35
36 ccp = (int) cfree;
37 ccp = (ccp + CROUND) & ~CROUND;
38 for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) {
39 cp->c_next = cfreelist;
40 cfreelist = cp;
41 cfreecount += CBSIZE;
42 }
43}
44
11bd398c
BJ
45/*
46 * Character list get/put
47 */
48getc(p)
88a7a62a 49 register struct clist *p;
11bd398c
BJ
50{
51 register struct cblock *bp;
52 register int c, s;
53
a8170d5d 54 s = spltty();
11bd398c
BJ
55 if (p->c_cc <= 0) {
56 c = -1;
57 p->c_cc = 0;
58 p->c_cf = p->c_cl = NULL;
59 } else {
e39f9ea6
MT
60 c = *p->c_cf & 0377;
61 if (isquote(p->c_cf))
62 c |= TTY_QUOTE;
63 p->c_cf++;
11bd398c 64 if (--p->c_cc<=0) {
e39f9ea6
MT
65 bp = cbptr(p->c_cf-1);
66 bp = cbptr((int)bp & ~CROUND);
11bd398c
BJ
67 p->c_cf = NULL;
68 p->c_cl = NULL;
69 bp->c_next = cfreelist;
70 cfreelist = bp;
48575cec
BJ
71 cfreecount += CBSIZE;
72 if (cwaiting) {
73 wakeup(&cwaiting);
74 cwaiting = 0;
75 }
11bd398c 76 } else if (((int)p->c_cf & CROUND) == 0){
e39f9ea6 77 bp = cbptr(p->c_cf);
11bd398c
BJ
78 bp--;
79 p->c_cf = bp->c_next->c_info;
80 bp->c_next = cfreelist;
81 cfreelist = bp;
48575cec
BJ
82 cfreecount += CBSIZE;
83 if (cwaiting) {
84 wakeup(&cwaiting);
85 cwaiting = 0;
86 }
11bd398c
BJ
87 }
88 }
89 splx(s);
01b0e233 90 return (c);
11bd398c
BJ
91}
92
93/*
94 * copy clist to buffer.
95 * return number of bytes moved.
96 */
97q_to_b(q, cp, cc)
961945a8
SL
98 register struct clist *q;
99 register char *cp;
fd402d46 100 int cc;
11bd398c
BJ
101{
102 register struct cblock *bp;
fd402d46 103 register int s, nc;
11bd398c
BJ
104 char *acp;
105
106 if (cc <= 0)
01b0e233 107 return (0);
a8170d5d 108 s = spltty();
11bd398c
BJ
109 if (q->c_cc <= 0) {
110 q->c_cc = 0;
111 q->c_cf = q->c_cl = NULL;
48575cec 112 splx(s);
01b0e233 113 return (0);
11bd398c
BJ
114 }
115 acp = cp;
11bd398c 116
a8170d5d 117 while (cc) {
01b0e233 118 nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
a8170d5d
MK
119 nc = MIN(nc, cc);
120 nc = MIN(nc, q->c_cc);
121 (void) bcopy(q->c_cf, cp, (unsigned)nc);
122 q->c_cf += nc;
123 q->c_cc -= nc;
124 cc -= nc;
125 cp += nc;
126 if (q->c_cc <= 0) {
e39f9ea6
MT
127 bp = cbptr(q->c_cf - 1);
128 bp = cbptr((int)bp & ~CROUND);
11bd398c
BJ
129 q->c_cf = q->c_cl = NULL;
130 bp->c_next = cfreelist;
131 cfreelist = bp;
48575cec
BJ
132 cfreecount += CBSIZE;
133 if (cwaiting) {
134 wakeup(&cwaiting);
135 cwaiting = 0;
136 }
11bd398c
BJ
137 break;
138 }
139 if (((int)q->c_cf & CROUND) == 0) {
e39f9ea6 140 bp = cbptr(q->c_cf);
11bd398c
BJ
141 bp--;
142 q->c_cf = bp->c_next->c_info;
143 bp->c_next = cfreelist;
144 cfreelist = bp;
48575cec
BJ
145 cfreecount += CBSIZE;
146 if (cwaiting) {
147 wakeup(&cwaiting);
148 cwaiting = 0;
149 }
11bd398c
BJ
150 }
151 }
152 splx(s);
01b0e233 153 return (cp-acp);
11bd398c
BJ
154}
155
11bd398c
BJ
156/*
157 * Return count of contiguous characters
158 * in clist starting at q->c_cf.
159 * Stop counting if flag&character is non-null.
160 */
161ndqb(q, flag)
961945a8 162 register struct clist *q;
fd402d46 163 int flag;
11bd398c 164{
fd402d46 165 register int cc, s;
11bd398c 166
a8170d5d 167 s = spltty();
11bd398c
BJ
168 if (q->c_cc <= 0) {
169 cc = -q->c_cc;
170 goto out;
171 }
172 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
173 cc -= (int)q->c_cf;
174 if (q->c_cc < cc)
175 cc = q->c_cc;
176 if (flag) {
177 register char *p, *end;
178
179 p = q->c_cf;
180 end = p;
181 end += cc;
182 while (p < end) {
183 if (*p & flag) {
48575cec
BJ
184 cc = (int)p;
185 cc -= (int)q->c_cf;
11bd398c
BJ
186 break;
187 }
188 p++;
189 }
190 }
191out:
192 splx(s);
01b0e233 193 return (cc);
11bd398c
BJ
194}
195
11bd398c 196/*
48575cec 197 * Flush cc bytes from q.
11bd398c
BJ
198 */
199ndflush(q, cc)
88a7a62a 200 register struct clist *q;
fd402d46 201 register int cc;
11bd398c 202{
88a7a62a
SL
203 register struct cblock *bp;
204 char *end;
205 int rem, s;
11bd398c 206
a8170d5d 207 s = spltty();
01b0e233 208 if (q->c_cc <= 0)
11bd398c 209 goto out;
48575cec 210 while (cc>0 && q->c_cc) {
e39f9ea6 211 bp = cbptr((int)q->c_cf & ~CROUND);
48575cec
BJ
212 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
213 end = q->c_cl;
214 } else {
215 end = (char *)((int)bp + sizeof (struct cblock));
216 }
217 rem = end - q->c_cf;
218 if (cc >= rem) {
219 cc -= rem;
220 q->c_cc -= rem;
11bd398c 221 q->c_cf = bp->c_next->c_info;
48575cec
BJ
222 bp->c_next = cfreelist;
223 cfreelist = bp;
224 cfreecount += CBSIZE;
225 if (cwaiting) {
226 wakeup(&cwaiting);
227 cwaiting = 0;
228 }
11bd398c 229 } else {
48575cec
BJ
230 q->c_cc -= cc;
231 q->c_cf += cc;
232 if (q->c_cc <= 0) {
233 bp->c_next = cfreelist;
234 cfreelist = bp;
235 cfreecount += CBSIZE;
236 if (cwaiting) {
237 wakeup(&cwaiting);
238 cwaiting = 0;
239 }
240 }
241 break;
11bd398c 242 }
48575cec
BJ
243 }
244 if (q->c_cc <= 0) {
11bd398c 245 q->c_cf = q->c_cl = NULL;
48575cec 246 q->c_cc = 0;
11bd398c
BJ
247 }
248out:
249 splx(s);
250}
b8f09f36 251
48575cec 252
11bd398c 253putc(c, p)
fd402d46 254 int c;
88a7a62a 255 register struct clist *p;
11bd398c
BJ
256{
257 register struct cblock *bp;
258 register char *cp;
fd402d46 259 register int s;
11bd398c 260
a8170d5d 261 s = spltty();
e39f9ea6 262 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */
11bd398c
BJ
263 if ((bp = cfreelist) == NULL) {
264 splx(s);
01b0e233 265 return (-1);
11bd398c
BJ
266 }
267 cfreelist = bp->c_next;
48575cec 268 cfreecount -= CBSIZE;
11bd398c 269 bp->c_next = NULL;
e39f9ea6 270 bzero(bp->c_quote, CBQSIZE);
11bd398c
BJ
271 p->c_cf = cp = bp->c_info;
272 } else if (((int)cp & CROUND) == 0) {
e39f9ea6 273 bp = cbptr(cp) - 1; /* pointer arith */
11bd398c
BJ
274 if ((bp->c_next = cfreelist) == NULL) {
275 splx(s);
01b0e233 276 return (-1);
11bd398c
BJ
277 }
278 bp = bp->c_next;
279 cfreelist = bp->c_next;
48575cec 280 cfreecount -= CBSIZE;
11bd398c
BJ
281 bp->c_next = NULL;
282 cp = bp->c_info;
283 }
e39f9ea6
MT
284 if (c&TTY_QUOTE)
285 setquote(cp);
11bd398c
BJ
286 *cp++ = c;
287 p->c_cc++;
288 p->c_cl = cp;
289 splx(s);
01b0e233 290 return (0);
11bd398c
BJ
291}
292
11bd398c
BJ
293/*
294 * copy buffer to clist.
295 * return number of bytes not transfered.
296 */
297b_to_q(cp, cc, q)
88a7a62a
SL
298 register char *cp;
299 struct clist *q;
300 register int cc;
11bd398c
BJ
301{
302 register char *cq;
303 register struct cblock *bp;
fd402d46 304 register int s, nc;
a8170d5d 305 int acc;
11bd398c
BJ
306
307 if (cc <= 0)
01b0e233 308 return (0);
a8170d5d
MK
309 acc = cc;
310 s = spltty();
311 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
312 if ((bp = cfreelist) == NULL)
313 goto out;
314 cfreelist = bp->c_next;
315 cfreecount -= CBSIZE;
e39f9ea6 316 bzero(bp->c_quote, CBQSIZE);
a8170d5d
MK
317 bp->c_next = NULL;
318 q->c_cf = cq = bp->c_info;
319 }
320
321 while (cc) {
11bd398c 322 if (((int)cq & CROUND) == 0) {
e39f9ea6 323 bp = cbptr(cq) - 1;
a8170d5d
MK
324 if ((bp->c_next = cfreelist) == NULL)
325 goto out;
11bd398c
BJ
326 bp = bp->c_next;
327 cfreelist = bp->c_next;
48575cec 328 cfreecount -= CBSIZE;
e39f9ea6 329 bzero(bp->c_quote, CBQSIZE);
11bd398c 330 bp->c_next = NULL;
a8170d5d 331 cq = bp->c_info;
11bd398c 332 }
01b0e233 333 nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND));
a8170d5d
MK
334 (void) bcopy(cp, cq, (unsigned)nc);
335 cp += nc;
336 cq += nc;
337 cc -= nc;
11bd398c 338 }
a8170d5d
MK
339out:
340 q->c_cl = cq;
341 q->c_cc += acc - cc;
342 splx(s);
42cc3b3d 343 return (cc);
11bd398c
BJ
344}
345
b8f09f36
BJ
346/*
347 * Given a non-NULL pointter into the list (like c_cf which
348 * always points to a real character if non-NULL) return the pointer
349 * to the next character in the list or return NULL if no more chars.
350 *
351 * Callers must not allow getc's to happen between nextc's so that the
352 * pointer becomes invalid. Note that interrupts are NOT masked.
353 */
354char *
e39f9ea6 355nextc(p, cp, c)
88a7a62a
SL
356 register struct clist *p;
357 register char *cp;
e39f9ea6 358 register int *c;
b8f09f36
BJ
359{
360
361 if (p->c_cc && ++cp != p->c_cl) {
e39f9ea6
MT
362 if (((int)cp & CROUND) == 0) {
363 cp = (cbptr(cp))[-1].c_next->c_info;
364 }
365 *c = *cp;
366 if (isquote(cp))
367 *c |= TTY_QUOTE;
b8f09f36
BJ
368 return (cp);
369 }
370 return (0);
371}
372
373/*
374 * Remove the last character in the list and return it.
375 */
376unputc(p)
88a7a62a 377 register struct clist *p;
b8f09f36
BJ
378{
379 register struct cblock *bp;
380 register int c, s;
381 struct cblock *obp;
382
a8170d5d 383 s = spltty();
b8f09f36
BJ
384 if (p->c_cc <= 0)
385 c = -1;
386 else {
387 c = *--p->c_cl;
e39f9ea6
MT
388 if (isquote(p->c_cl))
389 c |= TTY_QUOTE;
b8f09f36 390 if (--p->c_cc <= 0) {
e39f9ea6
MT
391 bp = cbptr(p->c_cl);
392 bp = cbptr((int)bp & ~CROUND);
b8f09f36
BJ
393 p->c_cl = p->c_cf = NULL;
394 bp->c_next = cfreelist;
395 cfreelist = bp;
48575cec 396 cfreecount += CBSIZE;
e39f9ea6 397 } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
b8f09f36 398 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
e39f9ea6
MT
399
400 bp = cbptr(p->c_cf);
401 bp = cbptr((int)bp & ~CROUND);
402 while (bp->c_next != cbptr(p->c_cl))
b8f09f36
BJ
403 bp = bp->c_next;
404 obp = bp;
405 p->c_cl = (char *)(bp + 1);
406 bp = bp->c_next;
407 bp->c_next = cfreelist;
408 cfreelist = bp;
48575cec 409 cfreecount += CBSIZE;
b8f09f36
BJ
410 obp->c_next = NULL;
411 }
412 }
413 splx(s);
414 return (c);
415}
416
417/*
418 * Put the chars in the from que
419 * on the end of the to que.
b8f09f36
BJ
420 */
421catq(from, to)
88a7a62a 422 struct clist *from, *to;
b8f09f36 423{
e39f9ea6 424#ifdef notdef
a8170d5d 425 char bbuf[CBSIZE*4];
e39f9ea6 426#endif
fd402d46 427 register int s, c;
a8170d5d
MK
428
429 s = spltty();
430 if (to->c_cc == 0) {
431 *to = *from;
432 from->c_cc = 0;
433 from->c_cf = NULL;
434 from->c_cl = NULL;
435 splx(s);
436 return;
437 }
438 splx(s);
e39f9ea6 439#ifdef notdef
a8170d5d
MK
440 while (from->c_cc > 0) {
441 c = q_to_b(from, bbuf, sizeof bbuf);
442 (void) b_to_q(bbuf, c, to);
443 }
e39f9ea6
MT
444#endif
445 /* XXX - FIX */
446 while ((c = getc(from)) >= 0)
447 putc(c, to);
b8f09f36
BJ
448}
449
a8170d5d 450#ifdef unneeded
11bd398c 451/*
01b0e233 452 * Integer (short) get/put using clists.
11bd398c 453 */
a8170d5d 454typedef u_short word_t;
961945a8 455
11bd398c 456getw(p)
d0b37068 457 register struct clist *p;
11bd398c 458{
a8170d5d
MK
459 register int s, c;
460 register struct cblock *bp;
461
462 if (p->c_cc <= 1)
463 return(-1);
464 if (p->c_cc & 01) {
465 c = getc(p);
c6d44403 466#if BYTE_ORDER == LITTLE_ENDIAN
01b0e233
MK
467 return (c | (getc(p)<<8));
468#else
469 return (getc(p) | (c<<8));
470#endif
a8170d5d
MK
471 }
472 s = spltty();
e39f9ea6 473#if BYTE_ORDER == LITTLE_ENDIAN
fb1db32c 474 c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
01b0e233
MK
475#else
476 c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
477#endif
478 p->c_cf += sizeof (word_t);
479 p->c_cc -= sizeof (word_t);
a8170d5d 480 if (p->c_cc <= 0) {
e39f9ea6
MT
481 bp = cbptr(p->c_cf-1);
482 bp = cbptr((int)bp & ~CROUND);
a8170d5d
MK
483 p->c_cf = NULL;
484 p->c_cl = NULL;
485 bp->c_next = cfreelist;
486 cfreelist = bp;
487 cfreecount += CBSIZE;
488 if (cwaiting) {
489 wakeup(&cwaiting);
490 cwaiting = 0;
491 }
492 } else if (((int)p->c_cf & CROUND) == 0) {
e39f9ea6 493 bp = cbptr(p->c_cf);
a8170d5d
MK
494 bp--;
495 p->c_cf = bp->c_next->c_info;
496 bp->c_next = cfreelist;
497 cfreelist = bp;
498 cfreecount += CBSIZE;
499 if (cwaiting) {
500 wakeup(&cwaiting);
501 cwaiting = 0;
502 }
503 }
504 splx(s);
505 return (c);
11bd398c 506}
48575cec 507
11bd398c 508putw(c, p)
d0b37068 509 register struct clist *p;
a8170d5d 510 word_t c;
11bd398c 511{
fd402d46 512 register int s;
a8170d5d
MK
513 register struct cblock *bp;
514 register char *cp;
11bd398c 515
a8170d5d 516 s = spltty();
11bd398c
BJ
517 if (cfreelist==NULL) {
518 splx(s);
519 return(-1);
520 }
a8170d5d 521 if (p->c_cc & 01) {
c6d44403 522#if BYTE_ORDER == LITTLE_ENDIAN
a8170d5d
MK
523 (void) putc(c, p);
524 (void) putc(c>>8, p);
01b0e233
MK
525#else
526 (void) putc(c>>8, p);
527 (void) putc(c, p);
528#endif
a8170d5d
MK
529 } else {
530 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
531 if ((bp = cfreelist) == NULL) {
532 splx(s);
533 return (-1);
534 }
535 cfreelist = bp->c_next;
536 cfreecount -= CBSIZE;
537 bp->c_next = NULL;
538 p->c_cf = cp = bp->c_info;
539 } else if (((int)cp & CROUND) == 0) {
e39f9ea6 540 bp = cbptr(cp) - 1;
a8170d5d
MK
541 if ((bp->c_next = cfreelist) == NULL) {
542 splx(s);
543 return (-1);
544 }
545 bp = bp->c_next;
546 cfreelist = bp->c_next;
547 cfreecount -= CBSIZE;
548 bp->c_next = NULL;
549 cp = bp->c_info;
550 }
01b0e233 551#if defined(vax)
a8170d5d 552 *(word_t *)cp = c;
01b0e233
MK
553#else
554 ((u_char *)cp)[0] = c>>8;
555 ((u_char *)cp)[1] = c;
556#endif
557 p->c_cl = cp + sizeof (word_t);
558 p->c_cc += sizeof (word_t);
a8170d5d 559 }
11bd398c 560 splx(s);
961945a8 561 return (0);
11bd398c 562}
a8170d5d 563#endif unneeded