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