[comp.unix.ultrix] V7/BSD vs. S3/S5/POSIX tty drivers

guy@auspex.auspex.com (Guy Harris) (02/15/91)

(Not really a wizard-level question these days, and not really involved
with UNIX internals, and not Ultrix-specific; this long discourse should
probably be stuck in an FAQ list some day, at least until the POSIX tty
driver conquers the UNIX world and we can all *finally* forget about the
V7 driver and its descendants....)

>All bsd-based Unix-Implementations of getty (at least as far as known to me)
>support gettytab attributes f0, f1 and f2.
>
>According to TFM(gettytab) they take numeric values, where f0, f1 & f2
>represent the tty mode flags "to write messages", "to read login name",
>and "to leave terminal in".
>
>"... Terminal modes to be used for the output of the message,
>for input of the login name, and to leave ther terminal set as upon
>completion, are derived from the Boolean flags specified. If the derivation
>should prove inadequate, any (or all) of these three may be overridden
>with one of the f0, f1, or f2 numeric specifications, which can be
>used to specify (usually in octal, with a leading 0) the exact values
>of the flags. Local (new tty) flags are set in the top 16 bits of this
>(32-bit) value. ..."  [ From Dec Ultrix V4.0 Ref. Man. Vol 6 ]
>
>Now my question: how do the terminal mode flags (as know from termio or stty)
>correspond to the bits in f0 (or f1, f2)?
>
>Obviously it cannot be a 1:1 corresponency, since the struct termio
>contains 4 short values (c_iflag, c_oflag, c_cflag, c_lflag),
>or - in other words - 64 bits.
>
>Any ideas/experiences anyone?

There are two general flavors of UNIX terminal drivers: "V7ish" and
"System III"ish.  (We ignore "V6ish" terminal drivers, as they're really
ancient and obsolete.)

"V7ish" terminal drivers have the "ioctl" functions TIOCGETP,
TIOCSETP, TIOCSETN, TIOCGETC, and TIOCSETC, and may have other functions. 
TIOCGETP, TIOCSETP, and TIOCSETN use "struct sgtty", which includes the
member "sg_flags", which is a "short", generally 16 bits.

Some systems with "V7ish" terminal drivers have the functions TIOCLBIS,
TIOCLBIC, TIOCLSET, and TIOCLGET, which use a "local mode word", with 16
bits.

"System III"ish terminal drivers have one or more of:

	the "ioctl" functions TCGETA, TCSETA, TCSETAW, and TCSETAF;

	the "ioctl" functions TCGETS, TCSETS, TCSETSW, and TCSETSF;

	the POSIX functions "tcgetattr()" and "tcsetattr()".

TCGETA, TCSETA, TCSETAW, and TCSETAF use "struct termio", which includes
the members "c_iflag", "c_oflag", "c_cflag", and "c_lflag"; in "struct
termio", they are all "unsigned short", generally 16 bits.

TCGETS, TCSETS, TCSETSW, and TCSETSF, as well as "tcgetattr()" and
"tcsetattr()", use "struct termios", which also includes the members
"c_iflag", "c_oflag", "c_cflag", and "c_lflag"; in "struct termios",
they are all "unsigned long", or "tcflag_t", generally 32 bits.

The "f0", "f1", and "f2" flags in "gettytab" are the 16 bits from
"sgtty.sg_flags", plus the 16 bits from the "local mode word", as
described above (the "local mode word" flags are in the upper 16 bits). 

Some systems support both interfaces, either by some subterfuge such as
having multiple line disciplines, or by translating one style of "ioctl"
into another.  SunOS 4.x and S5R4 do the latter; they support a "System
III"ish terminal driver as their native tty driver, with a streams
module that translates "V7ish" "ioctl"s into "System III"ish "ioctl"s. 
The underlying "System III"ish tty driver has been extended to support a
bunch of BSDish features.

