The POSIX terminal interface is the generalized abstraction, comprising both an application programming interface for programs, and a set of behavioural expectations for users of a terminal, as defined by the POSIX standard and the Single Unix Specification. It is a historical development from the terminal interfaces of BSD version 4 and Seventh Edition Unix.
A multiplicity of I/O devices are regarded as "terminals" in Unix systems. [1] [2] These include:
Unlike its mainframe and minicomputer[ citation needed ] contemporaries, the original Unix system was developed solely for dumb terminals, and that remains the case today. [6] A terminal is a character-oriented device, comprising streams of characters received from and sent to the device. [6] [7] Although the streams of characters are structured, incorporating control characters, escape codes, and special characters, the I/O protocol is not structured as would be the I/O protocol of smart, or intelligent , terminals. There are no field format specifications. There's no block transmission of entire screens (input forms) of input data.
By contrast mainframes and minicomputers in closed architectures commonly use Block-oriented terminals.
The "capabilities" of a terminal comprise various dumb terminal features that are above and beyond what is available from a pure teletypewriter, which programs can make use of. They (mainly) comprise escape codes that can be sent to or received from the terminal. The escape codes sent to the terminal perform various functions that a CRT terminal (or software terminal emulator) is capable of that a teletypewriter is not, such as moving the terminal's cursor to positions on the screen, clearing and scrolling all or parts of the screen, turning on and off attached printer devices, programmable function keys, changing display colours and attributes (such as reverse video), and setting display title strings. The escape codes received from the terminal signify things such as function key, arrow key, and other special keystrokes (home key, end key, help key, PgUp key, PgDn key, insert key, delete key, and so forth). [8] [9]
These capabilities are encoded in databases that are configured by a system administrator and accessed from programs via the terminfo library (which supersedes the older termcap library), upon which in turn are built libraries such as the curses and ncurses libraries. Application programs use the terminal capabilities to provide textual user interfaces with windows, dialogue boxes, buttons, labels, input fields, menus, and so forth. [10] [11]
TERM
et al.The particular set of capabilities for the terminal that a (terminal-aware) program's input and output uses is obtained from the database rather than hardwired into programs and libraries, and is controlled by the TERM
environment variable (and, optionally for the termcap and terminfo libraries, the TERMCAP
and TERMINFO
environment variables, respectively). [10] This variable is set by whatever terminal monitor program spawns the programs that then use that terminal for its input and output, or sometimes explicitly. For example:
TERM
environment variable according to a system database (variously inittab or the configuration files for the ttymon or launchd programs) defining what local terminals are attached to what serial ports and what terminal types are provided by local virtual terminals or the local system console.TERM
environment variable immediately after login to the correct type. (More usually, the terminal type set by the getty program for the dial-up line, that the system administrator has determined to be used most often by dial-up users with remote terminals, matches the one used by the dial-up user and that user has no need to override the terminal type.)TERM
environment variable to the same terminal type as the SSH client. [12] TERM
environment variable to specify the type of terminal that it is emulating. Emulated terminals often do not exactly match real terminal hardware, and terminal emulators have type names dedicated for their use. The xterm program (by default) sets xterm
as the terminal type, for example. [13] The GNU Screen program sets screen
as the terminal type.Terminals provide job control facilities. Interactively, the user at the terminal can send control characters that suspend the currently running job, reverting to the interactive job control shell that spawned the job, and can run commands that place jobs in the "background" or that switch another, background, job into the foreground (unsuspending it if necessary). [14] [15]
Strictly speaking, in Unixes a terminal device comprises the underlying tty device driver, responsible for the physical control of the device hardware via I/O instructions and handling device interrupt requests for character input and output, and the line discipline. A line discipline is independent of the actual device hardware, and the same line discipline can be used for a terminal concentrator device responsible for multiple controlling terminals as for a pseudoterminal. In fact, the line discipline (or, in the case of BSD, AIX, and other systems, line disciplines) are the same across all terminal devices. It is the line discipline that is responsible for local echo, line editing, processing of input modes, processing of output modes, and character mapping. All these things are independent of the actual hardware, dealing as they do in the simple abstractions provided by tty device drivers: transmit a character, receive a character, set various hardware states. [16] [17]
In Seventh Edition Unix, BSD systems and derivatives including macOS, and Linux, each terminal device can be switched amongst multiple line disciplines. [18] In the AT&T STREAMS system, line disciplines are STREAMS modules that may be pushed onto and popped off a STREAMS I/O stack. [19]
The POSIX terminal interface is derived from the terminal interfaces of various Unix systems.
The terminal interface provided by Unix 32V and Seventh Edition Unix, and also presented by BSD version 4 as the old terminal driver, was a simple one, largely geared towards teletypewriters as terminals. Input was entered a line at a time, with the terminal driver in the operating system (and not the terminals themselves) providing simple line editing capabilities. A buffer was maintained by the kernel in which editing took place. Applications reading terminal input would receive the contents of the buffer only when the return key was pressed on the terminal to end line editing. The @ key sent from the terminal to the system would erase ("kill") the entire current contents of the editing buffer, and would be normally displayed as an '@' symbol followed by a newline sequence to move the print position to a fresh blank line. The # key sent from the terminal to the system would erase the last character from the end of the editing buffer, and would be normally displayed as an '#' symbol, which users would have to recognize as denoting a "rubout" of the preceding character (teletypewriters not being physically capable of erasing characters once they have been printed on the paper). [20] [21] [22] [23] [18]
From a programming point of view, a terminal device had transmit and receive baud rates, "erase" and "kill" characters (that performed line editing, as explained), "interrupt" and "quit" characters (generating signals to all of the processes for which the terminal was a controlling terminal), "start" and "stop" characters (used for modem flow control), an "end of file" character (acting like a carriage return except discarded from the buffer by the read()
system call and therefore potentially causing a zero-length result to be returned) and various basic mode flags determining whether local echo was emulated by the kernel's terminal driver, whether modem flow control was enabled, the lengths of various output delays, mapping for the carriage return character, and the three input modes. [24]
The three input modes were:
In line mode the line discipline performs all line editing functions and recognizes the "interrupt" and "quit" control characters and transforms them into signals sent to processes. Applications programs reading from the terminal receive entire lines, after line editing has been completed by the user pressing return. [21] [25]
cbreak mode is one of two character-at-a-time modes. (Stephen R. Bourne jokingly referred to it ( Bourne 1983 , p. 288) as a "half-cooked" and therefore "rare" mode.) The line discipline performs no line editing, and the control sequences for line editing functions are treated as normal character input. Applications programs reading from the terminal receive characters immediately, as soon as they are available in the input queue to be read. However, the "interrupt" and "quit" control characters, as well as modem flow control characters, are still handled specially and stripped from the input stream. [26] [27]
The programmatic interface for querying and modifying all of these modes and control characters was the ioctl()
system call. (This replaced the stty()
and gtty()
system calls of Sixth Edition Unix.) [29] [30] Although the "erase" and "kill" characters were modifiable from their defaults of # and @, for many years they were the pre-set defaults in the terminal device drivers, and on many Unix systems, which only altered terminal device settings as part of the login process, in system login scripts that ran after the user had entered username and password, any mistakes at the login and password prompts had to be corrected using the historical editing key characters inherited from teletypewriter terminals. [23]
With the BSD Unixes came job control, and a new terminal driver with extended capabilities. [18] These extensions comprised additional (again programmatically modifiable) special characters:
SUB
and EM
) caused the generation of a new SIGTSTP
signal to processes in the terminal's controlling process group. [27] ETB
, SYN
, and DC2
) performed additional line editing functions. "word erase" erased the last word at the end of the line editing buffer. "literal next" allowed any special character to be entered into the line editing buffer (a function available, somewhat inconveniently, in Seventh Edition Unix via the backslash character). "reprint" caused the line discipline to reprint the current contents of the line editing buffer on a new line (useful for when another, background, process had generated output that had intermingled with line editing). [27] The programmatic interface for querying and modifying all of these extra modes and control characters was still the ioctl()
system call, which its creators ( Leffler et al. 1989 , p. 262) described as a "rather cluttered interface". All of the original Seventh Edition Unix functionality was retained, and the new functionality was added via additional ioctl()
operation codes, resulting in a programmatic interface that had clearly grown, and that presented some duplication of functionality. [31]
System III introduced a new programming interface that combined Seventh Edition's separate ioctl()
operations to get and set flags and to get and set control characters into calls that used a termio
structure to hold both flags and control characters and that could get them in a single operation and set them in another single operation. It also split some of the flags from the Seventh Edition interface into multiple separate flags, and added some additional capabilities, although it did not support job control or the cooked-mode enhancements of 4BSD. [32] For example, it replaced the "cooked", "cbreak", and "raw" modes of Seventh Edition with different abstractions. The recognition of signal-generating characters is independent of input mode, and there are only the two input modes: canonical and non-canonical. (This allows a terminal input mode not present in Seventh Edition and BSD: canonical mode with signal generation disabled.)
System III's successors, including System V, used the same interface.
One of the major problems that the POSIX standard addressed with its definition of a general terminal interface was the plethora of programmatic interfaces. Although by the time of the standard the behaviour of terminals was fairly uniform from system to system, most Unixes having adopted the notions of line disciplines and the BSD job control capabilities, the programmatic interface to terminals via the ioctl()
system call was a mess. Different Unixes supplied different ioctl()
operations, with different (symbolic) names, and different flags. Portable source code had to contain a significant amount of conditional compilation to accommodate the differences across software platforms, even though they were all notionally Unix. [33]
The POSIX standard replaces the ioctl()
system entirely, with a set of library functions (which, of course, may be implemented under the covers via platform-specific ioctl()
operations) with standardized names and parameters. The termio
data structure of System V Unix was used as a template for the POSIX termios
data structure, whose fields were largely unchanged except that they now used alias data types for specifying the fields, allowing them to be easily ported across multiple processor architectures by implementors, rather than explicitly requiring the unsigned short
and char
data types of the C and C++ programming languages (which might be inconvenient sizes on some processor architectures). [33] [34]
POSIX also introduced support for job control, with the termios
structure containing suspend and delayed-suspend characters in addition to the control characters supported by System III and System V. It did not add any of the cooked-mode extensions from BSD, although SunOS 4.x, System V Release 4, Solaris, HP-UX, AIX, newer BSDs, macOS, and Linux have implemented them as extensions to termios
.
Each process in the system has either a single controlling terminal, or no controlling terminal at all. A process inherits its controlling terminal from its parent, and the only operations upon a process are acquiring a controlling terminal, by a process that has no controlling terminal, and relinquishing it, by a process that has a controlling terminal. [33]
No portable way of acquiring a controlling terminal is defined, the method being implementation defined. The standard defines the O_NOCTTY
flag for the open()
system call, which is the way of preventing what is otherwise the conventional way of acquiring a controlling terminal (a process with no controlling terminal open()
s a terminal device file that isn't already the controlling terminal for some other process, without specifying the O_NOCTTY
flag [35] ) but leaves its conventional semantics optional.
Each process also is a member of a process group. Each terminal device records a process group that is termed its foreground process group. The process groups control terminal access and signal delivery. Signals generated at the terminal are sent to all processes that are members of the terminal's foreground process group. read()
and write()
I/O operations on a terminal by a process that is not a member of the terminal's foreground process group will and may optionally (respectively) cause signals ( SIGTTIN
and SIGTTOU
respectively) to be sent to the invoking process. Various terminal-mode-altering library functions have the same behaviour as write()
, except that they always generate the signals, even if that functionality is turned off for write()
itself. [36] [37]
termios
data structure The data structure used by all of the terminal library calls is the termios
structure, [38] whose C and C++ programming language definition is as follows: [34]
structtermios{tcflag_tc_iflag;// Input modestcflag_tc_oflag;// Output modestcflag_tc_cflag;// Control modestcflag_tc_lflag;// Local modescc_tc_cc[NCCS];// Control characters};
The order of the fields within the termios
structure is not defined, and implementations are allowed to add non-standard fields. [34] Indeed, implementations have to add non-standard fields for recording input and output baud rates. These are recorded in the structure, in an implementation-defined form, and accessed via accessor functions, rather than by direct manipulation of the field values, as is the case for the standardized structure fields. [39]
The data type aliases tcflag_t
and cc_t
, as well as the symbolic constant NCCS
and symbolic constants for the various mode flags, control character names, and baud rates, are all defined in a standard header termios.h
. (This is not to be confused with the similarly named header termio.h
from System III and System V, which defines a similar termio
structure and a lot of similarly named symbolic constants. This interface is specific to System III and System V, and code that uses it will not necessarily be portable to other systems.) [40]
The structure's fields are (in summary, for details see the main article[ clarification needed ]):
c_iflag
c_oflag
c_cflag
c_lflag
SIGTTOU
signal by the write()
system call [39] The library functions are (in summary, for details see the main article[ clarification needed ]):
tcgetattr()
termios
structure [43] tcsetattr()
termios
structure, optionally waiting for queued output to drain and flushing queued input [43] cfgetispeed()
termios
structure [44] cfgetospeed()
termios
structure [44] cfsetispeed()
termios
structure [44] cfsetospeed()
termios
structure [44] tcsendbreak()
tcdrain()
tcflush()
tcflow()
tcgetpgrp()
tcsetpgrp()
Field | meaning | Retrieved by read() | Notes |
---|---|---|---|
c_cc[VEOF] | end of file | No | Only processed by canonical mode line editing |
c_cc[VEOL] | end of line | Yes | Only processed by canonical mode line editing |
c_cc[VERASE] | "erase" | No | Only processed by canonical mode line editing |
c_cc[VKILL] | "kill" | No | Only processed by canonical mode line editing |
c_cc[VINTR] | "interrupt" | No | Signal-generation character independent of input mode |
c_cc[VQUIT] | "quit" | No | Signal-generation character independent of input mode |
c_cc[VSUSP] | "suspend" | No | Signal-generation character independent of input mode |
c_cc[VSTOP] | "stop" | No | Modem flow control character independent of input mode |
c_cc[VSTART] | "start" | No | Modem flow control character independent of input mode |
The c_cc[]
array member of the termios
data structure specifies all of the (programmatically modifiable) special characters. The indexes into the array are symbolic constants, one for each special character type, as in the table at right. (Two further entries in the array are relevant to non-canonical mode input processing and are discussed below.) [43]
Non-programmatically modifiable special characters are linefeed (ASCII LF
) and carriage return (ASCII CR
). [47]
Input processing determines the behaviour of the read()
system call on a terminal device and the line editing and signal-generation characteristics of the line discipline. Unlike the case of Seventh Edition Unix and BSD version 4, and like the case of System III and System V, line editing operates in one of just two modes: canonical mode and non-canonical mode. The basic difference between them is when, from the point of view of the blocking/non-blocking requirements of the read()
system call (specified with the O_NONBLOCK
flag on the file descriptor via open()
or fcntl()
), data "are available for reading". [48]
In canonical mode, data are accumulated in a line editing buffer, and do not become "available for reading" until line editing has been terminated by the user (at the terminal) sending a line delimiter character. Line delimiter characters are special characters, and they are end of file, end of line, and linefeed (ASCII LF
). The former two are settable programmatically, whilst the latter is fixed. The latter two are included in the line editing buffer, whilst the former one is not. [49]
More strictly, zero or more lines are accumulated in the line editing buffer, separated by line delimiters (which may or may not be discarded once read()
comes around to reading them), and line editing operates upon the part of the line editing buffer that follows the last (if any) line delimiter in the buffer. So, for example, the "erase" character (whatever that has been programmed to be) will erase the last character in the line buffer only up to (but not including) a preceding line delimiter. [49]
In non-canonical mode, data are accumulated in a buffer (which may or may not be the line editing buffer — some implementations having separate "processed input" and "raw input" queues) and become "available for reading" according to the values of two input control parameters, the c_cc[MIN]
and c_cc[TIME]
members of the termios
data structure. Both are unsigned quantities (because cc_t
is required to be an alias for an unsigned type). The former specifies a minimum number of characters, and the latter specifies a timeout in tenths of a second. [50] There are four possibilities:
c_cc[TIME]
and c_cc[MIN]
are both zeroread()
returns immediately with whatever data are in the buffer (potentially returning zero if there are zero data available). [51] c_cc[TIME]
is non-zero and c_cc[MIN]
is zeroread()
system call, or if a single character is received. In other words, read()
waits for a maximum specified total time, and may return zero data, and returns any data as soon as they are received. [51] c_cc[TIME]
is zero and c_cc[MIN]
is non-zeroread()
waits for a minimum amount of data (which may be larger than what the caller is prepared to read in the system call), will not return zero data, and may wait indefinitely. [51] c_cc[TIME]
and c_cc[MIN]
are both non-zeroread()
waits for a minimum amount of data (which may be larger than what the caller is prepared to read in the system call), will not return zero data, may wait indefinitely, but won't wait longer than the specified timeout if at least one character is in the buffer to be read. [51] Output processing is largely unchanged from its System III/System V roots. Output mode control flags determine various options:
An operating system (OS) is system software that manages computer hardware, software resources, and provides common services for computer programs.
A Unix shell is a command-line interpreter or shell that provides a command line user interface for Unix-like operating systems. The shell is both an interactive command language and a scripting language, and is used by the operating system to control the execution of the system using shell scripts.
A terminal emulator, or terminal application, is a computer program that emulates a video terminal within some other display architecture. Though typically synonymous with a shell or text terminal, the term terminal covers all remote terminals, including graphical interfaces. A terminal emulator inside a graphical user interface is often called a terminal window.
The Open Sound System (OSS) is an interface for making and capturing sound in Unix and Unix-like operating systems. It is based on standard Unix devices system calls. The term also sometimes refers to the software in a Unix kernel that provides the OSS interface; it can be thought of as a device driver for sound controller hardware. The goal of OSS is to allow the writing of sound-based applications that are agnostic of the underlying sound hardware.
In computer programming, standard streams are interconnected input and output communication channels between a computer program and its environment when it begins execution. The three input/output (I/O) connections are called standard input (stdin), standard output (stdout) and standard error (stderr). Originally I/O happened via a physically connected system console, but standard streams abstract this. When a command is executed via an interactive shell, the streams are typically connected to the text terminal on which the shell is running, but can be changed with redirection or a pipeline. More generally, a child process inherits the standard streams of its parent process.
The C programming language provides many standard library functions for file input and output. These functions make up the bulk of the C standard library header <stdio.h>. The functionality descends from a "portable I/O package" written by Mike Lesk at Bell Labs in the early 1970s, and officially became part of the Unix operating system in Version 7.
A computer terminal is an electronic or electromechanical hardware device that can be used for entering data into, and transcribing data from, a computer or a computing system. The teletype was an example of an early-day hard-copy terminal and predated the use of a computer screen by decades.
In computing, "Not a typewriter" or ENOTTY is an error code defined in the errno.h found on many Unix systems. This code is now used to indicate that an invalid ioctl number was specified in an ioctl system call.
In computing, text-based user interfaces (TUI), is a retronym describing a type of user interface (UI) common as an early form of human–computer interaction, before the advent of modern conventional graphical user interfaces (GUIs). Like GUIs, they may use the entire screen area and accept mouse and other inputs. They may also use color and often structure the display using special graphical characters such as ┌ and ╣, referred to in Unicode as the "box drawing" set. The modern context of use is usually a terminal emulator.
In some operating systems, including Unix and Linux, a pseudoterminal, pseudotty, or PTY is a pair of pseudo-device endpoints (files) which establish asynchronous, bidirectional communication (IPC) channel between two or more processes. The master provides means by which a terminal emulator process controls the slave. The slave, emulates a hardware text terminal device. PTY are similar to bidirectional pipes.
The seven standard Unix file types are regular, directory, symbolic link, FIFO special, block special, character special, and socket as defined by POSIX. Different OS-specific implementations allow more types than what POSIX requires. A file's type can be identified by the ls -l
command, which displays the type in the first character of the file-system permissions field.
In computer networking, STREAMS is the native framework in Unix System V for implementing character device drivers, network protocols, and inter-process communication. In this framework, a stream is a chain of coroutines that pass messages between a program and a device driver. STREAMS originated in Version 8 Research Unix, as Streams.
In computing, ioctl
is a system call for device-specific input/output operations and other operations which cannot be expressed by regular system calls. It takes a parameter specifying a request code; the effect of a call depends completely on the request code. Request codes are often device-specific. For instance, a CD-ROM device driver which can instruct a physical device to eject a disc would provide an ioctl
request code to do so. Device-independent request codes are sometimes used to give userspace access to kernel functions which are only used by core system software or still under development.
In Unix and Unix-like operating systems, job control refers to control of jobs by a shell, especially interactively, where a "job" is a shell's representation for a process group. Basic job control features are the suspending, resuming, or terminating of all processes in the job/process group; more advanced features can be performed by sending signals to the job. Job control is of particular interest in Unix due to its multiprocessing, and should be distinguished from job control generally, which is frequently applied to sequential execution.
A line discipline (LDISC) is a layer in the terminal subsystem in some Unix-like systems. The terminal subsystem consists of three layers: the upper layer to provide the character device interface, the lower hardware driver to communicate with the hardware or pseudo terminal, and the middle line discipline to implement behavior common to terminal devices.
In telecommunications, echo is the local display of data, either initially as it is locally sourced and sent, or finally as a copy of it is received back from a remote destination. Local echo is where the local sending equipment displays the outgoing sent data. Remote echo is where the display is a return copy of data as received remotely. Both are used together in a computed form of error detection to ensure that data received at the remote destination of a telecommunication are the same as data sent from the local source. When (two) modems communicate in echoplex mode the remote modem echoes whatever it receives from the local modem.
In Unix-like operating systems, a device file or special file is an interface to a device driver that appears in a file system as if it were an ordinary file. There are also special files in DOS, OS/2, and Windows. These special files allow an application program to interact with a device by using its device driver via standard input/output system calls. Using standard system calls simplifies many programming tasks, and leads to consistent user-space I/O mechanisms regardless of device features and functions.
Toybox is a free and open-source software implementation of over 200 Unix command line utilities such as ls, cp, and mv. The Toybox project was started in 2006, and became a 0BSD licensed BusyBox alternative. Toybox is used for most of Android's command line tools in all currently supported Android versions, and is also used to build Android on Linux and macOS. All of the tools are tested on Linux, and many of them also work on BSD and macOS.
A command-line interpreter or command-line processor uses a command-line interface (CLI) to receive commands from a user in the form of lines of text. This provides a means of setting parameters for the environment, invoking executables and providing information to them as to what actions they are to perform. In some cases the invocation is conditional based on conditions established by the user or previous executables. Such access was first provided by computer terminals starting in the mid-1960s. This provided an interactive environment not available with punched cards or other input methods.
The Seventh Edition Unix terminal interface is the generalized abstraction, comprising both an application programming interface for programs and a set of behavioural expectations for users, of a terminal as historically available in Seventh Edition Unix. It has been largely superseded by the POSIX terminal interface.