Terminal I/O POSIX termios Two terminal I/O modes Canonical and non-canonical Getting and setting terminal attributes Terminal window size: struct winsize tty One of the first terminals was the TeleTypeWriter from which we get the abbreviation tty A terminal is usually interactive and can be either local or connected via a network A tty is connected at two “ends” For real terminals, one end is connected to hardware, such as the monitor, and the other end to software, such as the shell Pseudo terminals (covered next time) have both ends connected to software such as telnet etc Terminal I/O Modes Canonical mode (aka cooked mode) Default terminal mode Provides a simple line editor. Input is sent to application one line at a time Most UNIX systems implement this in a module known as the “terminal line discipline” Non-canonical mode (aka raw mode) Input not assembled into lines. Data passed to application as it is received Terminal Operations int isatty(int desc); desc is an open file descriptor Returns 1 if the FD is connected to a tty device or 0 otherwise char *ttyname(int fd); Returns the pathname of the terminal device or NULL on error (such as fd is not associated with a tty device) Terminal Operations char *ctermid(char *s); Returns the pathname of the controlling terminal. If s is NULL, static buffer is used Pass in a buffer of length L_ctermid to avoid the static buffer termios overview Structure defined in <termios.h> that contains the terminal device characteristics that we can change 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 flags */ cc_t c_cc[NCCS]; /* control chars */ }; termios overview c_iflag Input flags. Controls the input of characters by the terminal device driver (strip 8th bit on input, enable parity, etc) c_oflag Output flags. Controls driver output (perform output processing, map newline to CR/LF, etc) termios overview c_cflag Control flags. Affect the RS-232 serial lines (ignore modem status lines, one or two stop bits per character, etc) c_lflag Local flags. Affect interface between driver and user (echo on or off, visually erase characters, enable terminal-generated signals, job control stop signal for background output, etc) termios overview c_cc An array of special characters we can change such as Ctrl D etc. NCCS is usually 15-20 elements. POSIX defines 11, the rest are implementation specific cc_t is large enough to hold a special character. Usually an unsigned char See figs 18.3-18.6 staring on page 635 for list of flags Fig 18.7 on page 637 lists functions that manipulate these flags termios overview tcgetattr - fetch attributes tcsetattr - set attributes tcdrain - wait for all output to be transmitted tcflush - flush pending input and/or output Special Input Characters Fig 18.9 on page 638 lists the special input characters 11 are POSIX standard. Of those, we can not change the value of CR (\r) or NL (\n). The other 9 can be changed Getting and Setting Terminal Attributes int tcgetattr(int fd, struct termios *termios_p); int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); termios_p points to a termios structure optional_actions specifies when to apply the new attributes TCSANOW - set attributes now TCSADRAIN – wait for all output to transmit TCSAFLUSH – flush pending input/output Terminal Option Flags Section 18.5 lists the various flags that can be used with the termios structure. See page 645-651 for full list c_cflg CSIZE a mask that specifies the number of bits per byte (not including parity bit if used) Values are CS5, CS6, CS7 and CS8 See example on page 644 for usage Terminal Option Flags PARENB if set, generates and checks parity for outgoing and incoming characters PARODD If set, parity is odd, otherwise parity is even c_lflag ECHO if set, input characters are echoed back to the terminal device. Can be used in either canonical or non-canonical modes Terminal Option Flags c_iflag ICANON if set, canonical mode is in effect ECHONL if set, and if ICANON is set, the NL character is echoed, even if ECHO is not set ISTRIP when set, valid input bytes are stripped to 7 bits. Otherwise all 8 bits are processed ETC… stty command Shell command to examine and modify terminal attributes stty –a displays all the terminal attributes Baud Rate Functions Baud Rate – bits per second B2400, B9600, B19200, B38400, etc Get I/O Baud Rate speed_t cfgetispeed(const struct termios *termios_p); speed_t cfgetospeed(const struct termios *termios_p); Set I/O Baud Rate int cfsetispeed(struct termios *termios_p, speed_t speed); int cfsetospeed(struct termios *termios_p, speed_t speed); Returns 0 if ok, -1 on error Line Control Functions See page 653 for full explanation int int int int tcdrain(int fd); tcflow(int fd, int action); tcflush(int fd, int queue_selector); tcsendbreak(int fd, int duration); Canonical Mode Provides limited line editing. Data sent to application one line at a time When we issue a read it returns when The requested number of bytes have been read A line delimiter is encountered (NL, EOF, EOL, EOL2 and sometimes CR) A signal is caught but read not automatically restarted Non-Canonical Mode Specified by turning off the ICANON flag in the c_lflag field of the termios structure Input data not assembled into lines Some characters not processed (ERASE, KILL, EOF, NL, EOL, EOL2, CR, REPRINT, STATUS and WERASE) Non-Canonical Mode Two variables (MIN and TIME) in the c_cc array indexed by VMIN and VTIME MIN - specifies the minimum number of bytes to read before a read returns TIME – specifies the number of tenths of a second to wait for data to arrive Non-Canonical Mode MIN > 0 MIN == 0 A: read returns [MIN, nbytes] before timer expires TIME > 0 Read returns [1,MIN) if time expires (TIME=interbyte timer. Caller can block indefinitely) C: read return [1, nbytes] before timer expires Read returns 0 if timer expires (TIME=read timer) B: read returns [MIN, nbytes] when TIME == 0 available (Caller can block indefinitely) D: read returns[0, nbytes] immediately Terminal Window Size Most UNIX systems provide a way to keep track of the current terminal window size and have the kernel notify the foreground process group when the size changes struct winsize{ unsigned short ws_row; /* rows in characters */ unsigned short ws_col; /* cols in characters */ unsigned short ws_xpixel /* unused */ unsigned short ws_ypixel /* unused */ }; Terminal Window Size Current window size can be fetched by calling ioctl with TIOCGWINSZ Can set a new value by calling ioctl with TIOCSWINSZ. If new value is different than old value it is stored in the kernel and a SIGWINCH is sent to the foreground process group (by default the signal is ignored)