Here's stuff from the manual page for that streams module, which gives
some indication of how the modes are mapped.  Note that *NOT* all
systems with "System III"ish tty drivers have all the modes described
below; if your system doesn't document it, it probably doesn't have it. 
Some fairly old systems with "V7ish" tty drivers may not have all the
BSD features listed either.

     The basic ioctl calls use the sgttyb  structure  defined  by
     <sys/ioctl.h>:

          struct sgttyb {
               char sg_ispeed;
               char sg_ospeed;
               char sg_erase;
               char sg_kill;
               short sg_flags;
          };

     The sg_ispeed and sg_ospeed fields describe  the  input  and
     output  speeds  of the device, and reflect the values in the
     c_cflag field of the termio  structure.   The  sg_erase  and
     sg_kill  fields  of the argument structure specify the erase
     and kill characters respectively, and reflect the values  in
     the VERASE and VKILL members of the c_cc field of the termio
     structure.

     The  sg_flags  field  of  the  argument  structure  contains
     several  flags  that determine the system's treatment of the
     terminal.  They are mapped into flags in fields of the  ter-
     minal state, represented by the termio structure.

     Delay type 0 is always mapped into the equivalent delay type
     0 in the c_oflag field of the termio structure.  Other delay
     mappings are performed as follows:

          sg_flags    c_oflag
          BS1         BS1
          FF1         VT1
          CR1         CR2
          CR2         CR3
          CR3         not supported
          TAB1        TAB1
          TAB2        TAB2
          XTABS       TAB3
          NL1         ONLRET|CR1
          NL2         NL1

     If previous  TIOCLSET  or  TIOCLBIS  ioctl  calls  have  not
     selected  LITOUT  or  PASS8  mode,  and  if  RAW mode is not
     selected, the ISTRIP flag is set in the c_iflag field of the
     termio  structure,  and the EVENP and ODDP flags control the
     parity of characters sent to the terminal and accepted  from
     the terminal:

     0           Parity is not  to  be  generated  on  output  or
                 checked  on  input; the character size is set to
                 CS8 and  the  PARENB  flag  is  cleared  in  the
                 c_cflag field of the termio structure.

     EVENP       Even parity characters are to  be  generated  on
                 output  and accepted on input; the INPCK flag is
                 set in the c_iflag field of  the  termio  struc-
                 ture,  the  character size is set to CS7 and the
                 PARENB flag is set in the c_cflag field  of  the
                 termio structure.

     ODDP        Odd parity characters are  to  be  generated  on
                 output  and accepted on input; the INPCK flag is
                 set in the c_iflag field, the character size  is
                 set  to  CS7 and the PARENB and PARODD flags are
                 set in the c_cflag field of  the  termio  struc-
                 ture.

     EVENP|ODDP  Even parity characters are to  be  generated  on
                 output and characters of either parity are to be
                 accepted on input; the INPCK flag is cleared  in
                 the  c_iflag field, the character size is set to
                 CS7 and the PARENB flag is set  in  the  c_cflag
                 field of the termio structure.

     The RAW flag disables all output processing (the OPOST  flag
     in  the  c_oflag  field,  and  the XCASE flag in the c_lflag
     field, are cleared in the termio structure) and  input  pro-
     cessing (all flags in the c_iflag field other than the IXOFF
     and IXANY flags are cleared in  the  termio  structure).   8
     bits  of data, with no parity bit, are accepted on input and
     generated on output; the character size is set  to  CS8  and
     the PARENB and PARODD flags are cleared in the c_cflag field
     of the termio structure.  The  signal-generating  and  line-
     editing control characters are disabled by clearing the ISIG
     and ICANON flags in the c_lflag field of the  termio  struc-
     ture.

     The CRMOD flag turn input  RETURN  characters  into  NEWLINE
     characters,  and  output and echoed NEWLINE characters to be
     output as a RETURN followed by a LINEFEED. The ICRNL flag in
     the  c_iflag  field,  and  the  OPOST and ONLCR flags in the
     c_oflag field, are set in the termio structure.

     The LCASE flag maps upper-case letters in the ASCII  charac-
     ter  set to their lower-case equivalents on input (the IUCLC
     flag is set in  the  c_iflag  field),  and  maps  lower-case
     letters  in  the  ASCII  character  set  to their upper-case
     equivalents on output (the OLCUC flag is set in the  c_oflag
     field).   Escape  sequences  are accepted on input, and gen-
     erated on output, to handle  certain  ASCII  characters  not
     supported  by  older terminals (the XCASE flag is set in the
     c_lflag field).

     Other flags are directly  mapped  to  flags  in  the  termio
     structure:

          sg_flags    flags in termio structure
          CBREAK      complement of ICANON in c_lflag field
          ECHO        ECHO in c_lflag field
          TANDEM      IXOFF in c_iflag field

     Another structure associated with  each  terminal  specifies
     characters  that  are  special in both the old Version 7 and
     the newer 4BSD terminal interfaces.  The following structure
     is defined by <sys/ioctl.h>:

          struct tchars {
               char t_intrc;  /* interrupt */
               char t_quitc;  /* quit */
               char t_startc; /* start output */
               char t_stopc;  /* stop output */
               char t_eofc;   /* end-of-file */
               char t_brkc;   /* input delimiter (like nl) */
          };

     The characters are mapped to members of the  c_cc  field  of
     the termio structure as follows:

          tchars      c_cc index
          t_intrc     VINTR
          t_quitc     VQUIT
          t_startc    VSTART
          t_stopc     VSTOP
          t_eofc      VEOF
          t_brkc      VEOL

     Also associated with each terminal is  a  local  flag  word,
     specifying  flags  supported by the new 4BSD terminal inter-
     face.  Most of these flags are directly mapped to  flags  in
     the termio structure:

          local flags flags in termio structure
          LCRTBS      not supported
          LPRTERA     ECHOPRT in the c_lflag field
          LCRTERA     ECHOE in the c_lflag field
          LTILDE      not supported
          LTOSTOP     TOSTOP in the c_lflag field
          LFLUSHO     FLUSHO in the c_lflag field
          LNOHANG     CLOCAL in the c_cflag field
          LCRTKIL     ECHOKE in the c_lflag field
          LCTLECH     CTLECH in the c_lflag field
          LPENDIN     PENDIN in the c_lflag field
          LDECCTQ     complement of IXANY in the c_iflag field
          LNOFLSH     NOFLSH in the c_lflag field

     Another structure  associated  with  each  terminal  is  the
     ltchars  structure  which defines control characters for the
     new 4BSD terminal interface.  Its structure is:
          struct ltchars {
               char t_suspc;  /* stop process signal */
               char t_dsuspc; /* delayed stop process signal */
               char t_rprntc; /* reprint line */
               char t_flushc; /* flush output (toggles) */
               char t_werasc; /* word erase */
               char t_lnextc; /* literal next character */
          };

     The characters are mapped to members of the  c_cc  field  of
     the termio structure as follows:

          ltchars     c_cc index
          t_suspc     VSUSP
          t_dsuspc    VDSUSP
          t_rprntc    VREPRINT
          t_flushc    VDISCARD
          t_werasc    VWERASE
          t_lnextc    VLNEXT

