deprecate creat, setreuid, setregid; add set{,e}{u,g}id, gete[ug]id,
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
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 *
75d5a0b0 6 * @(#)tty_subr.c 7.5 (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 16char 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 */
29getc(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 */
78q_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 */
142ndqb(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 }
172out:
173 splx(s);
01b0e233 174 return (cc);
11bd398c
BJ
175}
176
11bd398c 177/*
48575cec 178 * Flush cc bytes from q.
11bd398c
BJ
179 */
180ndflush(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 }
229out:
230 splx(s);
231}
b8f09f36 232
48575cec 233
11bd398c 234putc(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 */
277b_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
319out:
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 */
334char *
e39f9ea6 335nextc(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 */
356unputc(p)
88a7a62a 357 register struct clist *p;
b8f09f36
BJ
358{
359 register struct cblock *bp;
360 register int c, s;
361 struct cblock *obp;
362
a8170d5d 363 s = spltty();
b8f09f36
BJ
364 if (p->c_cc <= 0)
365 c = -1;
366 else {
367 c = *--p->c_cl;
e39f9ea6
MT
368 if (isquote(p->c_cl))
369 c |= TTY_QUOTE;
b8f09f36 370 if (--p->c_cc <= 0) {
e39f9ea6
MT
371 bp = cbptr(p->c_cl);
372 bp = cbptr((int)bp & ~CROUND);
b8f09f36
BJ
373 p->c_cl = p->c_cf = NULL;
374 bp->c_next = cfreelist;
375 cfreelist = bp;
48575cec 376 cfreecount += CBSIZE;
e39f9ea6 377 } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
b8f09f36 378 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
e39f9ea6
MT
379
380 bp = cbptr(p->c_cf);
381 bp = cbptr((int)bp & ~CROUND);
382 while (bp->c_next != cbptr(p->c_cl))
b8f09f36
BJ
383 bp = bp->c_next;
384 obp = bp;
385 p->c_cl = (char *)(bp + 1);
386 bp = bp->c_next;
387 bp->c_next = cfreelist;
388 cfreelist = bp;
48575cec 389 cfreecount += CBSIZE;
b8f09f36
BJ
390 obp->c_next = NULL;
391 }
392 }
393 splx(s);
394 return (c);
395}
396
397/*
398 * Put the chars in the from que
399 * on the end of the to que.
b8f09f36
BJ
400 */
401catq(from, to)
88a7a62a 402 struct clist *from, *to;
b8f09f36 403{
e39f9ea6 404#ifdef notdef
a8170d5d 405 char bbuf[CBSIZE*4];
e39f9ea6 406#endif
a8170d5d
MK
407 register s, c;
408
409 s = spltty();
410 if (to->c_cc == 0) {
411 *to = *from;
412 from->c_cc = 0;
413 from->c_cf = NULL;
414 from->c_cl = NULL;
415 splx(s);
416 return;
417 }
418 splx(s);
e39f9ea6 419#ifdef notdef
a8170d5d
MK
420 while (from->c_cc > 0) {
421 c = q_to_b(from, bbuf, sizeof bbuf);
422 (void) b_to_q(bbuf, c, to);
423 }
e39f9ea6
MT
424#endif
425 /* XXX - FIX */
426 while ((c = getc(from)) >= 0)
427 putc(c, to);
b8f09f36
BJ
428}
429
a8170d5d 430#ifdef unneeded
11bd398c 431/*
01b0e233 432 * Integer (short) get/put using clists.
11bd398c 433 */
a8170d5d 434typedef u_short word_t;
961945a8 435
11bd398c 436getw(p)
d0b37068 437 register struct clist *p;
11bd398c 438{
a8170d5d
MK
439 register int s, c;
440 register struct cblock *bp;
441
442 if (p->c_cc <= 1)
443 return(-1);
444 if (p->c_cc & 01) {
445 c = getc(p);
c6d44403 446#if BYTE_ORDER == LITTLE_ENDIAN
01b0e233
MK
447 return (c | (getc(p)<<8));
448#else
449 return (getc(p) | (c<<8));
450#endif
a8170d5d
MK
451 }
452 s = spltty();
e39f9ea6 453#if BYTE_ORDER == LITTLE_ENDIAN
fb1db32c 454 c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
01b0e233
MK
455#else
456 c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
457#endif
458 p->c_cf += sizeof (word_t);
459 p->c_cc -= sizeof (word_t);
a8170d5d 460 if (p->c_cc <= 0) {
e39f9ea6
MT
461 bp = cbptr(p->c_cf-1);
462 bp = cbptr((int)bp & ~CROUND);
a8170d5d
MK
463 p->c_cf = NULL;
464 p->c_cl = NULL;
465 bp->c_next = cfreelist;
466 cfreelist = bp;
467 cfreecount += CBSIZE;
468 if (cwaiting) {
469 wakeup(&cwaiting);
470 cwaiting = 0;
471 }
472 } else if (((int)p->c_cf & CROUND) == 0) {
e39f9ea6 473 bp = cbptr(p->c_cf);
a8170d5d
MK
474 bp--;
475 p->c_cf = bp->c_next->c_info;
476 bp->c_next = cfreelist;
477 cfreelist = bp;
478 cfreecount += CBSIZE;
479 if (cwaiting) {
480 wakeup(&cwaiting);
481 cwaiting = 0;
482 }
483 }
484 splx(s);
485 return (c);
11bd398c 486}
48575cec 487
11bd398c 488putw(c, p)
d0b37068 489 register struct clist *p;
a8170d5d 490 word_t c;
11bd398c
BJ
491{
492 register s;
a8170d5d
MK
493 register struct cblock *bp;
494 register char *cp;
11bd398c 495
a8170d5d 496 s = spltty();
11bd398c
BJ
497 if (cfreelist==NULL) {
498 splx(s);
499 return(-1);
500 }
a8170d5d 501 if (p->c_cc & 01) {
c6d44403 502#if BYTE_ORDER == LITTLE_ENDIAN
a8170d5d
MK
503 (void) putc(c, p);
504 (void) putc(c>>8, p);
01b0e233
MK
505#else
506 (void) putc(c>>8, p);
507 (void) putc(c, p);
508#endif
a8170d5d
MK
509 } else {
510 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
511 if ((bp = cfreelist) == NULL) {
512 splx(s);
513 return (-1);
514 }
515 cfreelist = bp->c_next;
516 cfreecount -= CBSIZE;
517 bp->c_next = NULL;
518 p->c_cf = cp = bp->c_info;
519 } else if (((int)cp & CROUND) == 0) {
e39f9ea6 520 bp = cbptr(cp) - 1;
a8170d5d
MK
521 if ((bp->c_next = cfreelist) == NULL) {
522 splx(s);
523 return (-1);
524 }
525 bp = bp->c_next;
526 cfreelist = bp->c_next;
527 cfreecount -= CBSIZE;
528 bp->c_next = NULL;
529 cp = bp->c_info;
530 }
01b0e233 531#if defined(vax)
a8170d5d 532 *(word_t *)cp = c;
01b0e233
MK
533#else
534 ((u_char *)cp)[0] = c>>8;
535 ((u_char *)cp)[1] = c;
536#endif
537 p->c_cl = cp + sizeof (word_t);
538 p->c_cc += sizeof (word_t);
a8170d5d 539 }
11bd398c 540 splx(s);
961945a8 541 return (0);
11bd398c 542}
a8170d5d 543#endif unneeded