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