must include proc before tty.h and socketvar.h
[unix-history] / usr / src / sys / kern / tty_subr.c
... / ...
CommitLineData
1/*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 *
7 * @(#)tty_subr.c 7.9 (Berkeley) %G%
8 */
9
10#include "param.h"
11#include "systm.h"
12#include "buf.h"
13#include "ioctl.h"
14#include "proc.h"
15#include "tty.h"
16#include "clist.h"
17
18char cwaiting;
19
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
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
45/*
46 * Character list get/put
47 */
48getc(p)
49 register struct clist *p;
50{
51 register struct cblock *bp;
52 register int c, s;
53
54 s = spltty();
55 if (p->c_cc <= 0) {
56 c = -1;
57 p->c_cc = 0;
58 p->c_cf = p->c_cl = NULL;
59 } else {
60 c = *p->c_cf & 0377;
61 if (isquote(p->c_cf))
62 c |= TTY_QUOTE;
63 p->c_cf++;
64 if (--p->c_cc<=0) {
65 bp = cbptr(p->c_cf-1);
66 bp = cbptr((int)bp & ~CROUND);
67 p->c_cf = NULL;
68 p->c_cl = NULL;
69 bp->c_next = cfreelist;
70 cfreelist = bp;
71 cfreecount += CBSIZE;
72 if (cwaiting) {
73 wakeup(&cwaiting);
74 cwaiting = 0;
75 }
76 } else if (((int)p->c_cf & CROUND) == 0){
77 bp = cbptr(p->c_cf);
78 bp--;
79 p->c_cf = bp->c_next->c_info;
80 bp->c_next = cfreelist;
81 cfreelist = bp;
82 cfreecount += CBSIZE;
83 if (cwaiting) {
84 wakeup(&cwaiting);
85 cwaiting = 0;
86 }
87 }
88 }
89 splx(s);
90 return (c);
91}
92
93/*
94 * copy clist to buffer.
95 * return number of bytes moved.
96 */
97q_to_b(q, cp, cc)
98 register struct clist *q;
99 register char *cp;
100 int cc;
101{
102 register struct cblock *bp;
103 register int s, nc;
104 char *acp;
105
106 if (cc <= 0)
107 return (0);
108 s = spltty();
109 if (q->c_cc <= 0) {
110 q->c_cc = 0;
111 q->c_cf = q->c_cl = NULL;
112 splx(s);
113 return (0);
114 }
115 acp = cp;
116
117 while (cc) {
118 nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
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) {
127 bp = cbptr(q->c_cf - 1);
128 bp = cbptr((int)bp & ~CROUND);
129 q->c_cf = q->c_cl = NULL;
130 bp->c_next = cfreelist;
131 cfreelist = bp;
132 cfreecount += CBSIZE;
133 if (cwaiting) {
134 wakeup(&cwaiting);
135 cwaiting = 0;
136 }
137 break;
138 }
139 if (((int)q->c_cf & CROUND) == 0) {
140 bp = cbptr(q->c_cf);
141 bp--;
142 q->c_cf = bp->c_next->c_info;
143 bp->c_next = cfreelist;
144 cfreelist = bp;
145 cfreecount += CBSIZE;
146 if (cwaiting) {
147 wakeup(&cwaiting);
148 cwaiting = 0;
149 }
150 }
151 }
152 splx(s);
153 return (cp-acp);
154}
155
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)
162 register struct clist *q;
163 int flag;
164{
165 register int cc, s;
166
167 s = spltty();
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) {
184 cc = (int)p;
185 cc -= (int)q->c_cf;
186 break;
187 }
188 p++;
189 }
190 }
191out:
192 splx(s);
193 return (cc);
194}
195
196/*
197 * Flush cc bytes from q.
198 */
199ndflush(q, cc)
200 register struct clist *q;
201 register int cc;
202{
203 register struct cblock *bp;
204 char *end;
205 int rem, s;
206
207 s = spltty();
208 if (q->c_cc <= 0)
209 goto out;
210 while (cc>0 && q->c_cc) {
211 bp = cbptr((int)q->c_cf & ~CROUND);
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;
221 q->c_cf = bp->c_next->c_info;
222 bp->c_next = cfreelist;
223 cfreelist = bp;
224 cfreecount += CBSIZE;
225 if (cwaiting) {
226 wakeup(&cwaiting);
227 cwaiting = 0;
228 }
229 } else {
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;
242 }
243 }
244 if (q->c_cc <= 0) {
245 q->c_cf = q->c_cl = NULL;
246 q->c_cc = 0;
247 }
248out:
249 splx(s);
250}
251
252
253putc(c, p)
254 int c;
255 register struct clist *p;
256{
257 register struct cblock *bp;
258 register char *cp;
259 register int s;
260
261 s = spltty();
262 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */
263 if ((bp = cfreelist) == NULL) {
264 splx(s);
265 return (-1);
266 }
267 cfreelist = bp->c_next;
268 cfreecount -= CBSIZE;
269 bp->c_next = NULL;
270 bzero(bp->c_quote, CBQSIZE);
271 p->c_cf = cp = bp->c_info;
272 } else if (((int)cp & CROUND) == 0) {
273 bp = cbptr(cp) - 1; /* pointer arith */
274 if ((bp->c_next = cfreelist) == NULL) {
275 splx(s);
276 return (-1);
277 }
278 bp = bp->c_next;
279 cfreelist = bp->c_next;
280 cfreecount -= CBSIZE;
281 bp->c_next = NULL;
282 cp = bp->c_info;
283 }
284 if (c&TTY_QUOTE)
285 setquote(cp);
286 *cp++ = c;
287 p->c_cc++;
288 p->c_cl = cp;
289 splx(s);
290 return (0);
291}
292
293/*
294 * copy buffer to clist.
295 * return number of bytes not transfered.
296 */
297b_to_q(cp, cc, q)
298 register char *cp;
299 struct clist *q;
300 register int cc;
301{
302 register char *cq;
303 register struct cblock *bp;
304 register int s, nc;
305 int acc;
306
307 if (cc <= 0)
308 return (0);
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;
316 bzero(bp->c_quote, CBQSIZE);
317 bp->c_next = NULL;
318 q->c_cf = cq = bp->c_info;
319 }
320
321 while (cc) {
322 if (((int)cq & CROUND) == 0) {
323 bp = cbptr(cq) - 1;
324 if ((bp->c_next = cfreelist) == NULL)
325 goto out;
326 bp = bp->c_next;
327 cfreelist = bp->c_next;
328 cfreecount -= CBSIZE;
329 bzero(bp->c_quote, CBQSIZE);
330 bp->c_next = NULL;
331 cq = bp->c_info;
332 }
333 nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND));
334 (void) bcopy(cp, cq, (unsigned)nc);
335 cp += nc;
336 cq += nc;
337 cc -= nc;
338 }
339out:
340 q->c_cl = cq;
341 q->c_cc += acc - cc;
342 splx(s);
343 return (cc);
344}
345
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 *
355nextc(p, cp, c)
356 register struct clist *p;
357 register char *cp;
358 register int *c;
359{
360
361 if (p->c_cc && ++cp != p->c_cl) {
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;
368 return (cp);
369 }
370 return (0);
371}
372
373/*
374 * Remove the last character in the list and return it.
375 */
376unputc(p)
377 register struct clist *p;
378{
379 register struct cblock *bp;
380 register int c, s;
381 struct cblock *obp;
382
383 s = spltty();
384 if (p->c_cc <= 0)
385 c = -1;
386 else {
387 c = *--p->c_cl;
388 if (isquote(p->c_cl))
389 c |= TTY_QUOTE;
390 if (--p->c_cc <= 0) {
391 bp = cbptr(p->c_cl);
392 bp = cbptr((int)bp & ~CROUND);
393 p->c_cl = p->c_cf = NULL;
394 bp->c_next = cfreelist;
395 cfreelist = bp;
396 cfreecount += CBSIZE;
397 } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
398 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
399
400 bp = cbptr(p->c_cf);
401 bp = cbptr((int)bp & ~CROUND);
402 while (bp->c_next != cbptr(p->c_cl))
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;
409 cfreecount += CBSIZE;
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.
420 */
421catq(from, to)
422 struct clist *from, *to;
423{
424#ifdef notdef
425 char bbuf[CBSIZE*4];
426#endif
427 register int s, c;
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);
439#ifdef notdef
440 while (from->c_cc > 0) {
441 c = q_to_b(from, bbuf, sizeof bbuf);
442 (void) b_to_q(bbuf, c, to);
443 }
444#endif
445 /* XXX - FIX */
446 while ((c = getc(from)) >= 0)
447 putc(c, to);
448}
449
450#ifdef unneeded
451/*
452 * Integer (short) get/put using clists.
453 */
454typedef u_short word_t;
455
456getw(p)
457 register struct clist *p;
458{
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);
466#if BYTE_ORDER == LITTLE_ENDIAN
467 return (c | (getc(p)<<8));
468#else
469 return (getc(p) | (c<<8));
470#endif
471 }
472 s = spltty();
473#if BYTE_ORDER == LITTLE_ENDIAN
474 c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
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);
480 if (p->c_cc <= 0) {
481 bp = cbptr(p->c_cf-1);
482 bp = cbptr((int)bp & ~CROUND);
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) {
493 bp = cbptr(p->c_cf);
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);
506}
507
508putw(c, p)
509 register struct clist *p;
510 word_t c;
511{
512 register int s;
513 register struct cblock *bp;
514 register char *cp;
515
516 s = spltty();
517 if (cfreelist==NULL) {
518 splx(s);
519 return(-1);
520 }
521 if (p->c_cc & 01) {
522#if BYTE_ORDER == LITTLE_ENDIAN
523 (void) putc(c, p);
524 (void) putc(c>>8, p);
525#else
526 (void) putc(c>>8, p);
527 (void) putc(c, p);
528#endif
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) {
540 bp = cbptr(cp) - 1;
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 }
551#if defined(vax)
552 *(word_t *)cp = c;
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);
559 }
560 splx(s);
561 return (0);
562}
563#endif unneeded