Decoded: stty (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]

Logical flow of stty command (coreutils)

Summary

stty - print or change terminal characteristics

[Source] [Code Walkthrough]

Lines of code: 2323
Principal syscall: write()
Support syscalls: open()
Options: 8 (3 short, 5 long, does not include legacy digits for field skip)

Descended from stty introduced in Version 2 UNIX (1972)
Added to Shellutils in November 1992 [First version]
Number of revisions: 213

The first 1000 lines of code in stty navigate compatibility issues among the many terminal types available across platforms. The core utility collects and sets terminal parameters via tcgetattr() and tcsetattr()

Helpers:
  • apply_settings() - Retrieves mode, speed, and attribute variables from a device
  • baud_to_value() - Finds the actual rate value from the internal speed_t
  • display_all() - Executes the display all option (-a)
  • display_changed() - Displays settings that don't match the 'sane' mode (default display)
  • display_recoverable() - Print mode information in a transferrable format (-g)
  • display_settings() - Displays settings based on output type
  • display_speed() - Displays the line speeds
  • display_window_size() - Displays the number of rows and columns of a tty device
  • get_win_size() - Gets the window size via ioctl()
  • integer_arg() - Converts an input string to its integer equivalent with bounds checking
  • mode_type_flag() - Returns a pointer to the proper mode in the struct termios
  • recover_mode() - Checks if the input is recoverable from display_recoverable(-g)
  • sane_mode() - Applies all of sane mode settings
  • screen_columns() - Gets the number of screen columns
  • set_control_char() - Sets the control character in the control mode (c_cc)
  • set_mode() - Sets the combination mode settings
  • set_speed() - Sets the line speed as given
  • set_window_size() - Sets the window dimensions via ioctl()
  • string_to_baud() - Looks up an input speed string to the internal baud rate, speed_t
  • strtoul_cc_t() - Parses the special control characters
  • strtoul_tcflag_t() - Parses the input, output, control, and local flags
  • visible() - Convert a string to all printables
  • wrapf() - Prints formatted strings with line wrapping
External non-standard helpers:
  • cfsetispeed() - Sets the input baud rate (POSIX)
  • cfsetospeed() - Sets the output baud rate (POSIX)
  • die() - Exit with mandatory non-zero error and message to stderr
  • error() - Outputs error message to standard error with possible process termination

Setup

stty defines a generic mode structure, mode_info, to describe the settings for the mode. It then defines an array of dozens of distinct modes that may be referenced as a user argument

main() introduces a few local variables:

  • argi - The argument index
  • *device_name - The target tty device (either user provided or 'standard input')
  • *file_name - The user provided device tty file
  • noargs - Flag set if no arguments are passed
  • optc - The character for the next option to process
  • opti - The option index
  • recoverable_output - Flag set if the user wants to output parsable stty info (-g)
  • require_set_attr - True if the user needs to set information
  • speed_was_set - Flag true if the ispeed or ospeed were set
  • verbose_output - Flag set if the user requests maximum info (-a)

Parsing

Parsing is more complicated than many utilities due to the number of possible arguments (and potential arguments within arguments). At a minimum, parsing considers the following questions:

  • Is the output for people to read or to pass to another utility?
  • Is there a specified TTY to use?

Parsing failures

These failure cases are explicitly checked:

  • Printing both a human readable and parsable form
  • Specifying more than one tty device
  • Trying to combine both display and set operations
  • Unknown option used

User specified parsing failures result in a short error message followed by the usage instructions. Access related parsing errors die with an error message.


Execution

stty execution follows a predictable path despite the painful details behind all of the modes.

  • Check the provided mode in order to gather setting requirements
  • Open the device and set controls: O_NONBLOCK
  • Get the current tty mode
  • Display output, if requested
  • Set output, if requested

Failure cases:

  • Unable to pull window information via ioctl()
  • Open to open target device
  • Unable to get or set any mode information

All failures at this stage output an error message to STDERR and return without displaying usage help


[Back to Project Main Page]