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