Not all UNIX-based interfaces are graphical. Character-based interfaces were the original mainstay of UNIX computing long before the graphical workstation was conceived. There are two options for character-based interfaces. Either a migration to the Microsoft Interix environment can take place with minimal change, or a graphical interface (Windows-based or HTML) can replace the character-based interface. A preliminary port to POSIX smoothes the migration to Interix.
The POSIX termios structure and a new set of access calls replace the two traditional terminal hardware interfaces, namely termio structures in System V and stty structures in BSD.
The POSIX input/output (I/O) model is very similar to the System V model. Two modes exist: canonical and noncanonical. Canonical input is line-based , like BSD cooked mode. Noncanonical mode is character-based, like BSD raw or cbreak mode. The Interix subsystem includes a true, noncanonical mode, with support for cc_c[VMIN ] and cc_c[VTIME] .
The termios structure is defined in Termios.h, as shown in the following listing:
struct termios { tcflag_t c_iflag; /* input mode */ tcflag_t c_oflag; /* output mode */ tcflag_t c_cflag; /* control mode */ tcflag_t c_lflag; /* local mode */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ cc_t c_cc[NCCS]; /* control characters */ };
The Interix SDK extends the POSIX.1 set of flags for c_iflag to include IMAXBEL and VBELTIME. For c_cc , VMIN and VTIME do not have the same values as VEOF and VEOL. For a portable application, however, a developer should take into consideration that VMIN and VTIME can be identical to VEOF and VEOL on a POSIX.1 system.
Table11.8 shows the 12 new functions that replace the terminal I/O ioctl() calls, which include ioctl(fd, TIOCSETP, buf) and ioctl(fd, TIOCGETP, buf) or stty() and gtty() . They were changed because the data type of the final argument for terminal I/O ioctl() calls depends on an action that makes type checking impossible .
Function | Description |
---|---|
tcgetattr() | Fetches attributes (termios structure). |
tcsetattr() | Sets attributes (termios structure). |
cfgetispeed() | Gets input speed. |
cfgetospeed() | Gets output speed. |
cfsetispeed() | Sets input speed. |
cfsetospeed() | Sets output speed. |
tcdrain() | Waits for all output to be transmitted. |
tcflow() | Suspends transmit or receive. |
tcflush() | Flushes pending I/O. |
tcsendbreak() | Sends BREAK character. |
tcgetpgrp () | Gets foreground process group identifier (ID). |
tcsetpgrp() | Sets foreground process group ID. |
To get the window size , use the TIOCGWINSZ command for ioctl() or the winsize structure, which are both supported.
The Interix SDK libraries include Libcurses.a, a port of the ncurses package, and Libtermcap.a, termcap routines. The Interix SDK also supports pseudoterminals. Porting such applications to Interix should be straightforward, but note the following:
The curses routines make use of the terminfo database, stored in /usr/share/terminfo. This location is different from the location used in traditional systems. To link with the terminfo routines, link with the curses library.
Interix supports both the BSD /dev/ptynn and the System V /dev/ptmx methods for opening the master side of a pseudoterminal. The System V method is slightly faster because the search for an available master device is handled in the subsystem. Currently, the Interix subsystem supports 265 ptys named /dev/pty[p “zA “E][0 “9a “f] on the master side. The corresponding subordinate side names are /dev/tty[p “zA “E][0 “9a “f].
When using /dev/ptmx, the subordinate (slave) tty name can be obtained with ptsname() . BSD-based ioctl() calls can be used with the pty master side.
Provided that it is a session leader, a process without a controlling tty acquires a controlling terminal on the first open () call to a tty, unless NOCTTY is specified in the open() call.
Older character-based terminal applications placed the cursor on the physical display screen based on the capabilities of the terminal. These capabilities were typically stored in the /etc/termcap file with around 15,000 lines of terminal capabilities.
The Console APIs can be used to create character-based applications with an addressable cursor. SetConsoleCursorPosition() , WriteConsole() , and ReadConsole() are three functions among the many available for use in the Console API.