hang while device is waiting for silo to flush
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
e7a747b1 1/* tty.c 4.45 83/07/06 */
961945a8
SL
2
3#include "../machine/reg.h"
89dc6dfb 4
89dc6dfb
BJ
5#include "../h/param.h"
6#include "../h/systm.h"
7#include "../h/dir.h"
8#include "../h/user.h"
becb115c 9#include "../h/ioctl.h"
89dc6dfb
BJ
10#include "../h/tty.h"
11#include "../h/proc.h"
89dc6dfb
BJ
12#include "../h/inode.h"
13#include "../h/file.h"
89dc6dfb
BJ
14#include "../h/conf.h"
15#include "../h/buf.h"
d1778415 16#include "../h/dk.h"
d6d7360b 17#include "../h/uio.h"
894cfdb7 18#include "../h/kernel.h"
89dc6dfb 19
8bba2b8f
RE
20/*
21 * Table giving parity for characters and indicating
22 * character classes to tty driver. In particular,
23 * if the low 6 bits are 0, then the character needs
24 * no special processing on output.
25 */
26
27char partab[] = {
28 0001,0201,0201,0001,0201,0001,0001,0201,
29 0202,0004,0003,0201,0005,0206,0201,0001,
30 0201,0001,0001,0201,0001,0201,0201,0001,
31 0001,0201,0201,0001,0201,0001,0001,0201,
32 0200,0000,0000,0200,0000,0200,0200,0000,
33 0000,0200,0200,0000,0200,0000,0000,0200,
34 0000,0200,0200,0000,0200,0000,0000,0200,
35 0200,0000,0000,0200,0000,0200,0200,0000,
36 0200,0000,0000,0200,0000,0200,0200,0000,
37 0000,0200,0200,0000,0200,0000,0000,0200,
38 0000,0200,0200,0000,0200,0000,0000,0200,
39 0200,0000,0000,0200,0000,0200,0200,0000,
40 0000,0200,0200,0000,0200,0000,0000,0200,
41 0200,0000,0000,0200,0000,0200,0200,0000,
42 0200,0000,0000,0200,0000,0200,0200,0000,
43 0000,0200,0200,0000,0200,0000,0000,0201,
44
45 /*
46 * 7 bit ascii ends with the last character above,
47 * but we contine through all 256 codes for the sake
48 * of the tty output routines which use special vax
49 * instructions which need a 256 character trt table.
50 */
51
52 0007,0007,0007,0007,0007,0007,0007,0007,
53 0007,0007,0007,0007,0007,0007,0007,0007,
54 0007,0007,0007,0007,0007,0007,0007,0007,
55 0007,0007,0007,0007,0007,0007,0007,0007,
56 0007,0007,0007,0007,0007,0007,0007,0007,
57 0007,0007,0007,0007,0007,0007,0007,0007,
58 0007,0007,0007,0007,0007,0007,0007,0007,
59 0007,0007,0007,0007,0007,0007,0007,0007,
60 0007,0007,0007,0007,0007,0007,0007,0007,
61 0007,0007,0007,0007,0007,0007,0007,0007,
62 0007,0007,0007,0007,0007,0007,0007,0007,
63 0007,0007,0007,0007,0007,0007,0007,0007,
64 0007,0007,0007,0007,0007,0007,0007,0007,
65 0007,0007,0007,0007,0007,0007,0007,0007,
66 0007,0007,0007,0007,0007,0007,0007,0007,
67 0007,0007,0007,0007,0007,0007,0007,0007
68};
89dc6dfb 69
89dc6dfb
BJ
70/*
71 * Input mapping table-- if an entry is non-zero, when the
72 * corresponding character is typed preceded by "\" the escape
73 * sequence is replaced by the table value. Mostly used for
74 * upper-case only terminals.
75 */
89dc6dfb
BJ
76char maptab[] ={
77 000,000,000,000,000,000,000,000,
78 000,000,000,000,000,000,000,000,
79 000,000,000,000,000,000,000,000,
80 000,000,000,000,000,000,000,000,
81 000,'|',000,000,000,000,000,'`',
82 '{','}',000,000,000,000,000,000,
83 000,000,000,000,000,000,000,000,
84 000,000,000,000,000,000,000,000,
85 000,000,000,000,000,000,000,000,
86 000,000,000,000,000,000,000,000,
87 000,000,000,000,000,000,000,000,
88 000,000,000,000,000,000,'~',000,
89 000,'A','B','C','D','E','F','G',
90 'H','I','J','K','L','M','N','O',
91 'P','Q','R','S','T','U','V','W',
92 'X','Y','Z',000,000,000,000,000,
93};
94
0d65848d 95short tthiwat[16] =
6f21eede 96 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
0d65848d
BJ
97short ttlowat[16] =
98 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99
becb115c
SL
100struct ttychars ttydefaults = {
101 CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF,
102 CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
103};
89dc6dfb 104
89dc6dfb 105ttychars(tp)
becb115c 106 struct tty *tp;
89dc6dfb 107{
8062c8a7 108
becb115c 109 tp->t_chars = ttydefaults;
89dc6dfb
BJ
110}
111
112/*
50e2732b 113 * Wait for output to drain, then flush input waiting.
89dc6dfb 114 */
88a7a62a 115ttywflush(tp)
941944c9 116 register struct tty *tp;
89dc6dfb
BJ
117{
118
88a7a62a
SL
119 ttywait(tp);
120 ttyflush(tp, FREAD);
121}
122
123ttywait(tp)
124 register struct tty *tp;
125{
126 register int s = spl5();
127
4c67f645
BJ
128 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
129 && tp->t_oproc) { /* kludge for pty */
50e2732b 130 (*tp->t_oproc)(tp);
941944c9 131 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
132 sleep((caddr_t)&tp->t_outq, TTOPRI);
133 }
875a1e2c 134 splx(s);
89dc6dfb
BJ
135}
136
137/*
becb115c 138 * Flush all TTY queues
89dc6dfb 139 */
88a7a62a 140ttyflush(tp, rw)
4b72e2f9 141 register struct tty *tp;
89dc6dfb 142{
50e2732b
BJ
143 register s;
144
50e2732b
BJ
145 s = spl6();
146 if (rw & FREAD) {
147 while (getc(&tp->t_canq) >= 0)
148 ;
149 wakeup((caddr_t)&tp->t_rawq);
150 }
151 if (rw & FWRITE) {
152 wakeup((caddr_t)&tp->t_outq);
941944c9 153 tp->t_state &= ~TS_TTSTOP;
39697bd8 154 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
155 while (getc(&tp->t_outq) >= 0)
156 ;
157 }
158 if (rw & FREAD) {
159 while (getc(&tp->t_rawq) >= 0)
160 ;
161 tp->t_delct = 0;
becb115c 162 tp->t_rocount = 0;
50e2732b 163 tp->t_rocol = 0;
becb115c 164 tp->t_state &= ~TS_LOCAL;
50e2732b
BJ
165 }
166 splx(s);
89dc6dfb
BJ
167}
168
50e2732b
BJ
169/*
170 * Send stop character on input overflow.
171 */
172ttyblock(tp)
4b72e2f9 173 register struct tty *tp;
89dc6dfb 174{
50e2732b 175 register x;
becb115c 176
50e2732b
BJ
177 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
178 if (tp->t_rawq.c_cc > TTYHOG) {
88a7a62a 179 ttyflush(tp, FREAD|FWRITE);
941944c9 180 tp->t_state &= ~TS_TBLOCK;
50e2732b 181 }
becb115c
SL
182 if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
183 tp->t_state |= TS_TBLOCK;
becb115c 184 ttstart(tp);
50e2732b 185 }
89dc6dfb
BJ
186}
187
101ba270 188/*
50e2732b
BJ
189 * Restart typewriter output following a delay
190 * timeout.
191 * The name of the routine is passed to the timeout
192 * subroutine and it is called during a clock interrupt.
101ba270 193 */
50e2732b 194ttrstrt(tp)
4b72e2f9 195 register struct tty *tp;
101ba270
BJ
196{
197
becb115c
SL
198 if (tp == 0)
199 panic("ttrstrt");
941944c9 200 tp->t_state &= ~TS_TIMEOUT;
50e2732b 201 ttstart(tp);
101ba270
BJ
202}
203
89dc6dfb 204/*
50e2732b
BJ
205 * Start output on the typewriter. It is used from the top half
206 * after some characters have been put on the output queue,
207 * from the interrupt routine to transmit the next
208 * character, and after a timeout has finished.
89dc6dfb 209 */
50e2732b 210ttstart(tp)
4b72e2f9 211 register struct tty *tp;
89dc6dfb 212{
50e2732b 213 register s;
8062c8a7 214
50e2732b 215 s = spl5();
becb115c 216 if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
4c67f645 217 tp->t_oproc) /* kludge for pty */
50e2732b
BJ
218 (*tp->t_oproc)(tp);
219 splx(s);
89dc6dfb
BJ
220}
221
222/*
50e2732b 223 * Common code for tty ioctls.
89dc6dfb 224 */
49c84d3f 225/*ARGSUSED*/
4b72e2f9
SL
226ttioctl(tp, com, data, flag)
227 register struct tty *tp;
228 caddr_t data;
89dc6dfb 229{
840510a3 230 int dev = tp->t_dev;
89dc6dfb 231 extern int nldisp;
fc6972ae 232 int s;
88a7a62a 233 register int newflags;
89dc6dfb 234
50e2732b
BJ
235 /*
236 * If the ioctl involves modification,
237 * insist on being able to write the device,
238 * and hang if in the background.
239 */
4b72e2f9 240 switch (com) {
50e2732b 241
c6fe3a50
BJ
242 case TIOCSETD:
243 case TIOCSETP:
244 case TIOCSETN:
50e2732b
BJ
245 case TIOCFLUSH:
246 case TIOCSETC:
247 case TIOCSLTC:
248 case TIOCSPGRP:
249 case TIOCLBIS:
250 case TIOCLBIC:
251 case TIOCLSET:
8203fe05 252 case TIOCSTI:
50e2732b
BJ
253 while (tp->t_line == NTTYDISC &&
254 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
255 (u.u_procp->p_flag&SVFORK) == 0 &&
256 u.u_signal[SIGTTOU] != SIG_IGN &&
fc6972ae 257 u.u_signal[SIGTTOU] != SIG_HOLD) {
50e2732b
BJ
258 gsignal(u.u_procp->p_pgrp, SIGTTOU);
259 sleep((caddr_t)&lbolt, TTOPRI);
260 }
261 break;
262 }
263
becb115c
SL
264 /*
265 * Process the ioctl.
266 */
4b72e2f9 267 switch (com) {
89dc6dfb 268
fc6972ae 269 /* get discipline number */
89dc6dfb 270 case TIOCGETD:
4b72e2f9 271 *(int *)data = tp->t_line;
89dc6dfb
BJ
272 break;
273
fc6972ae 274 /* set line discipline */
4b72e2f9
SL
275 case TIOCSETD: {
276 register int t = *(int *)data;
becb115c 277 int error = 0;
4b72e2f9 278
4a003df3
SL
279 if (t >= nldisp)
280 return (ENXIO);
fc6972ae 281 s = spl5();
89dc6dfb
BJ
282 if (tp->t_line)
283 (*linesw[tp->t_line].l_close)(tp);
284 if (t)
fc6972ae
BJ
285 error = (*linesw[t].l_open)(dev, tp);
286 splx(s);
4a003df3
SL
287 if (error) {
288 s = spl5();
289 if (tp->t_line)
290 (void) (*linesw[tp->t_line].l_open)(dev, tp);
291 splx(s);
fc6972ae 292 return (error);
4a003df3 293 }
fc6972ae 294 tp->t_line = t;
89dc6dfb 295 break;
4b72e2f9 296 }
89dc6dfb 297
fc6972ae 298 /* prevent more opens on channel */
152c2598
BJ
299 case TIOCEXCL:
300 tp->t_state |= TS_XCLUDE;
301 break;
302
303 case TIOCNXCL:
304 tp->t_state &= ~TS_XCLUDE;
305 break;
306
fc6972ae 307 /* hang up line on last close */
89dc6dfb 308 case TIOCHPCL:
941944c9 309 tp->t_state |= TS_HUPCLS;
89dc6dfb
BJ
310 break;
311
7d973a4d 312 case TIOCFLUSH: {
4b72e2f9
SL
313 register int flags = *(int *)data;
314
315 if (flags == 0)
7d973a4d 316 flags = FREAD|FWRITE;
4b72e2f9
SL
317 else
318 flags &= FREAD|FWRITE;
88a7a62a 319 ttyflush(tp, flags);
89dc6dfb 320 break;
4568c08e 321 }
89dc6dfb 322
fc6972ae 323 /* return number of characters immediately available */
4b72e2f9
SL
324 case FIONREAD:
325 *(off_t *)data = ttnread(tp);
8062c8a7 326 break;
8062c8a7 327
b968e450
SL
328 case TIOCOUTQ:
329 *(int *)data = tp->t_outq.c_cc;
330 break;
331
a8d3bf7f
BJ
332 case TIOCSTOP:
333 s = spl5();
becb115c 334 if ((tp->t_state&TS_TTSTOP) == 0) {
bfcf09ee
BJ
335 tp->t_state |= TS_TTSTOP;
336 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
337 }
4b72e2f9 338 splx(s);
bfcf09ee
BJ
339 break;
340
a8d3bf7f
BJ
341 case TIOCSTART:
342 s = spl5();
becb115c 343 if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
bfcf09ee 344 tp->t_state &= ~TS_TTSTOP;
becb115c 345 tp->t_flags &= ~FLUSHO;
bfcf09ee
BJ
346 ttstart(tp);
347 }
4b72e2f9 348 splx(s);
bfcf09ee
BJ
349 break;
350
8203fe05
SL
351 /*
352 * Simulate typing of a character at the terminal.
353 */
354 case TIOCSTI:
355 if (u.u_uid && u.u_ttyp != tp)
356 return (EACCES);
becb115c 357 (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
8203fe05
SL
358 break;
359
88a7a62a
SL
360 case TIOCSETP:
361 case TIOCSETN: {
362 register struct sgttyb *sg = (struct sgttyb *)data;
363
364 tp->t_erase = sg->sg_erase;
365 tp->t_kill = sg->sg_kill;
366 tp->t_ispeed = sg->sg_ispeed;
367 tp->t_ospeed = sg->sg_ospeed;
368 newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
88a7a62a
SL
369 s = spl5();
370 if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
371 ttywait(tp);
372 ttyflush(tp, FREAD);
373 } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) {
374 if (newflags&CBREAK) {
375 struct clist tq;
376
377 catq(&tp->t_rawq, &tp->t_canq);
378 tq = tp->t_rawq;
379 tp->t_rawq = tp->t_canq;
380 tp->t_canq = tq;
381 } else {
382 tp->t_flags |= PENDIN;
096b7e95 383 newflags |= PENDIN;
88a7a62a
SL
384 ttwakeup(tp);
385 }
386 }
387 tp->t_flags = newflags;
388 if (tp->t_flags&RAW) {
389 tp->t_state &= ~TS_TTSTOP;
390 ttstart(tp);
391 }
392 splx(s);
393 break;
394 }
395
396 /* send current parameters to user */
397 case TIOCGETP: {
398 register struct sgttyb *sg = (struct sgttyb *)data;
399
400 sg->sg_ispeed = tp->t_ispeed;
401 sg->sg_ospeed = tp->t_ospeed;
402 sg->sg_erase = tp->t_erase;
403 sg->sg_kill = tp->t_kill;
404 sg->sg_flags = tp->t_flags;
405 break;
406 }
407
408 case FIONBIO:
409 if (*(int *)data)
410 tp->t_state |= TS_NBIO;
411 else
412 tp->t_state &= ~TS_NBIO;
413 break;
414
415 case FIOASYNC:
416 if (*(int *)data)
417 tp->t_state |= TS_ASYNC;
418 else
419 tp->t_state &= ~TS_ASYNC;
420 break;
421
b968e450
SL
422 case TIOCGETC:
423 bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
424 break;
425
426 case TIOCSETC:
427 bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
428 break;
429
88a7a62a
SL
430 /* set/get local special characters */
431 case TIOCSLTC:
432 bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
433 break;
434
435 case TIOCGLTC:
436 bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
437 break;
438
439 /*
440 * Modify local mode word.
441 */
442 case TIOCLBIS:
443 tp->t_flags |= *(int *)data << 16;
444 break;
445
446 case TIOCLBIC:
447 tp->t_flags &= ~(*(int *)data << 16);
448 break;
449
450 case TIOCLSET:
451 tp->t_flags &= 0xffff;
452 tp->t_flags |= *(int *)data << 16;
453 break;
454
455 case TIOCLGET:
456 *(int *)data = tp->t_flags >> 16;
457 break;
458
459 /* should allow SPGRP and GPGRP only if tty open for reading */
460 case TIOCSPGRP:
461 tp->t_pgrp = *(int *)data;
462 break;
463
464 case TIOCGPGRP:
465 *(int *)data = tp->t_pgrp;
466 break;
467
89dc6dfb 468 default:
fc6972ae 469 return (-1);
89dc6dfb 470 }
fc6972ae 471 return (0);
89dc6dfb 472}
e1d74936
BJ
473
474ttnread(tp)
475 struct tty *tp;
476{
477 int nread = 0;
478
becb115c 479 if (tp->t_flags & PENDIN)
e1d74936
BJ
480 ttypend(tp);
481 nread = tp->t_canq.c_cc;
482 if (tp->t_flags & (RAW|CBREAK))
483 nread += tp->t_rawq.c_cc;
484 return (nread);
485}
486
941944c9 487ttselect(dev, rw)
e1d74936 488 dev_t dev;
941944c9 489 int rw;
e1d74936
BJ
490{
491 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
492 int nread;
941944c9 493 int s = spl5();
e1d74936 494
941944c9 495 switch (rw) {
e1d74936
BJ
496
497 case FREAD:
498 nread = ttnread(tp);
499 if (nread > 0)
941944c9 500 goto win;
89b8a44c 501 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 502 tp->t_state |= TS_RCOLL;
e1d74936
BJ
503 else
504 tp->t_rsel = u.u_procp;
941944c9 505 break;
e1d74936 506
941944c9
BJ
507 case FWRITE:
508 if (tp->t_outq.c_cc <= TTLOWAT(tp))
509 goto win;
941944c9
BJ
510 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
511 tp->t_state |= TS_WCOLL;
512 else
513 tp->t_wsel = u.u_procp;
514 break;
e1d74936 515 }
941944c9
BJ
516 splx(s);
517 return (0);
518win:
519 splx(s);
520 return (1);
e1d74936 521}
8bba2b8f 522
4147b3f6 523/*
becb115c 524 * Establish a process group for distribution of
4147b3f6 525 * quits and interrupts from the tty.
4147b3f6
BJ
526 */
527ttyopen(dev, tp)
4b72e2f9
SL
528 dev_t dev;
529 register struct tty *tp;
4147b3f6
BJ
530{
531 register struct proc *pp;
532
533 pp = u.u_procp;
534 tp->t_dev = dev;
4b72e2f9 535 if (pp->p_pgrp == 0) {
4147b3f6
BJ
536 u.u_ttyp = tp;
537 u.u_ttyd = dev;
538 if (tp->t_pgrp == 0)
539 tp->t_pgrp = pp->p_pid;
540 pp->p_pgrp = tp->t_pgrp;
541 }
542 tp->t_state &= ~TS_WOPEN;
543 tp->t_state |= TS_ISOPEN;
544 if (tp->t_line != NTTYDISC)
88a7a62a 545 ttywflush(tp);
fc6972ae 546 return (0);
4147b3f6
BJ
547}
548
549/*
550 * clean tp on last close
551 */
552ttyclose(tp)
4b72e2f9 553 register struct tty *tp;
4147b3f6
BJ
554{
555
556 if (tp->t_line) {
88a7a62a 557 ttywflush(tp);
4147b3f6
BJ
558 tp->t_line = 0;
559 return;
560 }
561 tp->t_pgrp = 0;
88a7a62a 562 ttywflush(tp);
4147b3f6
BJ
563 tp->t_state = 0;
564}
565
566/*
567 * reinput pending characters after state switch
568 * call at spl5().
569 */
570ttypend(tp)
4b72e2f9 571 register struct tty *tp;
4147b3f6
BJ
572{
573 struct clist tq;
574 register c;
575
becb115c
SL
576 tp->t_flags &= ~PENDIN;
577 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
578 tq = tp->t_rawq;
579 tp->t_rawq.c_cc = 0;
580 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
581 while ((c = getc(&tq)) >= 0)
582 ttyinput(c, tp);
becb115c 583 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
584}
585
586/*
becb115c
SL
587 * Place a character on raw TTY input queue,
588 * putting in delimiters and waking up top
589 * half as needed. Also echo if required.
590 * The arguments are the character and the
591 * appropriate tty structure.
4147b3f6
BJ
592 */
593ttyinput(c, tp)
4b72e2f9
SL
594 register c;
595 register struct tty *tp;
4147b3f6 596{
becb115c 597 register int t_flags = tp->t_flags;
4147b3f6
BJ
598 int i;
599
becb115c
SL
600 /*
601 * If input is pending take it first.
602 */
603 if (t_flags&PENDIN)
4147b3f6
BJ
604 ttypend(tp);
605 tk_nin++;
606 c &= 0377;
becb115c
SL
607
608 /*
609 * In tandem mode, check high water mark.
610 */
4147b3f6
BJ
611 if (t_flags&TANDEM)
612 ttyblock(tp);
becb115c
SL
613
614 if (t_flags&RAW) {
615 /*
616 * Raw mode, just put character
617 * in input q w/o interpretation.
618 */
619 if (tp->t_rawq.c_cc > TTYHOG)
88a7a62a 620 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
621 else {
622 if (putc(c, &tp->t_rawq) >= 0)
623 ttwakeup(tp);
624 ttyecho(c, tp);
4147b3f6 625 }
becb115c
SL
626 goto endcase;
627 }
628
629 /*
630 * Ignore any high bit added during
631 * previous ttyinput processing.
632 */
633 if ((tp->t_state&TS_TYPEN) == 0)
634 c &= 0177;
635 /*
636 * Check for literal nexting very first
637 */
638 if (tp->t_state&TS_LNCH) {
639 c |= 0200;
640 tp->t_state &= ~TS_LNCH;
641 }
642
643 /*
644 * Scan for special characters. This code
645 * is really just a big case statement with
646 * non-constant cases. The bottom of the
647 * case statement is labeled ``endcase'', so goto
648 * it after a case match, or similar.
649 */
650 if (tp->t_line == NTTYDISC) {
651 if (c == tp->t_lnextc) {
4147b3f6
BJ
652 if (tp->t_flags&ECHO)
653 ttyout("^\b", tp);
becb115c
SL
654 tp->t_state |= TS_LNCH;
655 goto endcase;
656 }
657 if (c == tp->t_flushc) {
658 if (tp->t_flags&FLUSHO)
659 tp->t_flags &= ~FLUSHO;
4147b3f6 660 else {
88a7a62a 661 ttyflush(tp, FWRITE);
4147b3f6 662 ttyecho(c, tp);
becb115c 663 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 664 ttyretype(tp);
becb115c 665 tp->t_flags |= FLUSHO;
4147b3f6 666 }
becb115c
SL
667 goto startoutput;
668 }
669 if (c == tp->t_suspc) {
670 if ((tp->t_flags&NOFLSH) == 0)
88a7a62a 671 ttyflush(tp, FREAD);
4147b3f6 672 ttyecho(c, tp);
becb115c
SL
673 gsignal(tp->t_pgrp, SIGTSTP);
674 goto endcase;
675 }
676 }
677
678 /*
679 * Handle start/stop characters.
680 */
681 if (c == tp->t_stopc) {
682 if ((tp->t_state&TS_TTSTOP) == 0) {
683 tp->t_state |= TS_TTSTOP;
684 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
685 return;
686 }
687 if (c != tp->t_startc)
688 return;
689 goto endcase;
690 }
691 if (c == tp->t_startc)
692 goto restartoutput;
693
694 /*
695 * Look for interrupt/quit chars.
696 */
697 if (c == tp->t_intrc || c == tp->t_quitc) {
698 if ((tp->t_flags&NOFLSH) == 0)
88a7a62a 699 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
700 ttyecho(c, tp);
701 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
702 goto endcase;
703 }
704
705 /*
706 * Cbreak mode, don't process line editing
707 * characters; check high water mark for wakeup.
708 */
709 if (t_flags&CBREAK) {
710 if (tp->t_rawq.c_cc > TTYHOG) {
4147b3f6
BJ
711 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
712 tp->t_line == NTTYDISC)
713 (void) ttyoutput(CTRL(g), tp);
714 } else if (putc(c, &tp->t_rawq) >= 0) {
715 ttwakeup(tp);
716 ttyecho(c, tp);
717 }
becb115c
SL
718 goto endcase;
719 }
720
721 /*
722 * From here on down cooked mode character
723 * processing takes place.
724 */
725 if ((tp->t_state&TS_QUOT) &&
726 (c == tp->t_erase || c == tp->t_kill)) {
727 ttyrub(unputc(&tp->t_rawq), tp);
728 c |= 0200;
729 }
730 if (c == tp->t_erase) {
731 if (tp->t_rawq.c_cc)
732 ttyrub(unputc(&tp->t_rawq), tp);
733 goto endcase;
734 }
735 if (c == tp->t_kill) {
736 if (tp->t_flags&CRTKIL &&
737 tp->t_rawq.c_cc == tp->t_rocount) {
738 while (tp->t_rawq.c_cc)
739 ttyrub(unputc(&tp->t_rawq), tp);
740 } else {
741 ttyecho(c, tp);
742 ttyecho('\n', tp);
743 while (getc(&tp->t_rawq) > 0)
744 ;
745 tp->t_rocount = 0;
746 }
747 tp->t_state &= ~TS_LOCAL;
748 goto endcase;
749 }
750
751 /*
752 * New line discipline,
753 * check word erase/reprint line.
754 */
755 if (tp->t_line == NTTYDISC) {
756 if (c == tp->t_werasc) {
757 if (tp->t_rawq.c_cc == 0)
758 goto endcase;
759 do {
760 c = unputc(&tp->t_rawq);
761 if (c != ' ' && c != '\t')
762 goto erasenb;
763 ttyrub(c, tp);
764 } while (tp->t_rawq.c_cc);
765 goto endcase;
766 erasenb:
767 do {
768 ttyrub(c, tp);
769 if (tp->t_rawq.c_cc == 0)
770 goto endcase;
771 c = unputc(&tp->t_rawq);
772 } while (c != ' ' && c != '\t');
773 (void) putc(c, &tp->t_rawq);
774 goto endcase;
775 }
776 if (c == tp->t_rprntc) {
777 ttyretype(tp);
778 goto endcase;
779 }
780 }
781
782 /*
783 * Check for input buffer overflow
784 */
7c9f96c0
SL
785 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
786 if (tp->t_line == NTTYDISC)
787 (void) ttyoutput(CTRL(g), tp);
becb115c 788 goto endcase;
7c9f96c0 789 }
becb115c
SL
790
791 /*
792 * Put data char in q for user and
793 * wakeup on seeing a line delimiter.
794 */
795 if (putc(c, &tp->t_rawq) >= 0) {
becb115c
SL
796 if (ttbreakc(c, tp)) {
797 tp->t_rocount = 0;
798 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 799 ttwakeup(tp);
becb115c
SL
800 } else if (tp->t_rocount++ == 0)
801 tp->t_rocol = tp->t_col;
802 tp->t_state &= ~TS_QUOT;
803 if (c == '\\')
804 tp->t_state |= TS_QUOT;
805 if (tp->t_state&TS_ERASE) {
806 tp->t_state &= ~TS_ERASE;
807 (void) ttyoutput('/', tp);
808 }
809 i = tp->t_col;
4147b3f6 810 ttyecho(c, tp);
becb115c
SL
811 if (c == tp->t_eofc && tp->t_flags&ECHO) {
812 i = MIN(2, tp->t_col - i);
813 while (i > 0) {
814 (void) ttyoutput('\b', tp);
815 i--;
816 }
817 }
4147b3f6 818 }
becb115c
SL
819
820endcase:
821 /*
822 * If DEC-style start/stop is enabled don't restart
823 * output until seeing the start character.
824 */
825 if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
826 tp->t_startc != tp->t_stopc)
4147b3f6 827 return;
becb115c
SL
828
829restartoutput:
4147b3f6 830 tp->t_state &= ~TS_TTSTOP;
becb115c
SL
831 tp->t_flags &= ~FLUSHO;
832
833startoutput:
4147b3f6
BJ
834 ttstart(tp);
835}
836
837/*
becb115c 838 * Put character on TTY output queue, adding delays,
4147b3f6 839 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
840 * This is called both from the top half for output,
841 * and from interrupt level for echoing.
4147b3f6
BJ
842 * The arguments are the character and the tty structure.
843 * Returns < 0 if putc succeeds, otherwise returns char to resend
844 * Must be recursive.
845 */
846ttyoutput(c, tp)
847 register c;
848 register struct tty *tp;
849{
850 register char *colp;
851 register ctype;
852
becb115c
SL
853 if (tp->t_flags & (RAW|LITOUT)) {
854 if (tp->t_flags&FLUSHO)
4147b3f6
BJ
855 return (-1);
856 if (putc(c, &tp->t_outq))
4b72e2f9 857 return (c);
4147b3f6
BJ
858 tk_nout++;
859 return (-1);
860 }
becb115c 861
4147b3f6 862 /*
becb115c
SL
863 * Ignore EOT in normal mode to avoid
864 * hanging up certain terminals.
4147b3f6
BJ
865 */
866 c &= 0177;
becb115c 867 if (c == CEOT && (tp->t_flags&CBREAK) == 0)
4147b3f6
BJ
868 return (-1);
869 /*
870 * Turn tabs to spaces as required
871 */
becb115c 872 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
4147b3f6
BJ
873 register int s;
874
875 c = 8 - (tp->t_col&7);
becb115c 876 if ((tp->t_flags&FLUSHO) == 0) {
4147b3f6
BJ
877 s = spl5(); /* don't interrupt tabs */
878 c -= b_to_q(" ", c, &tp->t_outq);
879 tk_nout += c;
880 splx(s);
881 }
882 tp->t_col += c;
883 return (c ? -1 : '\t');
884 }
885 tk_nout++;
886 /*
887 * for upper-case-only terminals,
888 * generate escapes.
889 */
890 if (tp->t_flags&LCASE) {
891 colp = "({)}!|^~'`";
4b72e2f9
SL
892 while (*colp++)
893 if (c == *colp++) {
4147b3f6
BJ
894 if (ttyoutput('\\', tp) >= 0)
895 return (c);
896 c = colp[-2];
897 break;
898 }
becb115c 899 if ('A' <= c && c <= 'Z') {
4147b3f6
BJ
900 if (ttyoutput('\\', tp) >= 0)
901 return (c);
becb115c 902 } else if ('a' <= c && c <= 'z')
4147b3f6
BJ
903 c += 'A' - 'a';
904 }
becb115c 905
4147b3f6
BJ
906 /*
907 * turn <nl> to <cr><lf> if desired.
908 */
becb115c 909 if (c == '\n' && tp->t_flags&CRMOD)
4147b3f6
BJ
910 if (ttyoutput('\r', tp) >= 0)
911 return (c);
becb115c 912 if (c == '~' && tp->t_flags&TILDE)
4147b3f6 913 c = '`';
becb115c 914 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
915 return (c);
916 /*
917 * Calculate delays.
918 * The numbers here represent clock ticks
919 * and are not necessarily optimal for all terminals.
920 * The delays are indicated by characters above 0200.
921 * In raw mode there are no delays and the
922 * transmission path is 8 bits wide.
becb115c
SL
923 *
924 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
4147b3f6
BJ
925 */
926 colp = &tp->t_col;
927 ctype = partab[c];
928 c = 0;
929 switch (ctype&077) {
930
931 case ORDINARY:
932 (*colp)++;
933
934 case CONTROL:
935 break;
936
937 case BACKSPACE:
938 if (*colp)
939 (*colp)--;
940 break;
941
942 case NEWLINE:
943 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 944 if (ctype == 1) { /* tty 37 */
88a7a62a 945 if (*colp > 0)
4147b3f6 946 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
becb115c 947 } else if (ctype == 2) /* vt05 */
4147b3f6 948 c = 6;
4147b3f6
BJ
949 *colp = 0;
950 break;
951
952 case TAB:
953 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 954 if (ctype == 1) { /* tty 37 */
4147b3f6 955 c = 1 - (*colp | ~07);
4b72e2f9 956 if (c < 5)
4147b3f6
BJ
957 c = 0;
958 }
959 *colp |= 07;
960 (*colp)++;
961 break;
962
963 case VTAB:
becb115c 964 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
965 c = 0177;
966 break;
967
968 case RETURN:
969 ctype = (tp->t_flags >> 12) & 03;
becb115c 970 if (ctype == 1) /* tn 300 */
4147b3f6 971 c = 5;
becb115c 972 else if (ctype == 2) /* ti 700 */
4147b3f6 973 c = 10;
becb115c 974 else if (ctype == 3) { /* concept 100 */
4147b3f6 975 int i;
becb115c 976
4147b3f6 977 if ((i = *colp) >= 0)
becb115c 978 for (; i < 9; i++)
4147b3f6
BJ
979 (void) putc(0177, &tp->t_outq);
980 }
981 *colp = 0;
982 }
becb115c 983 if (c && (tp->t_flags&FLUSHO) == 0)
4147b3f6
BJ
984 (void) putc(c|0200, &tp->t_outq);
985 return (-1);
986}
987
988/*
989 * Called from device's read routine after it has
990 * calculated the tty-structure given as argument.
991 */
d6d7360b 992ttread(tp, uio)
4b72e2f9 993 register struct tty *tp;
d6d7360b 994 struct uio *uio;
4147b3f6
BJ
995{
996 register struct clist *qp;
becb115c 997 register c, t_flags;
875a1e2c 998 int s, first, error = 0;
4147b3f6
BJ
999
1000 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 1001 return (EIO);
4147b3f6 1002loop:
becb115c
SL
1003 /*
1004 * Take any pending input first.
1005 */
875a1e2c 1006 s = spl5();
becb115c 1007 if (tp->t_flags&PENDIN)
4147b3f6 1008 ttypend(tp);
875a1e2c 1009 splx(s);
becb115c
SL
1010
1011 /*
1012 * Hang process if it's in the background.
1013 */
4147b3f6
BJ
1014 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
1015 if (u.u_signal[SIGTTIN] == SIG_IGN ||
1016 u.u_signal[SIGTTIN] == SIG_HOLD ||
1017/*
1018 (u.u_procp->p_flag&SDETACH) ||
1019*/
1020 u.u_procp->p_flag&SVFORK)
840510a3 1021 return (EIO);
4147b3f6
BJ
1022 gsignal(u.u_procp->p_pgrp, SIGTTIN);
1023 sleep((caddr_t)&lbolt, TTIPRI);
1024 }
becb115c
SL
1025 t_flags = tp->t_flags;
1026
1027 /*
1028 * In raw mode take characters directly from the
1029 * raw queue w/o processing. Interlock against
1030 * device interrupts when interrogating rawq.
1031 */
1032 if (t_flags&RAW) {
875a1e2c 1033 s = spl5();
4147b3f6 1034 if (tp->t_rawq.c_cc <= 0) {
becb115c 1035 if ((tp->t_state&TS_CARR_ON) == 0 ||
4147b3f6 1036 (tp->t_state&TS_NBIO)) {
875a1e2c 1037 splx(s);
becb115c 1038 return (0);
4147b3f6
BJ
1039 }
1040 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1041 splx(s);
4147b3f6
BJ
1042 goto loop;
1043 }
875a1e2c
SL
1044 splx(s);
1045 while (!error && tp->t_rawq.c_cc && uio->uio_iovcnt)
840510a3 1046 error = passuc(getc(&tp->t_rawq), uio);
875a1e2c 1047 goto checktandem;
becb115c
SL
1048 }
1049
1050 /*
1051 * In cbreak mode use the rawq, otherwise
1052 * take characters from the canonicalized q.
1053 */
1054 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1055
1056 /*
1057 * No input, sleep on rawq awaiting hardware
1058 * receipt and notification.
1059 */
875a1e2c 1060 s = spl5();
becb115c
SL
1061 if (qp->c_cc <= 0) {
1062 if ((tp->t_state&TS_CARR_ON) == 0 ||
1063 (tp->t_state&TS_NBIO)) {
875a1e2c 1064 splx(s);
becb115c 1065 return (EWOULDBLOCK);
4147b3f6 1066 }
becb115c 1067 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1068 splx(s);
becb115c
SL
1069 goto loop;
1070 }
875a1e2c 1071 splx(s);
becb115c
SL
1072
1073 /*
1074 * Input present, perform input mapping
1075 * and processing (we're not in raw mode).
1076 */
1077 first = 1;
1078 while ((c = getc(qp)) >= 0) {
1079 if (t_flags&CRMOD && c == '\r')
1080 c = '\n';
1081 /*
1082 * Hack lower case simulation on
1083 * upper case only terminals.
1084 */
1085 if (t_flags&LCASE && c <= 0177)
1086 if (tp->t_state&TS_BKSL) {
1087 if (maptab[c])
1088 c = maptab[c];
1089 tp->t_state &= ~TS_BKSL;
1090 } else if (c >= 'A' && c <= 'Z')
1091 c += 'a' - 'A';
1092 else if (c == '\\') {
1093 tp->t_state |= TS_BKSL;
1094 continue;
4147b3f6 1095 }
becb115c
SL
1096 /*
1097 * Check for delayed suspend character.
1098 */
1099 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1100 gsignal(tp->t_pgrp, SIGTSTP);
1101 if (first) {
1102 sleep((caddr_t)&lbolt, TTIPRI);
1103 goto loop;
1104 }
1105 break;
4147b3f6 1106 }
becb115c
SL
1107 /*
1108 * Interpret EOF only in cooked mode.
1109 */
1110 if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1111 break;
1112 /*
1113 * Give user character.
1114 */
1115 error = passuc(c & 0177, uio);
1116 if (error)
1117 break;
1118 if (uio->uio_iovcnt == 0)
1119 break;
1120 /*
1121 * In cooked mode check for a "break character"
1122 * marking the end of a "line of input".
1123 */
1124 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1125 break;
1126 first = 0;
4147b3f6 1127 }
becb115c
SL
1128 tp->t_state &= ~TS_BKSL;
1129
875a1e2c 1130checktandem:
becb115c
SL
1131 /*
1132 * Look to unblock output now that (presumably)
1133 * the input queue has gone down.
1134 */
875a1e2c 1135 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
becb115c 1136 if (putc(tp->t_startc, &tp->t_outq) == 0) {
4147b3f6
BJ
1137 tp->t_state &= ~TS_TBLOCK;
1138 ttstart(tp);
1139 }
840510a3 1140 return (error);
4147b3f6
BJ
1141}
1142
1143/*
1144 * Called from the device's write routine after it has
1145 * calculated the tty-structure given as argument.
1146 */
913ea2d1 1147ttwrite(tp, uio)
4b72e2f9 1148 register struct tty *tp;
becb115c 1149 register struct uio *uio;
4147b3f6 1150{
4147b3f6 1151 register char *cp;
becb115c
SL
1152 register int cc, ce, c;
1153 int i, hiwat, cnt, error, s;
4147b3f6 1154 char obuf[OBUFSIZ];
4147b3f6 1155
becb115c 1156 if ((tp->t_state&TS_CARR_ON) == 0)
840510a3 1157 return (EIO);
becb115c
SL
1158 hiwat = TTHIWAT(tp);
1159 cnt = uio->uio_resid;
1160 error = 0;
4147b3f6 1161loop:
becb115c
SL
1162 /*
1163 * Hang the process if it's in the background.
1164 */
4147b3f6 1165 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
becb115c 1166 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
4147b3f6
BJ
1167 u.u_signal[SIGTTOU] != SIG_IGN &&
1168 u.u_signal[SIGTTOU] != SIG_HOLD
1169/*
1170 &&
1171 (u.u_procp->p_flag&SDETACH)==0) {
1172*/
1173 ) {
1174 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1175 sleep((caddr_t)&lbolt, TTIPRI);
1176 }
becb115c
SL
1177
1178 /*
1179 * Process the user's data in at most OBUFSIZ
1180 * chunks. Perform lower case simulation and
1181 * similar hacks. Keep track of high water
1182 * mark, sleep on overflow awaiting device aid
1183 * in acquiring new space.
1184 */
913ea2d1 1185 while (uio->uio_resid > 0) {
becb115c
SL
1186 /*
1187 * Grab a hunk of data from the user.
1188 */
913ea2d1
BJ
1189 cc = uio->uio_iov->iov_len;
1190 if (cc == 0) {
1191 uio->uio_iovcnt--;
1192 uio->uio_iov++;
1193 if (uio->uio_iovcnt < 0)
1194 panic("ttwrite");
1195 continue;
1196 }
1197 if (cc > OBUFSIZ)
1198 cc = OBUFSIZ;
4147b3f6 1199 cp = obuf;
88a7a62a 1200 error = uiomove(cp, cc, UIO_WRITE, uio);
840510a3 1201 if (error)
4147b3f6
BJ
1202 break;
1203 if (tp->t_outq.c_cc > hiwat)
1204 goto ovhiwat;
becb115c 1205 if (tp->t_flags&FLUSHO)
4147b3f6 1206 continue;
becb115c
SL
1207 /*
1208 * If we're mapping lower case or kludging tildes,
1209 * then we've got to look at each character, so
1210 * just feed the stuff to ttyoutput...
1211 */
1212 if (tp->t_flags & (LCASE|TILDE)) {
1213 while (cc > 0) {
4147b3f6
BJ
1214 c = *cp++;
1215 tp->t_rocount = 0;
4b72e2f9 1216 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1217 /* out of clists, wait a bit */
1218 ttstart(tp);
1219 sleep((caddr_t)&lbolt, TTOPRI);
1220 tp->t_rocount = 0;
1221 }
1222 --cc;
1223 if (tp->t_outq.c_cc > hiwat)
1224 goto ovhiwat;
1225 }
1226 continue;
1227 }
becb115c
SL
1228 /*
1229 * If nothing fancy need be done, grab those characters we
1230 * can handle without any of ttyoutput's processing and
1231 * just transfer them to the output q. For those chars
1232 * which require special processing (as indicated by the
1233 * bits in partab), call ttyoutput. After processing
1234 * a hunk of data, look for FLUSHO so ^O's will take effect
1235 * immediately.
1236 */
1237 while (cc > 0) {
1238 if (tp->t_flags & (RAW|LITOUT))
4147b3f6
BJ
1239 ce = cc;
1240 else {
88a7a62a
SL
1241 ce = cc - scanc((unsigned)cc, (caddr_t)cp,
1242 (caddr_t)partab, 077);
becb115c
SL
1243 /*
1244 * If ce is zero, then we're processing
1245 * a special character through ttyoutput.
1246 */
1247 if (ce == 0) {
4147b3f6
BJ
1248 tp->t_rocount = 0;
1249 if (ttyoutput(*cp, tp) >= 0) {
becb115c 1250 /* no c-lists, wait a bit */
4147b3f6
BJ
1251 ttstart(tp);
1252 sleep((caddr_t)&lbolt, TTOPRI);
1253 continue;
1254 }
becb115c
SL
1255 cp++, cc--;
1256 if (tp->t_flags&FLUSHO ||
1257 tp->t_outq.c_cc > hiwat)
4147b3f6 1258 goto ovhiwat;
becb115c 1259 continue;
4147b3f6
BJ
1260 }
1261 }
becb115c
SL
1262 /*
1263 * A bunch of normal characters have been found,
1264 * transfer them en masse to the output queue and
1265 * continue processing at the top of the loop.
1266 * If there are any further characters in this
1267 * <= OBUFSIZ chunk, the first should be a character
1268 * requiring special handling by ttyoutput.
1269 */
4147b3f6 1270 tp->t_rocount = 0;
becb115c
SL
1271 i = b_to_q(cp, ce, &tp->t_outq);
1272 ce -= i;
1273 tp->t_col += ce;
1274 cp += ce, cc -= ce, tk_nout += ce;
1275 if (i > 0) {
1276 /* out of c-lists, wait a bit */
4147b3f6
BJ
1277 ttstart(tp);
1278 sleep((caddr_t)&lbolt, TTOPRI);
1279 }
becb115c 1280 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1281 goto ovhiwat;
1282 }
1283 }
1284 ttstart(tp);
840510a3 1285 return (error);
4147b3f6
BJ
1286
1287ovhiwat:
becb115c
SL
1288 s = spl5();
1289 if (cc != 0) {
1290 uio->uio_iov->iov_base -= cc;
1291 uio->uio_iov->iov_len += cc;
1292 uio->uio_resid += cc;
1293 uio->uio_offset -= cc;
1294 }
1295 /*
1296 * This can only occur if FLUSHO
1297 * is also set in t_flags.
1298 */
4147b3f6 1299 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1300 splx(s);
4147b3f6
BJ
1301 goto loop;
1302 }
1303 ttstart(tp);
becb115c 1304 if (tp->t_state&TS_NBIO) {
913ea2d1 1305 if (uio->uio_resid == cnt)
840510a3
BJ
1306 return (EWOULDBLOCK);
1307 return (0);
4147b3f6
BJ
1308 }
1309 tp->t_state |= TS_ASLEEP;
1310 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1311 splx(s);
4147b3f6
BJ
1312 goto loop;
1313}
1314
1315/*
1316 * Rubout one character from the rawq of tp
1317 * as cleanly as possible.
1318 */
1319ttyrub(c, tp)
4b72e2f9
SL
1320 register c;
1321 register struct tty *tp;
4147b3f6
BJ
1322{
1323 register char *cp;
1324 register int savecol;
1325 int s;
1326 char *nextc();
1327
becb115c 1328 if ((tp->t_flags&ECHO) == 0)
4147b3f6 1329 return;
becb115c 1330 tp->t_flags &= ~FLUSHO;
4147b3f6 1331 c &= 0377;
becb115c 1332 if (tp->t_flags&CRTBS) {
4147b3f6
BJ
1333 if (tp->t_rocount == 0) {
1334 /*
1335 * Screwed by ttwrite; retype
1336 */
1337 ttyretype(tp);
1338 return;
1339 }
becb115c 1340 if (c == ('\t'|0200) || c == ('\n'|0200))
4147b3f6 1341 ttyrubo(tp, 2);
becb115c 1342 else switch (partab[c&=0177]&0177) {
4147b3f6
BJ
1343
1344 case ORDINARY:
1345 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1346 ttyrubo(tp, 2);
1347 else
1348 ttyrubo(tp, 1);
1349 break;
1350
1351 case VTAB:
1352 case BACKSPACE:
1353 case CONTROL:
1354 case RETURN:
becb115c 1355 if (tp->t_flags&CTLECH)
4147b3f6
BJ
1356 ttyrubo(tp, 2);
1357 break;
1358
1359 case TAB:
1360 if (tp->t_rocount < tp->t_rawq.c_cc) {
1361 ttyretype(tp);
1362 return;
1363 }
1364 s = spl5();
1365 savecol = tp->t_col;
becb115c
SL
1366 tp->t_state |= TS_CNTTB;
1367 tp->t_flags |= FLUSHO;
4147b3f6 1368 tp->t_col = tp->t_rocol;
becb115c
SL
1369 cp = tp->t_rawq.c_cf;
1370 for (; cp; cp = nextc(&tp->t_rawq, cp))
4147b3f6 1371 ttyecho(*cp, tp);
becb115c
SL
1372 tp->t_flags &= ~FLUSHO;
1373 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1374 splx(s);
1375 /*
1376 * savecol will now be length of the tab
1377 */
1378 savecol -= tp->t_col;
1379 tp->t_col += savecol;
1380 if (savecol > 8)
1381 savecol = 8; /* overflow screw */
1382 while (--savecol >= 0)
1383 (void) ttyoutput('\b', tp);
1384 break;
1385
1386 default:
1387 panic("ttyrub");
1388 }
becb115c
SL
1389 } else if (tp->t_flags&PRTERA) {
1390 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1391 (void) ttyoutput('\\', tp);
becb115c 1392 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1393 }
1394 ttyecho(c, tp);
1395 } else
1396 ttyecho(tp->t_erase, tp);
1397 tp->t_rocount--;
1398}
1399
1400/*
1401 * Crt back over cnt chars perhaps
1402 * erasing them.
1403 */
1404ttyrubo(tp, cnt)
4b72e2f9
SL
1405 register struct tty *tp;
1406 int cnt;
4147b3f6 1407{
becb115c 1408 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
4147b3f6
BJ
1409
1410 while (--cnt >= 0)
becb115c 1411 ttyout(rubostring, tp);
4147b3f6
BJ
1412}
1413
1414/*
1415 * Reprint the rawq line.
1416 * We assume c_cc has already been checked.
1417 */
1418ttyretype(tp)
4b72e2f9 1419 register struct tty *tp;
4147b3f6
BJ
1420{
1421 register char *cp;
1422 char *nextc();
1423 int s;
1424
becb115c
SL
1425 if (tp->t_rprntc != 0377)
1426 ttyecho(tp->t_rprntc, tp);
4147b3f6
BJ
1427 (void) ttyoutput('\n', tp);
1428 s = spl5();
1429 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1430 ttyecho(*cp, tp);
1431 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1432 ttyecho(*cp, tp);
becb115c 1433 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1434 splx(s);
1435 tp->t_rocount = tp->t_rawq.c_cc;
1436 tp->t_rocol = 0;
1437}
1438
1439/*
1440 * Echo a typed character to the terminal
1441 */
1442ttyecho(c, tp)
4b72e2f9
SL
1443 register c;
1444 register struct tty *tp;
4147b3f6
BJ
1445{
1446
becb115c
SL
1447 if ((tp->t_state&TS_CNTTB) == 0)
1448 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
1449 if ((tp->t_flags&ECHO) == 0)
1450 return;
1451 c &= 0377;
1452 if (tp->t_flags&RAW) {
1453 (void) ttyoutput(c, tp);
1454 return;
1455 }
1456 if (c == '\r' && tp->t_flags&CRMOD)
1457 c = '\n';
becb115c 1458 if (tp->t_flags&CTLECH) {
4147b3f6
BJ
1459 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1460 (void) ttyoutput('^', tp);
1461 c &= 0177;
1462 if (c == 0177)
1463 c = '?';
1464 else if (tp->t_flags&LCASE)
1465 c += 'a' - 1;
1466 else
1467 c += 'A' - 1;
1468 }
1469 }
1470 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1471 c += 'a' - 'A';
becb115c 1472 (void) ttyoutput(c&0177, tp);
4147b3f6
BJ
1473}
1474
1475/*
1476 * Is c a break char for tp?
1477 */
1478ttbreakc(c, tp)
4b72e2f9
SL
1479 register c;
1480 register struct tty *tp;
4147b3f6 1481{
becb115c 1482 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
4147b3f6
BJ
1483 c == '\r' && (tp->t_flags&CRMOD));
1484}
1485
1486/*
1487 * send string cp to tp
1488 */
1489ttyout(cp, tp)
4b72e2f9
SL
1490 register char *cp;
1491 register struct tty *tp;
4147b3f6
BJ
1492{
1493 register char c;
1494
1495 while (c = *cp++)
1496 (void) ttyoutput(c, tp);
1497}
1498
1499ttwakeup(tp)
1500 struct tty *tp;
1501{
1502
1503 if (tp->t_rsel) {
1504 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1505 tp->t_state &= ~TS_RCOLL;
1506 tp->t_rsel = 0;
1507 }
88a7a62a
SL
1508 if (tp->t_state & TS_ASYNC)
1509 gsignal(tp->t_pgrp, SIGIO);
4147b3f6
BJ
1510 wakeup((caddr_t)&tp->t_rawq);
1511}
1512
e3d5bfde 1513#if !defined(vax)
becb115c
SL
1514scanc(size, cp, table, mask)
1515 register int size;
1516 register char *cp, table[];
1517 register int mask;
4147b3f6 1518{
becb115c 1519 register int i = 0;
4147b3f6 1520
becb115c
SL
1521 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
1522 i++;
1523 return (i);
4147b3f6 1524}
becb115c 1525#endif