ignore bogus (large) return values from read
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
0a30ed64 1/* tty_subr.c 4.19 83/02/06 */
8f6119af 2
11bd398c 3#include "../h/param.h"
11bd398c
BJ
4#include "../h/systm.h"
5#include "../h/conf.h"
6#include "../h/buf.h"
48575cec 7#include "../h/tty.h"
d4df41fe 8#include "../h/clist.h"
11bd398c 9
48575cec 10char cwaiting;
11bd398c
BJ
11
12/*
13 * Character list get/put
14 */
15getc(p)
16register struct clist *p;
17{
18 register struct cblock *bp;
19 register int c, s;
20
7eb2e67e 21 s = spl5();
11bd398c
BJ
22 if (p->c_cc <= 0) {
23 c = -1;
24 p->c_cc = 0;
25 p->c_cf = p->c_cl = NULL;
26 } else {
27 c = *p->c_cf++ & 0377;
28 if (--p->c_cc<=0) {
29 bp = (struct cblock *)(p->c_cf-1);
30 bp = (struct cblock *) ((int)bp & ~CROUND);
31 p->c_cf = NULL;
32 p->c_cl = NULL;
33 bp->c_next = cfreelist;
34 cfreelist = bp;
48575cec
BJ
35 cfreecount += CBSIZE;
36 if (cwaiting) {
37 wakeup(&cwaiting);
38 cwaiting = 0;
39 }
11bd398c
BJ
40 } else if (((int)p->c_cf & CROUND) == 0){
41 bp = (struct cblock *)(p->c_cf);
42 bp--;
43 p->c_cf = bp->c_next->c_info;
44 bp->c_next = cfreelist;
45 cfreelist = bp;
48575cec
BJ
46 cfreecount += CBSIZE;
47 if (cwaiting) {
48 wakeup(&cwaiting);
49 cwaiting = 0;
50 }
11bd398c
BJ
51 }
52 }
53 splx(s);
54 return(c);
55}
56
57/*
58 * copy clist to buffer.
59 * return number of bytes moved.
60 */
61q_to_b(q, cp, cc)
961945a8
SL
62 register struct clist *q;
63 register char *cp;
11bd398c
BJ
64{
65 register struct cblock *bp;
66 register int s;
67 char *acp;
68
69 if (cc <= 0)
70 return(0);
7eb2e67e 71 s = spl5();
11bd398c
BJ
72 if (q->c_cc <= 0) {
73 q->c_cc = 0;
74 q->c_cf = q->c_cl = NULL;
48575cec 75 splx(s);
11bd398c
BJ
76 return(0);
77 }
78 acp = cp;
79 cc++;
80
81 while (--cc) {
82 *cp++ = *q->c_cf++;
83 if (--q->c_cc <= 0) {
84 bp = (struct cblock *)(q->c_cf-1);
85 bp = (struct cblock *)((int)bp & ~CROUND);
86 q->c_cf = q->c_cl = NULL;
87 bp->c_next = cfreelist;
88 cfreelist = bp;
48575cec
BJ
89 cfreecount += CBSIZE;
90 if (cwaiting) {
91 wakeup(&cwaiting);
92 cwaiting = 0;
93 }
11bd398c
BJ
94 break;
95 }
96 if (((int)q->c_cf & CROUND) == 0) {
97 bp = (struct cblock *)(q->c_cf);
98 bp--;
99 q->c_cf = bp->c_next->c_info;
100 bp->c_next = cfreelist;
101 cfreelist = bp;
48575cec
BJ
102 cfreecount += CBSIZE;
103 if (cwaiting) {
104 wakeup(&cwaiting);
105 cwaiting = 0;
106 }
11bd398c
BJ
107 }
108 }
109 splx(s);
110 return(cp-acp);
111}
112
11bd398c
BJ
113/*
114 * Return count of contiguous characters
115 * in clist starting at q->c_cf.
116 * Stop counting if flag&character is non-null.
117 */
118ndqb(q, flag)
961945a8 119 register struct clist *q;
11bd398c 120{
961945a8
SL
121 register cc;
122 int s;
11bd398c 123
7eb2e67e 124 s = spl5();
11bd398c
BJ
125 if (q->c_cc <= 0) {
126 cc = -q->c_cc;
127 goto out;
128 }
129 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
130 cc -= (int)q->c_cf;
131 if (q->c_cc < cc)
132 cc = q->c_cc;
133 if (flag) {
134 register char *p, *end;
135
136 p = q->c_cf;
137 end = p;
138 end += cc;
139 while (p < end) {
140 if (*p & flag) {
48575cec
BJ
141 cc = (int)p;
142 cc -= (int)q->c_cf;
11bd398c
BJ
143 break;
144 }
145 p++;
146 }
147 }
148out:
149 splx(s);
150 return(cc);
151}
152
48575cec
BJ
153
154
11bd398c 155/*
48575cec 156 * Flush cc bytes from q.
11bd398c
BJ
157 */
158ndflush(q, cc)
159register struct clist *q;
160register cc;
161{
48575cec
BJ
162register struct cblock *bp;
163char *end;
164int rem;
11bd398c
BJ
165register s;
166
7eb2e67e 167 s = spl5();
0a30ed64 168 if (q->c_cc <= 0) {
11bd398c
BJ
169 goto out;
170 }
48575cec
BJ
171 while (cc>0 && q->c_cc) {
172 bp = (struct cblock *)((int)q->c_cf & ~CROUND);
173 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
174 end = q->c_cl;
175 } else {
176 end = (char *)((int)bp + sizeof (struct cblock));
177 }
178 rem = end - q->c_cf;
179 if (cc >= rem) {
180 cc -= rem;
181 q->c_cc -= rem;
11bd398c 182 q->c_cf = bp->c_next->c_info;
48575cec
BJ
183 bp->c_next = cfreelist;
184 cfreelist = bp;
185 cfreecount += CBSIZE;
186 if (cwaiting) {
187 wakeup(&cwaiting);
188 cwaiting = 0;
189 }
11bd398c 190 } else {
48575cec
BJ
191 q->c_cc -= cc;
192 q->c_cf += cc;
193 if (q->c_cc <= 0) {
194 bp->c_next = cfreelist;
195 cfreelist = bp;
196 cfreecount += CBSIZE;
197 if (cwaiting) {
198 wakeup(&cwaiting);
199 cwaiting = 0;
200 }
201 }
202 break;
11bd398c 203 }
48575cec
BJ
204 }
205 if (q->c_cc <= 0) {
11bd398c 206 q->c_cf = q->c_cl = NULL;
48575cec 207 q->c_cc = 0;
11bd398c
BJ
208 }
209out:
210 splx(s);
211}
b8f09f36 212
48575cec 213
11bd398c
BJ
214putc(c, p)
215register struct clist *p;
216{
217 register struct cblock *bp;
218 register char *cp;
219 register s;
220
7eb2e67e 221 s = spl5();
11bd398c
BJ
222 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
223 if ((bp = cfreelist) == NULL) {
224 splx(s);
225 return(-1);
226 }
227 cfreelist = bp->c_next;
48575cec 228 cfreecount -= CBSIZE;
11bd398c
BJ
229 bp->c_next = NULL;
230 p->c_cf = cp = bp->c_info;
231 } else if (((int)cp & CROUND) == 0) {
232 bp = (struct cblock *)cp - 1;
233 if ((bp->c_next = cfreelist) == NULL) {
234 splx(s);
235 return(-1);
236 }
237 bp = bp->c_next;
238 cfreelist = bp->c_next;
48575cec 239 cfreecount -= CBSIZE;
11bd398c
BJ
240 bp->c_next = NULL;
241 cp = bp->c_info;
242 }
243 *cp++ = c;
244 p->c_cc++;
245 p->c_cl = cp;
246 splx(s);
247 return(0);
248}
249
48575cec
BJ
250
251
11bd398c
BJ
252/*
253 * copy buffer to clist.
254 * return number of bytes not transfered.
255 */
256b_to_q(cp, cc, q)
257register char *cp;
258struct clist *q;
259register int cc;
260{
261 register char *cq;
262 register struct cblock *bp;
263 register s, acc;
264
265 if (cc <= 0)
266 return(0);
267 acc = cc;
48575cec
BJ
268
269
7eb2e67e 270 s = spl5();
11bd398c
BJ
271 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
272 if ((bp = cfreelist) == NULL)
273 goto out;
274 cfreelist = bp->c_next;
48575cec 275 cfreecount -= CBSIZE;
11bd398c
BJ
276 bp->c_next = NULL;
277 q->c_cf = cq = bp->c_info;
278 }
279
280 while (cc) {
281 if (((int)cq & CROUND) == 0) {
282 bp = (struct cblock *) cq - 1;
283 if ((bp->c_next = cfreelist) == NULL)
284 goto out;
285 bp = bp->c_next;
286 cfreelist = bp->c_next;
48575cec 287 cfreecount -= CBSIZE;
11bd398c
BJ
288 bp->c_next = NULL;
289 cq = bp->c_info;
290 }
291 *cq++ = *cp++;
292 cc--;
293 }
294out:
295 q->c_cl = cq;
296 q->c_cc += acc-cc;
297 splx(s);
298 return(cc);
299}
300
b8f09f36
BJ
301/*
302 * Given a non-NULL pointter into the list (like c_cf which
303 * always points to a real character if non-NULL) return the pointer
304 * to the next character in the list or return NULL if no more chars.
305 *
306 * Callers must not allow getc's to happen between nextc's so that the
307 * pointer becomes invalid. Note that interrupts are NOT masked.
308 */
309char *
310nextc(p, cp)
311register struct clist *p;
312register char *cp;
313{
314
315 if (p->c_cc && ++cp != p->c_cl) {
316 if (((int)cp & CROUND) == 0)
317 return (((struct cblock *)cp)[-1].c_next->c_info);
318 return (cp);
319 }
320 return (0);
321}
322
323/*
324 * Remove the last character in the list and return it.
325 */
326unputc(p)
327register struct clist *p;
328{
329 register struct cblock *bp;
330 register int c, s;
331 struct cblock *obp;
332
7eb2e67e 333 s = spl5();
b8f09f36
BJ
334 if (p->c_cc <= 0)
335 c = -1;
336 else {
337 c = *--p->c_cl;
338 if (--p->c_cc <= 0) {
339 bp = (struct cblock *)p->c_cl;
340 bp = (struct cblock *)((int)bp & ~CROUND);
341 p->c_cl = p->c_cf = NULL;
342 bp->c_next = cfreelist;
343 cfreelist = bp;
48575cec 344 cfreecount += CBSIZE;
b8f09f36
BJ
345 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
346 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
347 bp = (struct cblock *)p->c_cf;
348 bp = (struct cblock *)((int)bp & ~CROUND);
349 while (bp->c_next != (struct cblock *)p->c_cl)
350 bp = bp->c_next;
351 obp = bp;
352 p->c_cl = (char *)(bp + 1);
353 bp = bp->c_next;
354 bp->c_next = cfreelist;
355 cfreelist = bp;
48575cec 356 cfreecount += CBSIZE;
b8f09f36
BJ
357 obp->c_next = NULL;
358 }
359 }
360 splx(s);
361 return (c);
362}
363
364/*
365 * Put the chars in the from que
366 * on the end of the to que.
367 *
368 * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
369 */
370catq(from, to)
371struct clist *from, *to;
372{
373 register c;
374
375 while ((c = getc(from)) >= 0)
376 (void) putc(c, to);
377}
378
11bd398c 379/*
961945a8 380 * Integer (short) get/put
11bd398c
BJ
381 * using clists
382 */
961945a8
SL
383typedef short word_t;
384union chword {
385 word_t word;
386 struct {
387 char Ch[sizeof (word_t)];
388 } Cha;
389#define ch Cha.Ch
390};
391
11bd398c 392getw(p)
d0b37068 393 register struct clist *p;
11bd398c 394{
961945a8
SL
395 register int i;
396 union chword x;
397
398 if (p->c_cc < sizeof (word_t))
399 return (-1);
400 for (i = 0; i < sizeof (word_t); i++)
401 x.ch[i] = getc(p);
402 return (x.word);
11bd398c 403}
48575cec 404
11bd398c 405putw(c, p)
d0b37068 406 register struct clist *p;
11bd398c
BJ
407{
408 register s;
961945a8
SL
409 register int i;
410 union chword x;
11bd398c 411
7eb2e67e 412 s = spl5();
11bd398c
BJ
413 if (cfreelist==NULL) {
414 splx(s);
415 return(-1);
416 }
961945a8
SL
417 x.word = c;
418 for (i = 0; i < sizeof (word_t); i++)
419 (void) putc(x.ch[i], p);
11bd398c 420 splx(s);
961945a8 421 return (0);
11bd398c 422}