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