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