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