Home

Awesome

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d   The controlling terminal of the process.  (The minor device number is contained in
            the combination  of  bits 31 to 20 and 7 to 0; the major device number is in bits
            15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
	-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

Note:

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);

/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);

/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);

/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);

/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make