How to Detect When Someone Opens the Slave Side of a Pty (Pseudo-Terminal) in Linux

How can I detect when someone opens the slave side of a pty (pseudo-terminal) in Linux?

The reason you can't find this is because there's no documented interface specifically to allow it. However, there is a trick that allows you to do it. After opening the pseudo-terminal master (assumed here to be file descriptor ptm), you open and immediately close the slave side:

close(open(ptsname(ptm), O_RDWR | O_NOCTTY));

This sets the HUP flag on the tty master. You now poll the HUP flag regularly with poll() (say, whenever data comes in from your data source):

struct pollfd pfd = { .fd = ptm, .events = POLLHUP };
poll(&pfd, 1, 10 /* or other small timeout */);

if (!(pfd.revents & POLLHUP))
{
/* There is now a reader on the slave side */
}

If the reader ever goes away, POLLHUP will be set again.

In your case, you probably don't even need to remember from one loop to the next whether a given pty has a reader - just block on read() on your data source, then when data is available, simultaneously poll() all of your master ttys and send the data to any of them that do not have POLLHUP set.

How can the master pty detect if a slave tty has exited?

I've found the answer to this question by examining the telnetd source code found in the GNU inetutils package. In telnetd, they use a SIGCHLD handler like this:

int status;
pid_t pid = waitpid((pid_t)-1, &status, WNOHANG);
syslog (LOG_INFO, "child process %ld exited: %d",
(long) pid, WEXITSTATUS(status));
// do cleanup code

PTY/TTY - What Can't You Do With Only Slave FD

Thanks to StackOverflow's related-questions suggestions and other online searching since asking this, I've found a (partial?) answer:

  • Enabling or disabling packet mode on a PTY in Linux can only be done if you have the master FD [See TIOCPKT at this manpage]
  • Getting the Session ID associated with a TTY in Linux can only be done if you have the master FD (unclear if this is expected/intended behavior) [See TIOCGSID at this manpage]
  • Re-sizing the TTY is only portable from the master FD in practice (a terminal emulator might resize the TTY when it's resized, but an application with just the slave FD has no real certainty that the master size resizes accordingly, or that the terminal driver will even accept a resize from the slave end). [Source]
  • There is a trick for telling if the slave end of a TTY is opened, that you can't do if you don't have the master FD. [Source]

I'll try to keep coming back to edit this as I learn more.



Related Topics



Leave a reply



Submit