/* tty.c 6.10 84/08/29 */
#include "../machine/reg.h"
* Table giving parity for characters and indicating
* character classes to tty driver. In particular,
* if the low 6 bits are 0, then the character needs
* no special processing on output.
0001,0201,0201,0001,0201,0001,0001,0201,
0202,0004,0003,0201,0005,0206,0201,0001,
0201,0001,0001,0201,0001,0201,0201,0001,
0001,0201,0201,0001,0201,0001,0001,0201,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0201,
* 7 bit ascii ends with the last character above,
* but we contine through all 256 codes for the sake
* of the tty output routines which use special vax
* instructions which need a 256 character trt table.
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007,
0007,0007,0007,0007,0007,0007,0007,0007
* Input mapping table-- if an entry is non-zero, when the
* corresponding character is typed preceded by "\" the escape
* sequence is replaced by the table value. Mostly used for
* upper-case only terminals.
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,'|',000,000,000,000,000,'`',
'{','}',000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,'~',000,
000,'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W',
'X','Y','Z',000,000,000,000,000,
{ 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
{ 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
struct ttychars ttydefaults
= {
CERASE
, CKILL
, CINTR
, CQUIT
, CSTART
, CSTOP
, CEOF
,
CBRK
, CSUSP
, CDSUSP
, CRPRNT
, CFLUSH
, CWERASE
,CLNEXT
tp
->t_chars
= ttydefaults
;
* Wait for output to drain, then flush input waiting.
while ((tp
->t_outq
.c_cc
|| tp
->t_state
&TS_BUSY
) &&
tp
->t_state
&TS_CARR_ON
&& tp
->t_oproc
) { /* kludge for pty */
tp
->t_state
|= TS_ASLEEP
;
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);
while (getc(&tp
->t_canq
) >= 0)
wakeup((caddr_t
)&tp
->t_rawq
);
wakeup((caddr_t
)&tp
->t_outq
);
tp
->t_state
&= ~TS_TTSTOP
;
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, rw
);
while (getc(&tp
->t_outq
) >= 0)
while (getc(&tp
->t_rawq
) >= 0)
tp
->t_state
&= ~TS_LOCAL
;
* Send stop character on input overflow.
x
= tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
;
if (tp
->t_rawq
.c_cc
> TTYHOG
) {
ttyflush(tp
, FREAD
|FWRITE
);
tp
->t_state
&= ~TS_TBLOCK
;
* Block further input iff:
* Current input > threshold AND input is available to user program
((tp
->t_flags
& (RAW
|CBREAK
)) || (tp
->t_canq
.c_cc
> 0))) {
if (putc(tp
->t_stopc
, &tp
->t_outq
)==0) {
tp
->t_state
|= TS_TBLOCK
;
* Restart typewriter output following a delay
* The name of the routine is passed to the timeout
* subroutine and it is called during a clock interrupt.
tp
->t_state
&= ~TS_TIMEOUT
;
* Start output on the typewriter. It is used from the top half
* after some characters have been put on the output queue,
* from the interrupt routine to transmit the next
* character, and after a timeout has finished.
if ((tp
->t_state
& (TS_TIMEOUT
|TS_TTSTOP
|TS_BUSY
)) == 0 &&
tp
->t_oproc
) /* kludge for pty */
* Common code for tty ioctls.
ttioctl(tp
, com
, data
, flag
)
* If the ioctl involves modification,
* insist on being able to write the device,
* and hang if in the background.
#define bit(a) (1<<(a-1))
while (tp
->t_line
== NTTYDISC
&&
u
.u_procp
->p_pgrp
!= tp
->t_pgrp
&& tp
== u
.u_ttyp
&&
(u
.u_procp
->p_flag
&SVFORK
) == 0 &&
!(u
.u_procp
->p_sigignore
& bit(SIGTTOU
)) &&
!(u
.u_procp
->p_sigmask
& bit(SIGTTOU
))) {
gsignal(u
.u_procp
->p_pgrp
, SIGTTOU
);
sleep((caddr_t
)&lbolt
, TTOPRI
);
/* get discipline number */
*(int *)data
= tp
->t_line
;
/* set line discipline */
register int t
= *(int *)data
;
if ((unsigned) t
>= nldisp
)
(*linesw
[tp
->t_line
].l_close
)(tp
);
error
= (*linesw
[t
].l_open
)(dev
, tp
);
(void) (*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
/* prevent more opens on channel */
tp
->t_state
|= TS_XCLUDE
;
tp
->t_state
&= ~TS_XCLUDE
;
/* hang up line on last close */
tp
->t_state
|= TS_HUPCLS
;
register int flags
= *(int *)data
;
/* return number of characters immediately available */
*(off_t
*)data
= ttnread(tp
);
*(int *)data
= tp
->t_outq
.c_cc
;
if ((tp
->t_state
&TS_TTSTOP
) == 0) {
tp
->t_state
|= TS_TTSTOP
;
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
if ((tp
->t_state
&TS_TTSTOP
) || (tp
->t_flags
&FLUSHO
)) {
tp
->t_state
&= ~TS_TTSTOP
;
* Simulate typing of a character at the terminal.
if (u
.u_uid
&& u
.u_ttyp
!= tp
)
(*linesw
[tp
->t_line
].l_rint
)(*(char *)data
, tp
);
register struct sgttyb
*sg
= (struct sgttyb
*)data
;
tp
->t_erase
= sg
->sg_erase
;
tp
->t_kill
= sg
->sg_kill
;
tp
->t_ispeed
= sg
->sg_ispeed
;
tp
->t_ospeed
= sg
->sg_ospeed
;
newflags
= (tp
->t_flags
&0xffff0000) | (sg
->sg_flags
&0xffff);
if (tp
->t_flags
&RAW
|| newflags
&RAW
|| com
== TIOCSETP
) {
} else if ((tp
->t_flags
&CBREAK
) != (newflags
&CBREAK
)) {
catq(&tp
->t_rawq
, &tp
->t_canq
);
tp
->t_state
&= ~TS_TTSTOP
;
/* send current parameters to user */
register struct sgttyb
*sg
= (struct sgttyb
*)data
;
sg
->sg_ispeed
= tp
->t_ispeed
;
sg
->sg_ospeed
= tp
->t_ospeed
;
sg
->sg_erase
= tp
->t_erase
;
sg
->sg_kill
= tp
->t_kill
;
sg
->sg_flags
= tp
->t_flags
;
tp
->t_state
&= ~TS_ASYNC
;
bcopy((caddr_t
)&tp
->t_intrc
, data
, sizeof (struct tchars
));
bcopy(data
, (caddr_t
)&tp
->t_intrc
, sizeof (struct tchars
));
/* set/get local special characters */
bcopy(data
, (caddr_t
)&tp
->t_suspc
, sizeof (struct ltchars
));
bcopy((caddr_t
)&tp
->t_suspc
, data
, sizeof (struct ltchars
));
* Modify local mode word.
tp
->t_flags
|= *(int *)data
<< 16;
tp
->t_flags
&= ~(*(int *)data
<< 16);
tp
->t_flags
|= *(int *)data
<< 16;
*(int *)data
= ((unsigned) tp
->t_flags
) >> 16;
/* should allow SPGRP and GPGRP only if tty open for reading */
tp
->t_pgrp
= *(int *)data
;
*(int *)data
= tp
->t_pgrp
;
if (tp
->t_flags
& PENDIN
)
if (tp
->t_flags
& (RAW
|CBREAK
))
nread
+= tp
->t_rawq
.c_cc
;
register struct tty
*tp
= &cdevsw
[major(dev
)].d_ttys
[minor(dev
)];
if (tp
->t_rsel
&& tp
->t_rsel
->p_wchan
== (caddr_t
)&selwait
)
if (tp
->t_outq
.c_cc
<= TTLOWAT(tp
))
if (tp
->t_wsel
&& tp
->t_wsel
->p_wchan
== (caddr_t
)&selwait
)
* Establish a process group for distribution of
* quits and interrupts from the tty.
register struct proc
*pp
;
tp
->t_state
&= ~TS_WOPEN
;
tp
->t_state
|= TS_ISOPEN
;
if (tp
->t_line
!= NTTYDISC
)
* reinput pending characters after state switch
tp
->t_rawq
.c_cf
= tp
->t_rawq
.c_cl
= 0;
while ((c
= getc(&tq
)) >= 0)
tp
->t_state
&= ~TS_TYPEN
;
* Place a character on raw TTY input queue,
* putting in delimiters and waking up top
* half as needed. Also echo if required.
* The arguments are the character and the
* appropriate tty structure.
register int t_flags
= tp
->t_flags
;
* If input is pending take it first.
* In tandem mode, check high water mark.
* Raw mode, just put character
* in input q w/o interpretation.
if (tp
->t_rawq
.c_cc
> TTYHOG
)
ttyflush(tp
, FREAD
|FWRITE
);
if (putc(c
, &tp
->t_rawq
) >= 0)
* Ignore any high bit added during
* previous ttyinput processing.
if ((tp
->t_state
&TS_TYPEN
) == 0)
* Check for literal nexting very first
if (tp
->t_state
&TS_LNCH
) {
* Scan for special characters. This code
* is really just a big case statement with
* non-constant cases. The bottom of the
* case statement is labeled ``endcase'', so goto
* it after a case match, or similar.
if (tp
->t_line
== NTTYDISC
) {
if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
)
if ((tp
->t_flags
&NOFLSH
) == 0)
gsignal(tp
->t_pgrp
, SIGTSTP
);
* Handle start/stop characters.
if ((tp
->t_state
&TS_TTSTOP
) == 0) {
tp
->t_state
|= TS_TTSTOP
;
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
* Look for interrupt/quit chars.
if (c
== tp
->t_intrc
|| c
== tp
->t_quitc
) {
if ((tp
->t_flags
&NOFLSH
) == 0)
ttyflush(tp
, FREAD
|FWRITE
);
gsignal(tp
->t_pgrp
, c
== tp
->t_intrc
? SIGINT
: SIGQUIT
);
* Cbreak mode, don't process line editing
* characters; check high water mark for wakeup.
if (tp
->t_rawq
.c_cc
> TTYHOG
) {
if (tp
->t_outq
.c_cc
< TTHIWAT(tp
) &&
(void) ttyoutput(CTRL(g
), tp
);
} else if (putc(c
, &tp
->t_rawq
) >= 0) {
* From here on down cooked mode character
* processing takes place.
if ((tp
->t_state
&TS_QUOT
) &&
(c
== tp
->t_erase
|| c
== tp
->t_kill
)) {
ttyrub(unputc(&tp
->t_rawq
), tp
);
ttyrub(unputc(&tp
->t_rawq
), tp
);
if (tp
->t_flags
&CRTKIL
&&
tp
->t_rawq
.c_cc
== tp
->t_rocount
) {
ttyrub(unputc(&tp
->t_rawq
), tp
);
while (getc(&tp
->t_rawq
) > 0)
tp
->t_state
&= ~TS_LOCAL
;
* check word erase/reprint line.
if (tp
->t_line
== NTTYDISC
) {
if (tp
->t_rawq
.c_cc
== 0)
if (c
!= ' ' && c
!= '\t')
} while (tp
->t_rawq
.c_cc
);
if (tp
->t_rawq
.c_cc
== 0)
} while (c
!= ' ' && c
!= '\t');
(void) putc(c
, &tp
->t_rawq
);
* Check for input buffer overflow
if (tp
->t_rawq
.c_cc
+tp
->t_canq
.c_cc
>= TTYHOG
) {
if (tp
->t_line
== NTTYDISC
)
(void) ttyoutput(CTRL(g
), tp
);
* Put data char in q for user and
* wakeup on seeing a line delimiter.
if (putc(c
, &tp
->t_rawq
) >= 0) {
catq(&tp
->t_rawq
, &tp
->t_canq
);
} else if (tp
->t_rocount
++ == 0)
if (tp
->t_state
&TS_ERASE
) {
tp
->t_state
&= ~TS_ERASE
;
(void) ttyoutput('/', tp
);
if (c
== tp
->t_eofc
&& tp
->t_flags
&ECHO
) {
i
= MIN(2, tp
->t_col
- i
);
(void) ttyoutput('\b', tp
);
* If DEC-style start/stop is enabled don't restart
* output until seeing the start character.
if (tp
->t_flags
&DECCTQ
&& tp
->t_state
&TS_TTSTOP
&&
tp
->t_startc
!= tp
->t_stopc
)
tp
->t_state
&= ~TS_TTSTOP
;
* Put character on TTY output queue, adding delays,
* expanding tabs, and handling the CR/NL bit.
* This is called both from the top half for output,
* and from interrupt level for echoing.
* The arguments are the character and the tty structure.
* Returns < 0 if putc succeeds, otherwise returns char to resend
if (tp
->t_flags
& (RAW
|LITOUT
)) {
if (putc(c
, &tp
->t_outq
))
* Ignore EOT in normal mode to avoid
* hanging up certain terminals.
if (c
== CEOT
&& (tp
->t_flags
&CBREAK
) == 0)
* Turn tabs to spaces as required
if (c
== '\t' && (tp
->t_flags
&TBDELAY
) == XTABS
) {
if ((tp
->t_flags
&FLUSHO
) == 0) {
s
= spl5(); /* don't interrupt tabs */
c
-= b_to_q(" ", c
, &tp
->t_outq
);
* for upper-case-only terminals,
if (ttyoutput('\\', tp
) >= 0)
if ('A' <= c
&& c
<= 'Z') {
if (ttyoutput('\\', tp
) >= 0)
} else if ('a' <= c
&& c
<= 'z')
* turn <nl> to <cr><lf> if desired.
if (c
== '\n' && tp
->t_flags
&CRMOD
)
if (ttyoutput('\r', tp
) >= 0)
if (c
== '~' && tp
->t_flags
&TILDE
)
if ((tp
->t_flags
&FLUSHO
) == 0 && putc(c
, &tp
->t_outq
))
* The numbers here represent clock ticks
* and are not necessarily optimal for all terminals.
* The delays are indicated by characters above 0200.
* In raw mode there are no delays and the
* transmission path is 8 bits wide.
* SHOULD JUST ALLOW USER TO SPECIFY DELAYS
* This macro is close enough to the correct thing;
* it should be replaced by real user settable delays
#define mstohz(ms) (((ms) * hz) >> 10)
ctype
= (tp
->t_flags
>> 8) & 03;
if (ctype
== 1) { /* tty 37 */
c
= max((((unsigned)*colp
) >> 4) + 3,
} else if (ctype
== 2) /* vt05 */
ctype
= (tp
->t_flags
>> 10) & 03;
if (ctype
== 1) { /* tty 37 */
if (tp
->t_flags
&VTDELAY
) /* tty 37 */
ctype
= (tp
->t_flags
>> 12) & 03;
if (ctype
== 1) /* tn 300 */
else if (ctype
== 2) /* ti 700 */
else if (ctype
== 3) { /* concept 100 */
(void) putc(0177, &tp
->t_outq
);
if (c
&& (tp
->t_flags
&FLUSHO
) == 0)
(void) putc(c
|0200, &tp
->t_outq
);
* Called from device's read routine after it has
* calculated the tty-structure given as argument.
register struct clist
*qp
;
if ((tp
->t_state
&TS_CARR_ON
)==0)
* Take any pending input first.
* Hang process if it's in the background.
#define bit(a) (1<<(a-1))
while (tp
== u
.u_ttyp
&& u
.u_procp
->p_pgrp
!= tp
->t_pgrp
) {
if ((u
.u_procp
->p_sigignore
& bit(SIGTTIN
)) ||
(u
.u_procp
->p_sigmask
& bit(SIGTTIN
)) ||
(u.u_procp->p_flag&SDETACH) ||
u
.u_procp
->p_flag
&SVFORK
)
gsignal(u
.u_procp
->p_pgrp
, SIGTTIN
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
* In raw mode take characters directly from the
* raw queue w/o processing. Interlock against
* device interrupts when interrogating rawq.
if (tp
->t_rawq
.c_cc
<= 0) {
if ((tp
->t_state
&TS_CARR_ON
) == 0 ||
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
while (!error
&& tp
->t_rawq
.c_cc
&& uio
->uio_resid
)
error
= ureadc(getc(&tp
->t_rawq
), uio
);
* In cbreak mode use the rawq, otherwise
* take characters from the canonicalized q.
qp
= t_flags
&CBREAK
? &tp
->t_rawq
: &tp
->t_canq
;
* No input, sleep on rawq awaiting hardware
* receipt and notification.
if ((tp
->t_state
&TS_CARR_ON
) == 0 ||
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
* Input present, perform input mapping
* and processing (we're not in raw mode).
while ((c
= getc(qp
)) >= 0) {
if (t_flags
&CRMOD
&& c
== '\r')
* Hack lower case simulation on
* upper case only terminals.
if (t_flags
&LCASE
&& c
<= 0177)
if (tp
->t_state
&TS_BKSL
) {
} else if (c
>= 'A' && c
<= 'Z')
* Check for delayed suspend character.
if (tp
->t_line
== NTTYDISC
&& c
== tp
->t_dsuspc
) {
gsignal(tp
->t_pgrp
, SIGTSTP
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
* Interpret EOF only in cooked mode.
if (c
== tp
->t_eofc
&& (t_flags
&CBREAK
) == 0)
error
= ureadc(c
& 0177, uio
);
* In cooked mode check for a "break character"
* marking the end of a "line of input".
if ((t_flags
&CBREAK
) == 0 && ttbreakc(c
, tp
))
* Look to unblock output now that (presumably)
* the input queue has gone down.
if (tp
->t_state
&TS_TBLOCK
&& tp
->t_rawq
.c_cc
< TTYHOG
/5)
if (putc(tp
->t_startc
, &tp
->t_outq
) == 0) {
tp
->t_state
&= ~TS_TBLOCK
;
* Called from the device's write routine after it has
* calculated the tty-structure given as argument.
register struct uio
*uio
;
int i
, hiwat
, cnt
, error
, s
;
if ((tp
->t_state
&TS_CARR_ON
) == 0)
* Hang the process if it's in the background.
#define bit(a) (1<<(a-1))
while (u
.u_procp
->p_pgrp
!= tp
->t_pgrp
&& tp
== u
.u_ttyp
&&
(tp
->t_flags
&TOSTOP
) && (u
.u_procp
->p_flag
&SVFORK
)==0 &&
!(u
.u_procp
->p_sigignore
& bit(SIGTTOU
)) &&
!(u
.u_procp
->p_sigmask
& bit(SIGTTOU
))
(u.u_procp->p_flag&SDETACH)==0) {
gsignal(u
.u_procp
->p_pgrp
, SIGTTOU
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
* Process the user's data in at most OBUFSIZ
* chunks. Perform lower case simulation and
* similar hacks. Keep track of high water
* mark, sleep on overflow awaiting device aid
* in acquiring new space.
while (uio
->uio_resid
> 0) {
* Grab a hunk of data from the user.
cc
= uio
->uio_iov
->iov_len
;
error
= uiomove(cp
, cc
, UIO_WRITE
, uio
);
if (tp
->t_outq
.c_cc
> hiwat
)
* If we're mapping lower case or kludging tildes,
* then we've got to look at each character, so
* just feed the stuff to ttyoutput...
if (tp
->t_flags
& (LCASE
|TILDE
)) {
while ((c
= ttyoutput(c
, tp
)) >= 0) {
/* out of clists, wait a bit */
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (tp
->t_outq
.c_cc
> hiwat
)
* If nothing fancy need be done, grab those characters we
* can handle without any of ttyoutput's processing and
* just transfer them to the output q. For those chars
* which require special processing (as indicated by the
* bits in partab), call ttyoutput. After processing
* a hunk of data, look for FLUSHO so ^O's will take effect
if (tp
->t_flags
& (RAW
|LITOUT
))
ce
= cc
- scanc((unsigned)cc
, (caddr_t
)cp
,
* If ce is zero, then we're processing
* a special character through ttyoutput.
if (ttyoutput(*cp
, tp
) >= 0) {
/* no c-lists, wait a bit */
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (tp
->t_flags
&FLUSHO
||
* A bunch of normal characters have been found,
* transfer them en masse to the output queue and
* continue processing at the top of the loop.
* If there are any further characters in this
* <= OBUFSIZ chunk, the first should be a character
* requiring special handling by ttyoutput.
i
= b_to_q(cp
, ce
, &tp
->t_outq
);
cp
+= ce
, cc
-= ce
, tk_nout
+= ce
;
/* out of c-lists, wait a bit */
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (tp
->t_flags
&FLUSHO
|| tp
->t_outq
.c_cc
> hiwat
)
uio
->uio_iov
->iov_base
-= cc
;
uio
->uio_iov
->iov_len
+= cc
;
* This can only occur if FLUSHO
* is also set in t_flags.
if (tp
->t_outq
.c_cc
<= hiwat
) {
if (tp
->t_state
&TS_NBIO
) {
if (uio
->uio_resid
== cnt
)
tp
->t_state
|= TS_ASLEEP
;
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);
* Rubout one character from the rawq of tp
* as cleanly as possible.
if ((tp
->t_flags
&ECHO
) == 0)
if (tp
->t_rocount
== 0) {
* Screwed by ttwrite; retype
if (c
== ('\t'|0200) || c
== ('\n'|0200))
else switch (partab
[c
&=0177]&0177) {
if (tp
->t_flags
&LCASE
&& c
>= 'A' && c
<= 'Z')
if (tp
->t_rocount
< tp
->t_rawq
.c_cc
) {
for (; cp
; cp
= nextc(&tp
->t_rawq
, cp
))
tp
->t_state
&= ~TS_CNTTB
;
* savecol will now be length of the tab
savecol
= 8; /* overflow screw */
(void) ttyoutput('\b', tp
);
} else if (tp
->t_flags
&PRTERA
) {
if ((tp
->t_state
&TS_ERASE
) == 0) {
(void) ttyoutput('\\', tp
);
ttyecho(tp
->t_erase
, tp
);
* Crt back over cnt chars perhaps
register char *rubostring
= tp
->t_flags
&CRTERA
? "\b \b" : "\b";
* We assume c_cc has already been checked.
if (tp
->t_rprntc
!= 0377)
ttyecho(tp
->t_rprntc
, tp
);
(void) ttyoutput('\n', tp
);
for (cp
= tp
->t_canq
.c_cf
; cp
; cp
= nextc(&tp
->t_canq
, cp
))
for (cp
= tp
->t_rawq
.c_cf
; cp
; cp
= nextc(&tp
->t_rawq
, cp
))
tp
->t_state
&= ~TS_ERASE
;
tp
->t_rocount
= tp
->t_rawq
.c_cc
;
* Echo a typed character to the terminal
if ((tp
->t_state
&TS_CNTTB
) == 0)
if ((tp
->t_flags
&ECHO
) == 0)
if (c
== '\r' && tp
->t_flags
&CRMOD
)
if (tp
->t_flags
&CTLECH
) {
if ((c
&0177) <= 037 && c
!='\t' && c
!='\n' || (c
&0177)==0177) {
(void) ttyoutput('^', tp
);
else if (tp
->t_flags
&LCASE
)
if ((tp
->t_flags
&LCASE
) && (c
>= 'A' && c
<= 'Z'))
(void) ttyoutput(c
&0177, tp
);
* Is c a break char for tp?
return (c
== '\n' || c
== tp
->t_eofc
|| c
== tp
->t_brkc
||
c
== '\r' && (tp
->t_flags
&CRMOD
));
selwakeup(tp
->t_rsel
, tp
->t_state
&TS_RCOLL
);
tp
->t_state
&= ~TS_RCOLL
;
if (tp
->t_state
& TS_ASYNC
)
gsignal(tp
->t_pgrp
, SIGIO
);
wakeup((caddr_t
)&tp
->t_rawq
);
scanc(size
, cp
, table
, mask
)
register char *cp
, table
[];
while ((table
[*(u_char
*)(cp
+ i
)]&mask
) == 0 && i
< size
)