must rm before ln
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
b968e450 1/* tty.c 4.42 83/06/13 */
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;
383 ttwakeup(tp);
384 }
385 }
386 tp->t_flags = newflags;
387 if (tp->t_flags&RAW) {
388 tp->t_state &= ~TS_TTSTOP;
389 ttstart(tp);
390 }
391 splx(s);
392 break;
393 }
394
395 /* send current parameters to user */
396 case TIOCGETP: {
397 register struct sgttyb *sg = (struct sgttyb *)data;
398
399 sg->sg_ispeed = tp->t_ispeed;
400 sg->sg_ospeed = tp->t_ospeed;
401 sg->sg_erase = tp->t_erase;
402 sg->sg_kill = tp->t_kill;
403 sg->sg_flags = tp->t_flags;
404 break;
405 }
406
407 case FIONBIO:
408 if (*(int *)data)
409 tp->t_state |= TS_NBIO;
410 else
411 tp->t_state &= ~TS_NBIO;
412 break;
413
414 case FIOASYNC:
415 if (*(int *)data)
416 tp->t_state |= TS_ASYNC;
417 else
418 tp->t_state &= ~TS_ASYNC;
419 break;
420
b968e450
SL
421 case TIOCGETC:
422 bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
423 break;
424
425 case TIOCSETC:
426 bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
427 break;
428
88a7a62a
SL
429 /* set/get local special characters */
430 case TIOCSLTC:
431 bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
432 break;
433
434 case TIOCGLTC:
435 bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
436 break;
437
438 /*
439 * Modify local mode word.
440 */
441 case TIOCLBIS:
442 tp->t_flags |= *(int *)data << 16;
443 break;
444
445 case TIOCLBIC:
446 tp->t_flags &= ~(*(int *)data << 16);
447 break;
448
449 case TIOCLSET:
450 tp->t_flags &= 0xffff;
451 tp->t_flags |= *(int *)data << 16;
452 break;
453
454 case TIOCLGET:
455 *(int *)data = tp->t_flags >> 16;
456 break;
457
458 /* should allow SPGRP and GPGRP only if tty open for reading */
459 case TIOCSPGRP:
460 tp->t_pgrp = *(int *)data;
461 break;
462
463 case TIOCGPGRP:
464 *(int *)data = tp->t_pgrp;
465 break;
466
89dc6dfb 467 default:
fc6972ae 468 return (-1);
89dc6dfb 469 }
fc6972ae 470 return (0);
89dc6dfb 471}
e1d74936
BJ
472
473ttnread(tp)
474 struct tty *tp;
475{
476 int nread = 0;
477
becb115c 478 if (tp->t_flags & PENDIN)
e1d74936
BJ
479 ttypend(tp);
480 nread = tp->t_canq.c_cc;
481 if (tp->t_flags & (RAW|CBREAK))
482 nread += tp->t_rawq.c_cc;
483 return (nread);
484}
485
941944c9 486ttselect(dev, rw)
e1d74936 487 dev_t dev;
941944c9 488 int rw;
e1d74936
BJ
489{
490 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
491 int nread;
941944c9 492 int s = spl5();
e1d74936 493
941944c9 494 switch (rw) {
e1d74936
BJ
495
496 case FREAD:
497 nread = ttnread(tp);
498 if (nread > 0)
941944c9 499 goto win;
89b8a44c 500 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 501 tp->t_state |= TS_RCOLL;
e1d74936
BJ
502 else
503 tp->t_rsel = u.u_procp;
941944c9 504 break;
e1d74936 505
941944c9
BJ
506 case FWRITE:
507 if (tp->t_outq.c_cc <= TTLOWAT(tp))
508 goto win;
941944c9
BJ
509 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
510 tp->t_state |= TS_WCOLL;
511 else
512 tp->t_wsel = u.u_procp;
513 break;
e1d74936 514 }
941944c9
BJ
515 splx(s);
516 return (0);
517win:
518 splx(s);
519 return (1);
e1d74936 520}
8bba2b8f 521
4147b3f6 522/*
becb115c 523 * Establish a process group for distribution of
4147b3f6 524 * quits and interrupts from the tty.
4147b3f6
BJ
525 */
526ttyopen(dev, tp)
4b72e2f9
SL
527 dev_t dev;
528 register struct tty *tp;
4147b3f6
BJ
529{
530 register struct proc *pp;
531
532 pp = u.u_procp;
533 tp->t_dev = dev;
4b72e2f9 534 if (pp->p_pgrp == 0) {
4147b3f6
BJ
535 u.u_ttyp = tp;
536 u.u_ttyd = dev;
537 if (tp->t_pgrp == 0)
538 tp->t_pgrp = pp->p_pid;
539 pp->p_pgrp = tp->t_pgrp;
540 }
541 tp->t_state &= ~TS_WOPEN;
542 tp->t_state |= TS_ISOPEN;
543 if (tp->t_line != NTTYDISC)
88a7a62a 544 ttywflush(tp);
fc6972ae 545 return (0);
4147b3f6
BJ
546}
547
548/*
549 * clean tp on last close
550 */
551ttyclose(tp)
4b72e2f9 552 register struct tty *tp;
4147b3f6
BJ
553{
554
555 if (tp->t_line) {
88a7a62a 556 ttywflush(tp);
4147b3f6
BJ
557 tp->t_line = 0;
558 return;
559 }
560 tp->t_pgrp = 0;
88a7a62a 561 ttywflush(tp);
4147b3f6
BJ
562 tp->t_state = 0;
563}
564
565/*
566 * reinput pending characters after state switch
567 * call at spl5().
568 */
569ttypend(tp)
4b72e2f9 570 register struct tty *tp;
4147b3f6
BJ
571{
572 struct clist tq;
573 register c;
574
becb115c
SL
575 tp->t_flags &= ~PENDIN;
576 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
577 tq = tp->t_rawq;
578 tp->t_rawq.c_cc = 0;
579 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
580 while ((c = getc(&tq)) >= 0)
581 ttyinput(c, tp);
becb115c 582 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
583}
584
585/*
becb115c
SL
586 * Place a character on raw TTY input queue,
587 * putting in delimiters and waking up top
588 * half as needed. Also echo if required.
589 * The arguments are the character and the
590 * appropriate tty structure.
4147b3f6
BJ
591 */
592ttyinput(c, tp)
4b72e2f9
SL
593 register c;
594 register struct tty *tp;
4147b3f6 595{
becb115c 596 register int t_flags = tp->t_flags;
4147b3f6
BJ
597 int i;
598
becb115c
SL
599 /*
600 * If input is pending take it first.
601 */
602 if (t_flags&PENDIN)
4147b3f6
BJ
603 ttypend(tp);
604 tk_nin++;
605 c &= 0377;
becb115c
SL
606
607 /*
608 * In tandem mode, check high water mark.
609 */
4147b3f6
BJ
610 if (t_flags&TANDEM)
611 ttyblock(tp);
becb115c
SL
612
613 if (t_flags&RAW) {
614 /*
615 * Raw mode, just put character
616 * in input q w/o interpretation.
617 */
618 if (tp->t_rawq.c_cc > TTYHOG)
88a7a62a 619 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
620 else {
621 if (putc(c, &tp->t_rawq) >= 0)
622 ttwakeup(tp);
623 ttyecho(c, tp);
4147b3f6 624 }
becb115c
SL
625 goto endcase;
626 }
627
628 /*
629 * Ignore any high bit added during
630 * previous ttyinput processing.
631 */
632 if ((tp->t_state&TS_TYPEN) == 0)
633 c &= 0177;
634 /*
635 * Check for literal nexting very first
636 */
637 if (tp->t_state&TS_LNCH) {
638 c |= 0200;
639 tp->t_state &= ~TS_LNCH;
640 }
641
642 /*
643 * Scan for special characters. This code
644 * is really just a big case statement with
645 * non-constant cases. The bottom of the
646 * case statement is labeled ``endcase'', so goto
647 * it after a case match, or similar.
648 */
649 if (tp->t_line == NTTYDISC) {
650 if (c == tp->t_lnextc) {
4147b3f6
BJ
651 if (tp->t_flags&ECHO)
652 ttyout("^\b", tp);
becb115c
SL
653 tp->t_state |= TS_LNCH;
654 goto endcase;
655 }
656 if (c == tp->t_flushc) {
657 if (tp->t_flags&FLUSHO)
658 tp->t_flags &= ~FLUSHO;
4147b3f6 659 else {
88a7a62a 660 ttyflush(tp, FWRITE);
4147b3f6 661 ttyecho(c, tp);
becb115c 662 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 663 ttyretype(tp);
becb115c 664 tp->t_flags |= FLUSHO;
4147b3f6 665 }
becb115c
SL
666 goto startoutput;
667 }
668 if (c == tp->t_suspc) {
669 if ((tp->t_flags&NOFLSH) == 0)
88a7a62a 670 ttyflush(tp, FREAD);
4147b3f6 671 ttyecho(c, tp);
becb115c
SL
672 gsignal(tp->t_pgrp, SIGTSTP);
673 goto endcase;
674 }
675 }
676
677 /*
678 * Handle start/stop characters.
679 */
680 if (c == tp->t_stopc) {
681 if ((tp->t_state&TS_TTSTOP) == 0) {
682 tp->t_state |= TS_TTSTOP;
683 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
684 return;
685 }
686 if (c != tp->t_startc)
687 return;
688 goto endcase;
689 }
690 if (c == tp->t_startc)
691 goto restartoutput;
692
693 /*
694 * Look for interrupt/quit chars.
695 */
696 if (c == tp->t_intrc || c == tp->t_quitc) {
697 if ((tp->t_flags&NOFLSH) == 0)
88a7a62a 698 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
699 ttyecho(c, tp);
700 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
701 goto endcase;
702 }
703
704 /*
705 * Cbreak mode, don't process line editing
706 * characters; check high water mark for wakeup.
707 */
708 if (t_flags&CBREAK) {
709 if (tp->t_rawq.c_cc > TTYHOG) {
4147b3f6
BJ
710 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
711 tp->t_line == NTTYDISC)
712 (void) ttyoutput(CTRL(g), tp);
713 } else if (putc(c, &tp->t_rawq) >= 0) {
714 ttwakeup(tp);
715 ttyecho(c, tp);
716 }
becb115c
SL
717 goto endcase;
718 }
719
720 /*
721 * From here on down cooked mode character
722 * processing takes place.
723 */
724 if ((tp->t_state&TS_QUOT) &&
725 (c == tp->t_erase || c == tp->t_kill)) {
726 ttyrub(unputc(&tp->t_rawq), tp);
727 c |= 0200;
728 }
729 if (c == tp->t_erase) {
730 if (tp->t_rawq.c_cc)
731 ttyrub(unputc(&tp->t_rawq), tp);
732 goto endcase;
733 }
734 if (c == tp->t_kill) {
735 if (tp->t_flags&CRTKIL &&
736 tp->t_rawq.c_cc == tp->t_rocount) {
737 while (tp->t_rawq.c_cc)
738 ttyrub(unputc(&tp->t_rawq), tp);
739 } else {
740 ttyecho(c, tp);
741 ttyecho('\n', tp);
742 while (getc(&tp->t_rawq) > 0)
743 ;
744 tp->t_rocount = 0;
745 }
746 tp->t_state &= ~TS_LOCAL;
747 goto endcase;
748 }
749
750 /*
751 * New line discipline,
752 * check word erase/reprint line.
753 */
754 if (tp->t_line == NTTYDISC) {
755 if (c == tp->t_werasc) {
756 if (tp->t_rawq.c_cc == 0)
757 goto endcase;
758 do {
759 c = unputc(&tp->t_rawq);
760 if (c != ' ' && c != '\t')
761 goto erasenb;
762 ttyrub(c, tp);
763 } while (tp->t_rawq.c_cc);
764 goto endcase;
765 erasenb:
766 do {
767 ttyrub(c, tp);
768 if (tp->t_rawq.c_cc == 0)
769 goto endcase;
770 c = unputc(&tp->t_rawq);
771 } while (c != ' ' && c != '\t');
772 (void) putc(c, &tp->t_rawq);
773 goto endcase;
774 }
775 if (c == tp->t_rprntc) {
776 ttyretype(tp);
777 goto endcase;
778 }
779 }
780
781 /*
782 * Check for input buffer overflow
783 */
7c9f96c0
SL
784 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
785 if (tp->t_line == NTTYDISC)
786 (void) ttyoutput(CTRL(g), tp);
becb115c 787 goto endcase;
7c9f96c0 788 }
becb115c
SL
789
790 /*
791 * Put data char in q for user and
792 * wakeup on seeing a line delimiter.
793 */
794 if (putc(c, &tp->t_rawq) >= 0) {
becb115c
SL
795 if (ttbreakc(c, tp)) {
796 tp->t_rocount = 0;
797 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 798 ttwakeup(tp);
becb115c
SL
799 } else if (tp->t_rocount++ == 0)
800 tp->t_rocol = tp->t_col;
801 tp->t_state &= ~TS_QUOT;
802 if (c == '\\')
803 tp->t_state |= TS_QUOT;
804 if (tp->t_state&TS_ERASE) {
805 tp->t_state &= ~TS_ERASE;
806 (void) ttyoutput('/', tp);
807 }
808 i = tp->t_col;
4147b3f6 809 ttyecho(c, tp);
becb115c
SL
810 if (c == tp->t_eofc && tp->t_flags&ECHO) {
811 i = MIN(2, tp->t_col - i);
812 while (i > 0) {
813 (void) ttyoutput('\b', tp);
814 i--;
815 }
816 }
4147b3f6 817 }
becb115c
SL
818
819endcase:
820 /*
821 * If DEC-style start/stop is enabled don't restart
822 * output until seeing the start character.
823 */
824 if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
825 tp->t_startc != tp->t_stopc)
4147b3f6 826 return;
becb115c
SL
827
828restartoutput:
4147b3f6 829 tp->t_state &= ~TS_TTSTOP;
becb115c
SL
830 tp->t_flags &= ~FLUSHO;
831
832startoutput:
4147b3f6
BJ
833 ttstart(tp);
834}
835
836/*
becb115c 837 * Put character on TTY output queue, adding delays,
4147b3f6 838 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
839 * This is called both from the top half for output,
840 * and from interrupt level for echoing.
4147b3f6
BJ
841 * The arguments are the character and the tty structure.
842 * Returns < 0 if putc succeeds, otherwise returns char to resend
843 * Must be recursive.
844 */
845ttyoutput(c, tp)
846 register c;
847 register struct tty *tp;
848{
849 register char *colp;
850 register ctype;
851
becb115c
SL
852 if (tp->t_flags & (RAW|LITOUT)) {
853 if (tp->t_flags&FLUSHO)
4147b3f6
BJ
854 return (-1);
855 if (putc(c, &tp->t_outq))
4b72e2f9 856 return (c);
4147b3f6
BJ
857 tk_nout++;
858 return (-1);
859 }
becb115c 860
4147b3f6 861 /*
becb115c
SL
862 * Ignore EOT in normal mode to avoid
863 * hanging up certain terminals.
4147b3f6
BJ
864 */
865 c &= 0177;
becb115c 866 if (c == CEOT && (tp->t_flags&CBREAK) == 0)
4147b3f6
BJ
867 return (-1);
868 /*
869 * Turn tabs to spaces as required
870 */
becb115c 871 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
4147b3f6
BJ
872 register int s;
873
874 c = 8 - (tp->t_col&7);
becb115c 875 if ((tp->t_flags&FLUSHO) == 0) {
4147b3f6
BJ
876 s = spl5(); /* don't interrupt tabs */
877 c -= b_to_q(" ", c, &tp->t_outq);
878 tk_nout += c;
879 splx(s);
880 }
881 tp->t_col += c;
882 return (c ? -1 : '\t');
883 }
884 tk_nout++;
885 /*
886 * for upper-case-only terminals,
887 * generate escapes.
888 */
889 if (tp->t_flags&LCASE) {
890 colp = "({)}!|^~'`";
4b72e2f9
SL
891 while (*colp++)
892 if (c == *colp++) {
4147b3f6
BJ
893 if (ttyoutput('\\', tp) >= 0)
894 return (c);
895 c = colp[-2];
896 break;
897 }
becb115c 898 if ('A' <= c && c <= 'Z') {
4147b3f6
BJ
899 if (ttyoutput('\\', tp) >= 0)
900 return (c);
becb115c 901 } else if ('a' <= c && c <= 'z')
4147b3f6
BJ
902 c += 'A' - 'a';
903 }
becb115c 904
4147b3f6
BJ
905 /*
906 * turn <nl> to <cr><lf> if desired.
907 */
becb115c 908 if (c == '\n' && tp->t_flags&CRMOD)
4147b3f6
BJ
909 if (ttyoutput('\r', tp) >= 0)
910 return (c);
becb115c 911 if (c == '~' && tp->t_flags&TILDE)
4147b3f6 912 c = '`';
becb115c 913 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
914 return (c);
915 /*
916 * Calculate delays.
917 * The numbers here represent clock ticks
918 * and are not necessarily optimal for all terminals.
919 * The delays are indicated by characters above 0200.
920 * In raw mode there are no delays and the
921 * transmission path is 8 bits wide.
becb115c
SL
922 *
923 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
4147b3f6
BJ
924 */
925 colp = &tp->t_col;
926 ctype = partab[c];
927 c = 0;
928 switch (ctype&077) {
929
930 case ORDINARY:
931 (*colp)++;
932
933 case CONTROL:
934 break;
935
936 case BACKSPACE:
937 if (*colp)
938 (*colp)--;
939 break;
940
941 case NEWLINE:
942 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 943 if (ctype == 1) { /* tty 37 */
88a7a62a 944 if (*colp > 0)
4147b3f6 945 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
becb115c 946 } else if (ctype == 2) /* vt05 */
4147b3f6 947 c = 6;
4147b3f6
BJ
948 *colp = 0;
949 break;
950
951 case TAB:
952 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 953 if (ctype == 1) { /* tty 37 */
4147b3f6 954 c = 1 - (*colp | ~07);
4b72e2f9 955 if (c < 5)
4147b3f6
BJ
956 c = 0;
957 }
958 *colp |= 07;
959 (*colp)++;
960 break;
961
962 case VTAB:
becb115c 963 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
964 c = 0177;
965 break;
966
967 case RETURN:
968 ctype = (tp->t_flags >> 12) & 03;
becb115c 969 if (ctype == 1) /* tn 300 */
4147b3f6 970 c = 5;
becb115c 971 else if (ctype == 2) /* ti 700 */
4147b3f6 972 c = 10;
becb115c 973 else if (ctype == 3) { /* concept 100 */
4147b3f6 974 int i;
becb115c 975
4147b3f6 976 if ((i = *colp) >= 0)
becb115c 977 for (; i < 9; i++)
4147b3f6
BJ
978 (void) putc(0177, &tp->t_outq);
979 }
980 *colp = 0;
981 }
becb115c 982 if (c && (tp->t_flags&FLUSHO) == 0)
4147b3f6
BJ
983 (void) putc(c|0200, &tp->t_outq);
984 return (-1);
985}
986
987/*
988 * Called from device's read routine after it has
989 * calculated the tty-structure given as argument.
990 */
d6d7360b 991ttread(tp, uio)
4b72e2f9 992 register struct tty *tp;
d6d7360b 993 struct uio *uio;
4147b3f6
BJ
994{
995 register struct clist *qp;
becb115c 996 register c, t_flags;
875a1e2c 997 int s, first, error = 0;
4147b3f6
BJ
998
999 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 1000 return (EIO);
4147b3f6 1001loop:
becb115c
SL
1002 /*
1003 * Take any pending input first.
1004 */
875a1e2c 1005 s = spl5();
becb115c 1006 if (tp->t_flags&PENDIN)
4147b3f6 1007 ttypend(tp);
875a1e2c 1008 splx(s);
becb115c
SL
1009
1010 /*
1011 * Hang process if it's in the background.
1012 */
4147b3f6
BJ
1013 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
1014 if (u.u_signal[SIGTTIN] == SIG_IGN ||
1015 u.u_signal[SIGTTIN] == SIG_HOLD ||
1016/*
1017 (u.u_procp->p_flag&SDETACH) ||
1018*/
1019 u.u_procp->p_flag&SVFORK)
840510a3 1020 return (EIO);
4147b3f6
BJ
1021 gsignal(u.u_procp->p_pgrp, SIGTTIN);
1022 sleep((caddr_t)&lbolt, TTIPRI);
1023 }
becb115c
SL
1024 t_flags = tp->t_flags;
1025
1026 /*
1027 * In raw mode take characters directly from the
1028 * raw queue w/o processing. Interlock against
1029 * device interrupts when interrogating rawq.
1030 */
1031 if (t_flags&RAW) {
875a1e2c 1032 s = spl5();
4147b3f6 1033 if (tp->t_rawq.c_cc <= 0) {
becb115c 1034 if ((tp->t_state&TS_CARR_ON) == 0 ||
4147b3f6 1035 (tp->t_state&TS_NBIO)) {
875a1e2c 1036 splx(s);
becb115c 1037 return (0);
4147b3f6
BJ
1038 }
1039 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1040 splx(s);
4147b3f6
BJ
1041 goto loop;
1042 }
875a1e2c
SL
1043 splx(s);
1044 while (!error && tp->t_rawq.c_cc && uio->uio_iovcnt)
840510a3 1045 error = passuc(getc(&tp->t_rawq), uio);
875a1e2c 1046 goto checktandem;
becb115c
SL
1047 }
1048
1049 /*
1050 * In cbreak mode use the rawq, otherwise
1051 * take characters from the canonicalized q.
1052 */
1053 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1054
1055 /*
1056 * No input, sleep on rawq awaiting hardware
1057 * receipt and notification.
1058 */
875a1e2c 1059 s = spl5();
becb115c
SL
1060 if (qp->c_cc <= 0) {
1061 if ((tp->t_state&TS_CARR_ON) == 0 ||
1062 (tp->t_state&TS_NBIO)) {
875a1e2c 1063 splx(s);
becb115c 1064 return (EWOULDBLOCK);
4147b3f6 1065 }
becb115c 1066 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1067 splx(s);
becb115c
SL
1068 goto loop;
1069 }
875a1e2c 1070 splx(s);
becb115c
SL
1071
1072 /*
1073 * Input present, perform input mapping
1074 * and processing (we're not in raw mode).
1075 */
1076 first = 1;
1077 while ((c = getc(qp)) >= 0) {
1078 if (t_flags&CRMOD && c == '\r')
1079 c = '\n';
1080 /*
1081 * Hack lower case simulation on
1082 * upper case only terminals.
1083 */
1084 if (t_flags&LCASE && c <= 0177)
1085 if (tp->t_state&TS_BKSL) {
1086 if (maptab[c])
1087 c = maptab[c];
1088 tp->t_state &= ~TS_BKSL;
1089 } else if (c >= 'A' && c <= 'Z')
1090 c += 'a' - 'A';
1091 else if (c == '\\') {
1092 tp->t_state |= TS_BKSL;
1093 continue;
4147b3f6 1094 }
becb115c
SL
1095 /*
1096 * Check for delayed suspend character.
1097 */
1098 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1099 gsignal(tp->t_pgrp, SIGTSTP);
1100 if (first) {
1101 sleep((caddr_t)&lbolt, TTIPRI);
1102 goto loop;
1103 }
1104 break;
4147b3f6 1105 }
becb115c
SL
1106 /*
1107 * Interpret EOF only in cooked mode.
1108 */
1109 if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1110 break;
1111 /*
1112 * Give user character.
1113 */
1114 error = passuc(c & 0177, uio);
1115 if (error)
1116 break;
1117 if (uio->uio_iovcnt == 0)
1118 break;
1119 /*
1120 * In cooked mode check for a "break character"
1121 * marking the end of a "line of input".
1122 */
1123 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1124 break;
1125 first = 0;
4147b3f6 1126 }
becb115c
SL
1127 tp->t_state &= ~TS_BKSL;
1128
875a1e2c 1129checktandem:
becb115c
SL
1130 /*
1131 * Look to unblock output now that (presumably)
1132 * the input queue has gone down.
1133 */
875a1e2c 1134 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
becb115c 1135 if (putc(tp->t_startc, &tp->t_outq) == 0) {
4147b3f6
BJ
1136 tp->t_state &= ~TS_TBLOCK;
1137 ttstart(tp);
1138 }
840510a3 1139 return (error);
4147b3f6
BJ
1140}
1141
1142/*
1143 * Called from the device's write routine after it has
1144 * calculated the tty-structure given as argument.
1145 */
913ea2d1 1146ttwrite(tp, uio)
4b72e2f9 1147 register struct tty *tp;
becb115c 1148 register struct uio *uio;
4147b3f6 1149{
4147b3f6 1150 register char *cp;
becb115c
SL
1151 register int cc, ce, c;
1152 int i, hiwat, cnt, error, s;
4147b3f6 1153 char obuf[OBUFSIZ];
4147b3f6 1154
becb115c 1155 if ((tp->t_state&TS_CARR_ON) == 0)
840510a3 1156 return (EIO);
becb115c
SL
1157 hiwat = TTHIWAT(tp);
1158 cnt = uio->uio_resid;
1159 error = 0;
4147b3f6 1160loop:
becb115c
SL
1161 /*
1162 * Hang the process if it's in the background.
1163 */
4147b3f6 1164 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
becb115c 1165 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
4147b3f6
BJ
1166 u.u_signal[SIGTTOU] != SIG_IGN &&
1167 u.u_signal[SIGTTOU] != SIG_HOLD
1168/*
1169 &&
1170 (u.u_procp->p_flag&SDETACH)==0) {
1171*/
1172 ) {
1173 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1174 sleep((caddr_t)&lbolt, TTIPRI);
1175 }
becb115c
SL
1176
1177 /*
1178 * Process the user's data in at most OBUFSIZ
1179 * chunks. Perform lower case simulation and
1180 * similar hacks. Keep track of high water
1181 * mark, sleep on overflow awaiting device aid
1182 * in acquiring new space.
1183 */
913ea2d1 1184 while (uio->uio_resid > 0) {
becb115c
SL
1185 /*
1186 * Grab a hunk of data from the user.
1187 */
913ea2d1
BJ
1188 cc = uio->uio_iov->iov_len;
1189 if (cc == 0) {
1190 uio->uio_iovcnt--;
1191 uio->uio_iov++;
1192 if (uio->uio_iovcnt < 0)
1193 panic("ttwrite");
1194 continue;
1195 }
1196 if (cc > OBUFSIZ)
1197 cc = OBUFSIZ;
4147b3f6 1198 cp = obuf;
88a7a62a 1199 error = uiomove(cp, cc, UIO_WRITE, uio);
840510a3 1200 if (error)
4147b3f6
BJ
1201 break;
1202 if (tp->t_outq.c_cc > hiwat)
1203 goto ovhiwat;
becb115c 1204 if (tp->t_flags&FLUSHO)
4147b3f6 1205 continue;
becb115c
SL
1206 /*
1207 * If we're mapping lower case or kludging tildes,
1208 * then we've got to look at each character, so
1209 * just feed the stuff to ttyoutput...
1210 */
1211 if (tp->t_flags & (LCASE|TILDE)) {
1212 while (cc > 0) {
4147b3f6
BJ
1213 c = *cp++;
1214 tp->t_rocount = 0;
4b72e2f9 1215 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1216 /* out of clists, wait a bit */
1217 ttstart(tp);
1218 sleep((caddr_t)&lbolt, TTOPRI);
1219 tp->t_rocount = 0;
1220 }
1221 --cc;
1222 if (tp->t_outq.c_cc > hiwat)
1223 goto ovhiwat;
1224 }
1225 continue;
1226 }
becb115c
SL
1227 /*
1228 * If nothing fancy need be done, grab those characters we
1229 * can handle without any of ttyoutput's processing and
1230 * just transfer them to the output q. For those chars
1231 * which require special processing (as indicated by the
1232 * bits in partab), call ttyoutput. After processing
1233 * a hunk of data, look for FLUSHO so ^O's will take effect
1234 * immediately.
1235 */
1236 while (cc > 0) {
1237 if (tp->t_flags & (RAW|LITOUT))
4147b3f6
BJ
1238 ce = cc;
1239 else {
88a7a62a
SL
1240 ce = cc - scanc((unsigned)cc, (caddr_t)cp,
1241 (caddr_t)partab, 077);
becb115c
SL
1242 /*
1243 * If ce is zero, then we're processing
1244 * a special character through ttyoutput.
1245 */
1246 if (ce == 0) {
4147b3f6
BJ
1247 tp->t_rocount = 0;
1248 if (ttyoutput(*cp, tp) >= 0) {
becb115c 1249 /* no c-lists, wait a bit */
4147b3f6
BJ
1250 ttstart(tp);
1251 sleep((caddr_t)&lbolt, TTOPRI);
1252 continue;
1253 }
becb115c
SL
1254 cp++, cc--;
1255 if (tp->t_flags&FLUSHO ||
1256 tp->t_outq.c_cc > hiwat)
4147b3f6 1257 goto ovhiwat;
becb115c 1258 continue;
4147b3f6
BJ
1259 }
1260 }
becb115c
SL
1261 /*
1262 * A bunch of normal characters have been found,
1263 * transfer them en masse to the output queue and
1264 * continue processing at the top of the loop.
1265 * If there are any further characters in this
1266 * <= OBUFSIZ chunk, the first should be a character
1267 * requiring special handling by ttyoutput.
1268 */
4147b3f6 1269 tp->t_rocount = 0;
becb115c
SL
1270 i = b_to_q(cp, ce, &tp->t_outq);
1271 ce -= i;
1272 tp->t_col += ce;
1273 cp += ce, cc -= ce, tk_nout += ce;
1274 if (i > 0) {
1275 /* out of c-lists, wait a bit */
4147b3f6
BJ
1276 ttstart(tp);
1277 sleep((caddr_t)&lbolt, TTOPRI);
1278 }
becb115c 1279 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1280 goto ovhiwat;
1281 }
1282 }
1283 ttstart(tp);
840510a3 1284 return (error);
4147b3f6
BJ
1285
1286ovhiwat:
becb115c
SL
1287 s = spl5();
1288 if (cc != 0) {
1289 uio->uio_iov->iov_base -= cc;
1290 uio->uio_iov->iov_len += cc;
1291 uio->uio_resid += cc;
1292 uio->uio_offset -= cc;
1293 }
1294 /*
1295 * This can only occur if FLUSHO
1296 * is also set in t_flags.
1297 */
4147b3f6 1298 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1299 splx(s);
4147b3f6
BJ
1300 goto loop;
1301 }
1302 ttstart(tp);
becb115c 1303 if (tp->t_state&TS_NBIO) {
913ea2d1 1304 if (uio->uio_resid == cnt)
840510a3
BJ
1305 return (EWOULDBLOCK);
1306 return (0);
4147b3f6
BJ
1307 }
1308 tp->t_state |= TS_ASLEEP;
1309 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1310 splx(s);
4147b3f6
BJ
1311 goto loop;
1312}
1313
1314/*
1315 * Rubout one character from the rawq of tp
1316 * as cleanly as possible.
1317 */
1318ttyrub(c, tp)
4b72e2f9
SL
1319 register c;
1320 register struct tty *tp;
4147b3f6
BJ
1321{
1322 register char *cp;
1323 register int savecol;
1324 int s;
1325 char *nextc();
1326
becb115c 1327 if ((tp->t_flags&ECHO) == 0)
4147b3f6 1328 return;
becb115c 1329 tp->t_flags &= ~FLUSHO;
4147b3f6 1330 c &= 0377;
becb115c 1331 if (tp->t_flags&CRTBS) {
4147b3f6
BJ
1332 if (tp->t_rocount == 0) {
1333 /*
1334 * Screwed by ttwrite; retype
1335 */
1336 ttyretype(tp);
1337 return;
1338 }
becb115c 1339 if (c == ('\t'|0200) || c == ('\n'|0200))
4147b3f6 1340 ttyrubo(tp, 2);
becb115c 1341 else switch (partab[c&=0177]&0177) {
4147b3f6
BJ
1342
1343 case ORDINARY:
1344 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1345 ttyrubo(tp, 2);
1346 else
1347 ttyrubo(tp, 1);
1348 break;
1349
1350 case VTAB:
1351 case BACKSPACE:
1352 case CONTROL:
1353 case RETURN:
becb115c 1354 if (tp->t_flags&CTLECH)
4147b3f6
BJ
1355 ttyrubo(tp, 2);
1356 break;
1357
1358 case TAB:
1359 if (tp->t_rocount < tp->t_rawq.c_cc) {
1360 ttyretype(tp);
1361 return;
1362 }
1363 s = spl5();
1364 savecol = tp->t_col;
becb115c
SL
1365 tp->t_state |= TS_CNTTB;
1366 tp->t_flags |= FLUSHO;
4147b3f6 1367 tp->t_col = tp->t_rocol;
becb115c
SL
1368 cp = tp->t_rawq.c_cf;
1369 for (; cp; cp = nextc(&tp->t_rawq, cp))
4147b3f6 1370 ttyecho(*cp, tp);
becb115c
SL
1371 tp->t_flags &= ~FLUSHO;
1372 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1373 splx(s);
1374 /*
1375 * savecol will now be length of the tab
1376 */
1377 savecol -= tp->t_col;
1378 tp->t_col += savecol;
1379 if (savecol > 8)
1380 savecol = 8; /* overflow screw */
1381 while (--savecol >= 0)
1382 (void) ttyoutput('\b', tp);
1383 break;
1384
1385 default:
1386 panic("ttyrub");
1387 }
becb115c
SL
1388 } else if (tp->t_flags&PRTERA) {
1389 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1390 (void) ttyoutput('\\', tp);
becb115c 1391 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1392 }
1393 ttyecho(c, tp);
1394 } else
1395 ttyecho(tp->t_erase, tp);
1396 tp->t_rocount--;
1397}
1398
1399/*
1400 * Crt back over cnt chars perhaps
1401 * erasing them.
1402 */
1403ttyrubo(tp, cnt)
4b72e2f9
SL
1404 register struct tty *tp;
1405 int cnt;
4147b3f6 1406{
becb115c 1407 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
4147b3f6
BJ
1408
1409 while (--cnt >= 0)
becb115c 1410 ttyout(rubostring, tp);
4147b3f6
BJ
1411}
1412
1413/*
1414 * Reprint the rawq line.
1415 * We assume c_cc has already been checked.
1416 */
1417ttyretype(tp)
4b72e2f9 1418 register struct tty *tp;
4147b3f6
BJ
1419{
1420 register char *cp;
1421 char *nextc();
1422 int s;
1423
becb115c
SL
1424 if (tp->t_rprntc != 0377)
1425 ttyecho(tp->t_rprntc, tp);
4147b3f6
BJ
1426 (void) ttyoutput('\n', tp);
1427 s = spl5();
1428 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1429 ttyecho(*cp, tp);
1430 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1431 ttyecho(*cp, tp);
becb115c 1432 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1433 splx(s);
1434 tp->t_rocount = tp->t_rawq.c_cc;
1435 tp->t_rocol = 0;
1436}
1437
1438/*
1439 * Echo a typed character to the terminal
1440 */
1441ttyecho(c, tp)
4b72e2f9
SL
1442 register c;
1443 register struct tty *tp;
4147b3f6
BJ
1444{
1445
becb115c
SL
1446 if ((tp->t_state&TS_CNTTB) == 0)
1447 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
1448 if ((tp->t_flags&ECHO) == 0)
1449 return;
1450 c &= 0377;
1451 if (tp->t_flags&RAW) {
1452 (void) ttyoutput(c, tp);
1453 return;
1454 }
1455 if (c == '\r' && tp->t_flags&CRMOD)
1456 c = '\n';
becb115c 1457 if (tp->t_flags&CTLECH) {
4147b3f6
BJ
1458 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1459 (void) ttyoutput('^', tp);
1460 c &= 0177;
1461 if (c == 0177)
1462 c = '?';
1463 else if (tp->t_flags&LCASE)
1464 c += 'a' - 1;
1465 else
1466 c += 'A' - 1;
1467 }
1468 }
1469 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1470 c += 'a' - 'A';
becb115c 1471 (void) ttyoutput(c&0177, tp);
4147b3f6
BJ
1472}
1473
1474/*
1475 * Is c a break char for tp?
1476 */
1477ttbreakc(c, tp)
4b72e2f9
SL
1478 register c;
1479 register struct tty *tp;
4147b3f6 1480{
becb115c 1481 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
4147b3f6
BJ
1482 c == '\r' && (tp->t_flags&CRMOD));
1483}
1484
1485/*
1486 * send string cp to tp
1487 */
1488ttyout(cp, tp)
4b72e2f9
SL
1489 register char *cp;
1490 register struct tty *tp;
4147b3f6
BJ
1491{
1492 register char c;
1493
1494 while (c = *cp++)
1495 (void) ttyoutput(c, tp);
1496}
1497
1498ttwakeup(tp)
1499 struct tty *tp;
1500{
1501
1502 if (tp->t_rsel) {
1503 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1504 tp->t_state &= ~TS_RCOLL;
1505 tp->t_rsel = 0;
1506 }
88a7a62a
SL
1507 if (tp->t_state & TS_ASYNC)
1508 gsignal(tp->t_pgrp, SIGIO);
4147b3f6
BJ
1509 wakeup((caddr_t)&tp->t_rawq);
1510}
1511
7c9f96c0 1512#if !defined(vax) && !defined(sun)
becb115c
SL
1513scanc(size, cp, table, mask)
1514 register int size;
1515 register char *cp, table[];
1516 register int mask;
4147b3f6 1517{
becb115c 1518 register int i = 0;
4147b3f6 1519
becb115c
SL
1520 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
1521 i++;
1522 return (i);
4147b3f6 1523}
becb115c 1524#endif