- Forward


Unix Terminals
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Background
Back SMYC Forward
  • History:
    • UNIX systems were accessed using a piece of hardware called a terminal (often over an RS-232 serial cable)
    • Each specific device had its own device driver
  • Today:
    • UNIX systems are accessed using a terminal emulator (e.g., xterm)
    • Terminal emulators use a device driver called a pseudoterminal
    • As with other devices, a terminal is modeled as a file
Terminals as Files
Back SMYC Forward
  • Where are the files?
    • Usually in /dev or /dev/pts
  • An example that might surprise you:
    1. Open two terminals
    2. Enter tty in each to get its name
    3. In one terminal, enter ls (you should know what will happen)
    4. In the same terminal, enter ls > other where other is the name of the other terminal (e.g., /dev/pts/1)
    5. Figure out what happened and why
  • Another example:
    • Do the same thing but with man man (so that the output requires more than one "screen" and you need to provide input to move between "screens")
    • Figure out what happened and why
The Role of Terminal Drivers
Back SMYC Forward
  • Queue Management:
    • Input from the terminal to the reading process(es)
    • Output from process(es) to the terminal
  • Special Character Handling:
    • Interrupt (normally Ctrl+C)
    • End-Of-File (normally Ctrl+D)
Standard Operating Modes
Back SMYC Forward
  • Canonical:
    • Line-by-line (with line editing) which means that read() only returns when a line-feed character is encountered
  • Noncanonical:
    • Not line-by-line
Setting Terminal Atrtibutes: tcsetattr() tcsetattr
Back SMYC Forward
int tcsetattr(int fd, int options, const struct termios *attr);
Purpose:
Set the parameters associated with the terminal
Details:
fd The open file descriptor for the terminal
options TCSANOW to make changes now; TCSADRAIN to wait until after all output is transmitted; TCSAFLUSH to both wait and discard input not received
attr The attributes to set
Return 0 on success; -1 on error
#include <termios.h> termios.h
#include <unistd.h> unistd.h
The termios Structure
Back SMYC Forward
struct termios { tcflag_t c_iflag; // Input flags tcflag_t c_oflag; // Output flags tcflag_t c_cflag; // Control flags tcflag_t c_lflag; // Local modes cc_t c_line; // Do not use cc_t c_cc[NCCS}; // Special characters speed_t c_ispeed; // Do not use speed_t c_ospeed; // Do not use }
Some Useful Flags
Back SMYC Forward
For c_iflag
ICRNL Map CR to LF (i.e., newline) on input
IGNCR Ignore CR on input
For c_lflag
ECHO Echo input characters
ICANON Canonical model input
IEXTEN Enable extended processing of input characters
ISIG Enable signal generating characters
When Does read() Return in Noncanonical Mode?
Back SMYC Forward
  • Polling:
    • VMIN is 0, VTIME is 0
  • Blocking:
    • VMIN is > 0, VTIME is 0
  • Timeout:
    • VMIN is 0, VTIME is > 0
  • Interbyte Timeout:
    • VMIN is > 0, VTIME is > 0
An Example: Line-Based Input
Back SMYC Forward
unixexamples/terminal/line.c
 
An Example: Character-Based Input
Back SMYC Forward
unixexamples/terminal/yesno.c
 
File Type Check: isatty() isatty
Back SMYC Forward
int isatty(int fd);
Purpose:
Determine if a file descriptor is associated with a terminal
Details:
fd The file descriptor of interest
Return 1 (i.e., "true") if a terminal; "false" otherwise
#include <unistd.h> unistd.h
Terminal Name: ttyname() ttyname
Back SMYC Forward
char *ttyname(int fd);
Purpose:
Find the name of a terminal
Details:
fd The file descriptor of the terminal
Return The name of the terminal (usually in /dev or /dev/pts)
#include <unistd.h> unistd.h

This function is equivalent to the tty tty command.

There's Always More to Learn
Back -