Because the pseudo-TTY subsystem has no hardware driver downstream from the ldterm(7M) module to process the terminal ioctl(2) calls, another module that understands the ioctl commands is placed downstream from the ldterm(7M). This module, ptem(7M), processes all of the terminal ioctl(2)calls and mediates the passage of control information downstream.
ldterm(7M) and ptem(7M) together behave like a real terminal. Since there is no real terminal or modem in the pseudo-TTY subsystem, some of the ioctl(2) commands are ignored and cause only an acknowledgment of the command. ptem(7M) keeps track of the terminal parameters set by the various set commands such as TCSETA or TCSETAW but does not usually perform any action. For example, if a “set” ioctl is called, none of the bits in the c_cflag field of termio(7I) has any effect on the pseudo-terminal unless the baud rate is set to 0. Setting the baud rate to 0 has the effect of hanging up the pseudo-terminal.
The pseudo-terminal does not recognize parity, so none of the flags in the c_iflag that control the processing of parity errors have any effect. The delays specified in the c_oflag field are also not supported.
ptem(7M) does the following:
Processes, if appropriate, and acknowledges receipt of the following ioctls on its write queue by sending an M_IOCACK message back upstream: TCSETA, TCSETAW, TCSETAF, TCSETS, TCSETSW, TCSETSF, TCGETA, TCGETS, and TCSBRK.
Keeps track of the window size; information needed for the TIOCSWINSZ, TIOCGWINSZ, and JWINSIZE ioctl.
When it receives an ioctl, other than for TIOCSWINSZ, TIOCGWINSZ, or JWINSIZE on its write queue, it sends an M_IOCNAK message upstream.
It passes downstream the following ioctls after processing them: TCSETA, TCSETAW, TCSETAF, TCSETS, TCSETSW, TCSETSF, TCSBRK, and TIOCSWINSZ.
Frees any M_IOCNAK messages it receives on its read queue in case the pckt module (pckt(7M) (described in the section Packet Mode) is not on the pseudo-terminal subsystem and the TCSETA, TCSETAW, TCSETAF, TCSETS, TCSETSW, TCSETSF, TCSBRK, or TIOCSWINSZioctls get to the master's stream head which then sends an M_IOCNAK message.
In its open routine, ptem sends an M_SETOPTS message upstream requesting allocation of a controlling TTY.
When ptem receives an M_IOCTL message of type TCSBRK on its read queue, it sends an M_IOCACK message downstream and an M_BREAK message upstream.
When ptem receives an ioctl(2) message on its write queue to set the baud rate to 0 (TCSETAW with CBAUD set to B0), it sends an M_IOCACK message upstream and a zero-length message downstream.
When ptem receives an M_IOCTL of type TIOCSIGNAL on its read queue, it sends an M_IOCACK downstream and an M_PCSIG upstream, where the signal number is the same as in the M_IOCTL message.
When ptem receives an M_IOCTL of type TIOCREMOTE on its read queue, it sends an M_IOCACK message downstream and the appropriate M_CTL message upstream to enable or disable canonical processing.
When ptem receives an M_DELAY message on its read or write queue, it discards the message and does not act on it.
When ptem receives an M_IOCTL of type JWINSIZE on its write queue, and if the values in its jwinsize structure are not zero, it sends an M_IOCACK message upstream with the jwinsize structure. If the values are zero, it sends an M_IOCNAK message upstream.
When ptem receives an M_IOCTL message of type TIOCGWINSZ on its write queue and the values in the winsize structure are not zero, it sends an M_IOCACK message upstream with the winsize structure. If the values are zero, it sends an M_IOCNAK message upstream. It also saves the information passed to it in the winsize structure and sends a STREAMS signal message for signal SIGWINCH upstream to the slave process if the size changed.
When ptem(7M) receives an M_IOCTL message with type TIOCGWINSZ on its read queue and the values in the winsize structure are not zero, it sends an M_IOCACK message downstream with the winsize structure. If the values are zero, it sends an M_IOCNAK message downstream. It also saves the information passed to it in the winsize structure and sends a STREAMS signal message for signal SIGWINCH upstream to the slave process if the size changed.
All other messages are passed to the next module or driver.
Each instantiation of ptem(7M) is associated with a local area. These data are held in a structure called ptem that has the following format:
struct ptem { long cflags; /* copy of c_flags */ mblk_t *dack_ptr; /* pointer to preallocated msg blk used to send disconnect */ queue_t *q_ptr; /* pointer to ptem's read queue */ struct winsize wsz; /*struct to hold windowing info*/ unsigned short state; /* state of ptem entry */ };
When ptem(7M) is pushed onto the slave side stream, a search of the ptem structure is made for a free entry (state is not set to INUSE). The c_cflags of the termio(7I) structure and the windowing variables are stored in cflags and wsz respectively. The dack_ptr is a pointer to a message block used to send a zero-length message whenever a hang-up occurs on the slave side.
ptem(7M) internal implementation might change. This structure should be relevant only to people wanting to change the module.
The following information is implementation-dependent.
In the open routine of ptem(7M) a STREAMS message block is allocated for a zero-length message for delivering a hangup message. This allocation of a buffer is done before it is needed to ensure that a buffer is available. An M_SETOPTS message is sent upstream to set the read-side stream head queues, to assign high-water and low-water marks (1024 and 256 respectively), and to establish a controlling terminal.
The same default values as for the line-discipline module are assigned to cflags, and INUSE to the state field.
These default values are currently being examined and may change in the future.
The open routine fails if:
No free entries are found when the ptem(7M) structure is searched
sflag is not set to MODOPEN
A zero-length message cannot be allocated (no buffer is available)
A stroptions(9S) structure cannot be allocated
The close routine is called on the last close of the slave-side stream. Pointers to read and write queues are cleared and the buffer for the zero-length message is freed.