/* tty_pty.c 4.30 83/05/21 */
* (Actually two drivers, requiring two entries in 'cdevsw')
#define NPTY 32 /* crude XXX */
#define BUFSIZ 100 /* Chunk size iomoved from user */
struct proc
*pt_selr
, *pt_selw
;
#define PF_PKT 0x08 /* packet mode */
#define PF_STOPPED 0x10 /* user told stopped */
#define PF_REMOTE 0x20 /* remote and flow controlled input */
tp
= &pt_tty
[minor(dev
)];
if ((tp
->t_state
& TS_ISOPEN
) == 0) {
ttychars(tp
); /* Set up default chars */
tp
->t_ispeed
= tp
->t_ospeed
= EXTB
;
tp
->t_flags
= 0; /* No features (nor raw mode) */
} else if (tp
->t_state
&TS_XCLUDE
&& u
.u_uid
!= 0)
if (tp
->t_oproc
) /* Ctrlr still around. */
tp
->t_state
|= TS_CARR_ON
;
while ((tp
->t_state
& TS_CARR_ON
) == 0) {
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
return ((*linesw
[tp
->t_line
].l_open
)(dev
, tp
));
tp
= &pt_tty
[minor(dev
)];
(*linesw
[tp
->t_line
].l_close
)(tp
);
register struct tty
*tp
= &pt_tty
[minor(dev
)];
register struct pt_ioctl
*pti
= &pt_ioctl
[minor(dev
)];
if (pti
->pt_flags
& PF_REMOTE
) {
while (tp
== u
.u_ttyp
&& u
.u_procp
->p_pgrp
!= tp
->t_pgrp
) {
if (u
.u_signal
[SIGTTIN
] == SIG_IGN
||
u
.u_signal
[SIGTTIN
] == SIG_HOLD
||
(u.u_procp->p_flag&SDETACH) ||
u
.u_procp
->p_flag
&SVFORK
)
gsignal(u
.u_procp
->p_pgrp
, SIGTTIN
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
if (tp
->t_rawq
.c_cc
== 0) {
if (tp
->t_state
& TS_NBIO
)
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
while (tp
->t_rawq
.c_cc
> 1 && uio
->uio_resid
> 0)
if (ureadc(getc(&tp
->t_rawq
), uio
) < 0) {
if (tp
->t_rawq
.c_cc
== 1)
(void) getc(&tp
->t_rawq
);
error
= (*linesw
[tp
->t_line
].l_read
)(tp
, uio
);
wakeup((caddr_t
)&tp
->t_rawq
.c_cf
);
selwakeup(pti
->pt_selw
, pti
->pt_flags
& PF_WCOLL
);
pti
->pt_flags
&= ~PF_WCOLL
;
* Wakeups of controlling tty will happen
* indirectly, when tty driver calls ptsstart.
tp
= &pt_tty
[minor(dev
)];
return ((*linesw
[tp
->t_line
].l_write
)(tp
, uio
));
* Start output on pseudo-tty.
* Wake up process selecting or sleeping for input from controlling tty.
register struct pt_ioctl
*pti
= &pt_ioctl
[minor(tp
->t_dev
)];
if (tp
->t_state
& TS_TTSTOP
)
if (pti
->pt_flags
& PF_STOPPED
) {
pti
->pt_flags
&= ~PF_STOPPED
;
pti
->pt_send
= TIOCPKT_START
;
struct pt_ioctl
*pti
= &pt_ioctl
[minor(tp
->t_dev
)];
selwakeup(pti
->pt_selr
, pti
->pt_flags
& PF_RCOLL
);
pti
->pt_flags
&= ~PF_RCOLL
;
wakeup((caddr_t
)&tp
->t_outq
.c_cf
);
tp
= &pt_tty
[minor(dev
)];
if (tp
->t_state
& TS_WOPEN
)
wakeup((caddr_t
)&tp
->t_rawq
);
tp
->t_state
|= TS_CARR_ON
;
pti
= &pt_ioctl
[minor(dev
)];
tp
= &pt_tty
[minor(dev
)];
if (tp
->t_state
& TS_ISOPEN
)
gsignal(tp
->t_pgrp
, SIGHUP
);
tp
->t_state
&= ~TS_CARR_ON
; /* virtual carrier gone */
flushtty(tp
, FREAD
|FWRITE
);
tp
->t_oproc
= 0; /* mark closed */
register struct tty
*tp
= &pt_tty
[minor(dev
)];
if ((tp
->t_state
&(TS_CARR_ON
|TS_ISOPEN
)) == 0)
pti
= &pt_ioctl
[minor(dev
)];
if (pti
->pt_flags
& PF_PKT
) {
error
= ureadc(pti
->pt_send
, uio
);
while (tp
->t_outq
.c_cc
== 0 || (tp
->t_state
&TS_TTSTOP
)) {
if (pti
->pt_flags
&PF_NBIO
)
sleep((caddr_t
)&tp
->t_outq
.c_cf
, TTIPRI
);
while (tp
->t_outq
.c_cc
&& uio
->uio_resid
> 0)
if (ureadc(getc(&tp
->t_outq
), uio
) < 0) {
if (tp
->t_outq
.c_cc
<= TTLOWAT(tp
)) {
if (tp
->t_state
&TS_ASLEEP
) {
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_outq
);
selwakeup(tp
->t_wsel
, tp
->t_state
& TS_WCOLL
);
tp
->t_state
&= ~TS_WCOLL
;
struct pt_ioctl
*pti
= &pt_ioctl
[minor(tp
->t_dev
)];
/* note: FLUSHREAD and FLUSHWRITE already ok */
pti
->pt_flags
|= PF_STOPPED
;
pti
->pt_flags
&= ~PF_STOPPED
;
register struct tty
*tp
= &pt_tty
[minor(dev
)];
struct pt_ioctl
*pti
= &pt_ioctl
[minor(dev
)];
if ((tp
->t_state
&(TS_CARR_ON
|TS_ISOPEN
)) == 0)
if (tp
->t_outq
.c_cc
&& (tp
->t_state
&TS_TTSTOP
) == 0) {
if ((p
= pti
->pt_selr
) && p
->p_wchan
== (caddr_t
)&selwait
)
pti
->pt_flags
|= PF_RCOLL
;
pti
->pt_selr
= u
.u_procp
;
if ((pti
->pt_flags
& PF_REMOTE
) == 0 || tp
->t_rawq
.c_cc
== 0) {
if ((p
= pti
->pt_selw
) && p
->p_wchan
== (caddr_t
)&selwait
)
pti
->pt_flags
|= PF_WCOLL
;
pti
->pt_selw
= u
.u_procp
;
register struct tty
*tp
= &pt_tty
[minor(dev
)];
struct pt_ioctl
*pti
= &pt_ioctl
[minor(dev
)];
if ((tp
->t_state
&(TS_CARR_ON
|TS_ISOPEN
)) == 0)
register struct iovec
*iov
;
if (uio
->uio_iovcnt
== 0)
cc
= MIN(iov
->iov_len
, BUFSIZ
);
error
= uiomove(cp
, cc
, UIO_WRITE
, uio
);
if (pti
->pt_flags
& PF_REMOTE
) {
if (pti
->pt_flags
& PF_NBIO
) {
iov
->iov_base
-= ce
- cp
;
uio
->uio_resid
+= ce
- cp
;
uio
->uio_offset
-= ce
- cp
;
sleep((caddr_t
)&tp
->t_rawq
.c_cf
, TTOPRI
);
(void) b_to_q(cp
, cc
, &tp
->t_rawq
);
(void) putc(0, &tp
->t_rawq
);
wakeup((caddr_t
)&tp
->t_rawq
);
while (tp
->t_delct
&& tp
->t_rawq
.c_cc
>= TTYHOG
- 2) {
wakeup((caddr_t
)&tp
->t_rawq
);
if (tp
->t_state
& TS_NBIO
) {
iov
->iov_base
-= ce
- cp
;
uio
->uio_resid
+= ce
- cp
;
uio
->uio_offset
-= ce
- cp
;
/* Better than just flushing it! */
/* Wait for something to be read */
sleep((caddr_t
)&tp
->t_rawq
.c_cf
, TTOPRI
);
(*linesw
[tp
->t_line
].l_rint
)(*cp
++, tp
);
} while (uio
->uio_resid
);
ptyioctl(dev
, cmd
, data
, flag
)
register struct tty
*tp
= &pt_tty
[minor(dev
)];
register struct pt_ioctl
*pti
= &pt_ioctl
[minor(dev
)];
/* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
if (cdevsw
[major(dev
)].d_open
== ptcopen
)
pti
->pt_flags
&= ~PF_PKT
;
pti
->pt_flags
|= PF_REMOTE
;
pti
->pt_flags
&= ~PF_REMOTE
;
flushtty(tp
, FREAD
|FWRITE
);
pti
->pt_flags
|= PF_NBIO
;
pti
->pt_flags
&= ~PF_NBIO
;
while (getc(&tp
->t_outq
) >= 0)
error
= ttioctl(tp
, cmd
, data
, dev
);
{ int stop
= (tp
->t_stopc
== ('s'&037) &&
tp
->t_startc
== ('q'&037));
if (pti
->pt_flags
& PF_NOSTOP
) {
pti
->pt_send
&= TIOCPKT_NOSTOP
;
pti
->pt_send
|= TIOCPKT_DOSTOP
;
pti
->pt_flags
&= ~PF_NOSTOP
;
pti
->pt_send
&= ~TIOCPKT_DOSTOP
;
pti
->pt_send
|= TIOCPKT_NOSTOP
;
pti
->pt_flags
|= PF_NOSTOP
;