1 PTM(7D) Devices PTM(7D) 2 3 NAME 4 ptm, pts - STREAMS pseudo-terminal manager and subsidiary drivers 5 6 SYNOPSIS 7 /dev/ptmx 8 9 /dev/pts/* 10 11 DESCRIPTION 12 The pseudo-terminal subsystem simulates a terminal connection, where the 13 manager side represents the terminal and the subsidiary represents the 14 user process's special device end point. The manager device is set up as 15 a cloned device where its major device number is the major for the clone 16 device and its minor device number is the major for the ptm driver; see 17 CLONE_DEV in ddi_create_minor_node(9F). 18 19 There are no nodes in the file system for manager devices. The manager 20 pseudo driver is opened using the open(2) system call with /dev/ptmx as 21 the device parameter. The clone open finds the next available minor 22 device for the ptm major device. 23 24 A manager device is only available if it and its corresponding subsidiary 25 device are not already open. Only one open is allowed on a manager 26 device. Multiple opens are allowed on the subsidiary device. 27 28 When the manager device is opened, the corresponding subsidiary device is 29 automatically locked out. No user may open the subsidiary device until 30 its permissions are adjusted and the device is unlocked by calling the 31 functions grantpt(3C) and unlockpt(3C). The user can then invoke the 32 open(2) system call with the device name returned by the ptsname(3C) 33 function. 34 35 After both the manager and subsidiary have been opened, the user has two 36 file descriptors which are the end points of a full duplex connection 37 composed of two streams which are automatically connected at the manager 38 and subsidiary drivers. The user may then push modules onto either side 39 of the stream pair. Unless compiled in XPG4v2 mode (see XPG4v2 MODE), 40 the consumer needs to push the ptem(7M) and ldterm(7M) modules onto the 41 subsidiary device to get terminal semantics. 42 43 The manager and subsidiary drivers pass all messages to their adjacent 44 queues. Only the M_FLUSH needs some processing. Because the read queue 45 of one side is connected to the write queue of the other, the FLUSHR flag 46 is changed to the FLUSHW flag and vice versa. 47 48 When the manager device is closed, an M_HANGUP message is sent to the 49 subsidiary device which will render the device unusable. The process on 50 the subsidiary side gets an EIO error when attempting to write on that 51 stream, but it will be able to read any data remaining on the stream head 52 read queue. When all the data has been read, read(2) returns 0 53 indicating that the stream can no longer be used. 54 55 On the last close of the subsidiary device, a 0-length message is sent to 56 the manager device. When the application on the manager side issues a 57 read(2) or getmsg(2) and 0 is returned, the user of the manager device 58 decides whether to issue a close(2) that dismantles the entire pseudo- 59 terminal. If the manager device is not closed, the pseudo-terminal will 60 be available to another user to open the subsidiary device. 61 62 Since 0-length messages are used to indicate that the process on the 63 subsidiary side has closed, and should be interpreted that way by the 64 process on the manager side, applications on the subsidiary side should 65 not write 0-length messages. Unless the application is compiled in 66 XPG4v2 mode (see XPG4v2 MODE), then any 0-length messages written to the 67 subsidiary device will be discarded by the ptem(7M) module. 68 69 If O_NONBLOCK or O_NDELAY is set on the manager side: 70 71 o Read on the manager side returns -1 with errno set to EAGAIN if no 72 data is available 73 74 o Write returns -1 with errno set to EAGAIN if there is internal flow 75 control 76 77 Standard STREAMS system calls can access pseudo-terminal devices. The 78 subsidiary devices support the O_NDELAY and O_NONBLOCK flags. 79 80 XPG4v2 MODE 81 XPG4v2 requires that subsidiary pseudo-terminal devices provide the 82 process with an interface that is identical to the terminal interface, 83 without needing to explicitly push any modules to achieve this. It also 84 requires that 0-length messages written on the subsidiary device will be 85 propagated to the manager device. 86 87 Experience has shown that most software does not expect subsidiary 88 pseudo-terminal devices to operate in this manner. This XPG4v2-compliant 89 behaviour is only enabled in XPG4v2/SUS (see standards(5)) mode. 90 91 IOCTLS 92 The manager driver provides several ioctls to support the grantpt(3C), 93 unlockpt(3C), and ptsname(3C) functions: 94 95 ISPTM Determines whether the file descriptor is that of an open manager 96 device. On success, it returns the value 0. 97 98 UNLKPT Unlocks the manager and subsidiary devices. It returns 0 on 99 success. On failure, errno is set to EINVAL indicating that the 100 manager device is not open. 101 102 FILES 103 /dev/ptmx Pseudo-terminal manager clone device. 104 105 /dev/pts/N Pseudo-terminal subsidiary devices, 106 where N is a non-negative integer. 107 Located via calls to ptsname(3C). 108 109 EXAMPLES 110 Example 1 Opening the manager and subsidiary device for a pseudo- 111 terminal. 112 113 #include <stdlib.h> 114 #include <sys/types.h> 115 #include <sys/stat.h> 116 #include <unistd.h> 117 #include <stropts.h> 118 #include <fcntl.h> 119 #include <err.h> 120 ... 121 int fdm, fds; 122 char *subsidiaryname; 123 ... 124 /* 125 * NOTE: Portable applications should use posix_openpt(3C) here: 126 */ 127 if ((fdm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) < 0) { 128 err(1, "open manager"); 129 } 130 if (grantpt(fdm) != 0 || unlockpt(fdm) != 0 || 131 (subsidiaryname = ptsname(fdm)) == NULL) { 132 close(fdm); 133 err(1, "locate subsidiary"); 134 } 135 if ((fds = open(subsidiaryname, O_RDWR | O_NOCTTY)) < 0) { 136 close(fdm); 137 err(1, "open subsidiary"); 138 } 139 if (ioctl(fds, I_PUSH, "ptem") != 0 || 140 ioctl(fds, I_PUSH, "ldterm") != 0) { 141 close(fds); 142 close(fdm); 143 err(1, "push modules"); 144 } 145 146 SEE ALSO 147 close(2), getmsg(2), open(2), read(2), grantpt(3C), posix_openpt(3C), 148 ptsname(3C), unlockpt(3C), standards(5), ldterm(7M), pckt(7M), ptem(7M), 149 ddi_create_minor_node(9F) 150 151 illumos February 5, 2022 illumos