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