IOCTLS
     ttcompat responds to the following ioctl calls.  All  others
     are passed to the module below.

     TIOCGETP    The argument is a pointer to  an  sgttyb  struc-
                 ture.   The  current  terminal state is fetched;
                 the appropriate characters in the terminal state
                 are  stored  in that structure, as are the input
                 and output speeds.  The values of the  flags  in
                 the sg_flags field are derived from the flags in
                 the terminal state and stored in the structure.

     TIOCSETP    The argument is a pointer to  an  sgttyb  struc-
                 ture.   The appropriate characters and input and
                 output speeds in the terminal state are set from
                 the  values  in that structure, and the flags in
                 the terminal state are set to match  the  values
                 of  the  flags  in  the  sg_flags  field of that
                 structure.  The state is changed with a  TCSETSF
                 ioctl, so that the interface delays until output
                 is quiescent, then throws away any unread  char-
                 acters, before changing the modes.

     TIOCSETN    The argument is a pointer to  an  sgttyb  struc-
                 ture.  The terminal state is changed as TIOCSETP
                 would change it, but a TCSETS ioctl is used,  so
                 that  the  interface neither delays nor discards
                 input.

     TIOCHPCL    The argument is ignored.  The HUPCL flag is  set
                 in the c_cflag word of the terminal state.

     TIOCFLUSH   The argument is a pointer to  an  int  variable.
                 If  its value is zero, all characters waiting in
                 input or output queues are flushed.   Otherwise,
                 the  value  of the int is treated as the logical
                 OR of the FREAD  and  FWRITE  flags  defined  by
                 <sys/file.h>; if the FREAD bit is set, all char-
                 acters waiting in input queues are flushed,  and
                 if the FWRITE bit is set, all characters waiting
                 in output queues are flushed.

     TIOCSTOP    The argument is ignored.  Output is  stopped  as
                 if the STOP character had been typed.

     TIOCSTART   The argument is ignored.  Output is restarted as
                 if the START character had been typed.

     TIOCGETC    The argument is a pointer to  an  tchars  struc-
                 ture.   The  current  terminal state is fetched,
                 and the appropriate characters in  the  terminal
                 state are stored in that structure.

     TIOCSETC    The argument is a pointer to  an  tchars  struc-
                 ture.   The values of the appropriate characters
                 in the terminal state are set from  the  charac-
                 ters in that structure.

     TIOCLGET    The argument  is  a  pointer  to  an  int.   The
                 current  terminal  state  is  fetched,  and  the
                 values of the local flags are derived  from  the
                 flags  in  the  terminal state and stored in the
                 int pointed to by the argument.

     TIOCLBIS    The argument is a pointer to an int whose  value
                 is  a  mask  containing  flags  to be set in the
                 local flags word.  The current terminal state is
                 fetched,  and  the values of the local flags are
                 derived from the flags in  the  terminal  state;
                 the  specified  flags  are set, and the flags in
                 the terminal state are  set  to  match  the  new
                 value of the local flags word.

     TIOCLBIC    The argument is a pointer to an int whose  value
                 is  a mask containing flags to be cleared in the
                 local flags word.  The current terminal state is
                 fetched,  and  the values of the local flags are
                 derived from the flags in  the  terminal  state;
                 the  specified  flags are cleared, and the flags
                 in the terminal state are set to match  the  new
                 value of the local flags word.

     TIOCLSET    The argument is a pointer to an int containing a
                 new set of local flags.  The flags in the termi-
                 nal state are set to match the new value of  the
                 local flags word.

     TIOCGLTC    The argument is a pointer to an  ltchars  struc-
                 ture.   The values of the appropriate characters
                 in the terminal state are stored in that  struc-
                 ture.

     TIOCSLTC    The argument is a pointer to an  ltchars  struc-
                 ture.   The values of the appropriate characters
                 in the terminal state are set from  the  charac-
                 ters in that structure.