COHERENT uses two methods for controlling terminals: sgtty and termio. To use sgtty, simply include the statement #include <sgtty.h> in your sources. To use termio, include the statement #include <termio.h>.
The rest of this article discusses the termio method of controlling terminals.
When a terminal file is opened, it normally causes the process to wait until a connection is established. In practice, users' programs seldom open these files: they are opened by the program getty and become a user's standard input, output, and error files. The very first terminal file opened by the process group leader of a terminal file not already associated with a process group becomes the control terminal for that process group. The control terminal plays a special role in handling quit and interrupt signals, as discussed below. The control terminal is inherited by a child process during a call to fork(). A process can break this association by changing its process group using setpgrp().
A terminal associated with one of these files ordinarily operates in full-duplex mode. Characters can be typed at any time, even while output is occurring, and are lost only when the system's input buffers become completely full, which is rare, or when the user has accumulated the maximum allowed number of input characters that have not yet been read by some program. Currently, this limit is 256 characters. When the input limit is reached, the system throws away all the saved characters without notice.
Normally, terminal input is processed in units of lines. A line is delimited by a newline character (ASCII LF), an end- of-file character (ASCII EOT), or an end-of-line character. This means that a program attempting to read will be suspended until an entire line has been typed. Also, no matter how many characters are requested in the read call, at most one line is returned. It is not, however, necessary to read a whole line at once; any number of characters may be requested in a read, even one, without losing information.
During input, the system normally processes erase and kill characters. By default, the backspace character erases the last character typed, except that it will not erase beyond the beginning of the line. By default, the &&lltt;;ccttrrll--UU&&ggtt;; kills (deletes) the entire input line, and optionally outputs a newline character. Both these characters operate on a keystroke-by-keystroke basis, independently of any backspacing or tabbing which may have been done. Both the erase and kill characters may be entered literally by preceding them with the escape character (\). You can change the erase and kill characters.
Certain characters have special functions on input. These functions and their default character values are summarized as follows:
When the carrier signal from the data-set drops, the system sends a hangup signal to all processes that have this terminal as their control terminal. Unless other arrangements have been made, this signal causes the process to terminate. If the hangup signal is ignored, any subsequent read returns EOF. Thus, programs that read a terminal and test for end-of-file can terminate appropriately when hung up on.
When one or more characters are written, they are transmitted to the terminal as soon as previously written characters have finished typing. Input characters are echoed by putting them into the output queue as they arrive. If a process produces characters more rapidly than they can be printed, it is suspended when its output queue exceeds a preset limit. When the queue has drained down to that threshold, the program resumes.
Several calls to ioctl() apply to terminal files. The primary calls use the following structure, defined in <tteerrmmiioo..hh>:
#define NCC 8
struct termio {
unsigned short c_iflag; /* input modes */
unsigned short c_oflag; /* output modes */
unsigned short c_cflag; /* control modes */
unsigned short c_lflag; /* local modes */
char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control chars */
};
The special control characters are defined by the array c_cc. The relative positions and initial values for each function are as follows:
0 INTR ^C
1 QUIT ^\
2 ERASE \b
3 KILL ^U
4 EOF ^D
5 EOL \n
6 reserved
7 reserved
The field c_iflag describes the basic terminal input control:
BBRRKKIINNTT Signal interrupt on break IIGGNNPPAARR Ignore characters with parity errors IINNPPCCKK Enable input parity check IISSTTRRIIPP Strip character IICCRRNNLL Map CR to NL on input IIXXOONN Enable start/stop output control IIXXOOFFFF Enable start/stop input control
If INPCK is set, input parity checking is enabled. If it is not set, then checking is disabled. This allows output parity generation without input parity errors.
If ISTRIP is set, valid input characters are stripped to seven bits before being processed; otherwise, all eight bits are processed.
If IXON is set, START/STOP output control is enabled. A received STOP character suspends output and a received START character restarts output. All start/stop characters are ignored and not read.
If IXOFF is set, the system transmits START/STOP characters when the input queue is nearly empty or nearly full.
The initial input control value is all bits clear.
The field c_oflag field specifies the system treatment of output: OOPPOOSSTT Postprocess output. OOLLCCUUCC Map lower case to upper on output. OONNLLCCRR Map NL to CR-NL on output.
If OPOST is set, output characters are post-processed as indicated by the remaining flags; otherwise, characters are transmitted without change.
If OLCUC is set, a lower-case alphabetic character is transmitted as the corresponding upper-case character. This function is often used with IUCLC.
If ONLCR is set, the NL character is transmitted as the CR-NL character pair.
The initial output control value is all bits clear.
The field c_cflag describes the hardware control of the terminal, as follows: CCBBAAUUDD Baud rate BB00 Hang up BB5500 50 baud BB7755 75 baud BB111100 110 baud BB113344 134.5 baud BB115500 150 baud BB220000 200 baud BB330000 300 baud BB660000 600 baud BB11220000 1200 baud BB11880000 1800 baud BB22440000 2400 baud BB44880000 4800 baud BB99660000 9600 baud BB1199220000 19200 baud BB3388440000 38400 baud CCRREEAADD Enable receiver PPAARREENNBB Parity enable PPAARROODDDD Odd parity, else even HHUUPPCCLL Hang up on last close CCLLOOCCAALL Local line, else dial-up
The CBAUD bits specify the baud rate. The zero-baud rate, B0, hangs up the connection. If B0 is specified, the data-terminal-ready signal is not asserted. Normally, this disconnects the line. For any particular hardware, the system ignores impossible changes to the speed.
If PARENB is set, parity generation and detection is enabled and a parity bit is added to each character. If parity is enabled, the PARODD flag specifies odd parity if set; otherwise, even parity is used.
If CREAD is set, the receiver is enabled. Otherwise, no characters will be received.
If HUPCL is set, COHERENT disconnects the line when the last process with the line open closes the line or terminates; that is, the data-terminal-ready signal is not asserted.
If CLOCAL is set, the system assumes that the line to be a local, direct connection with no modem control. Otherwise, it assumes modem control.
The line discipline uses the field c_lflag to control terminal functions. The basic line discipline (zero) provides the following:
IISSIIGG Enable signals
IICCAANNOONN Canonical input (erase and kill processing)
XXCCAASSEE Canonical upper/lower presentation
EECCHHOO Enable echo
EECCHHOOEE Echo erase character as BS-SP-BS
EECCHHOOKK Echo NL after kill character
EECCHHOONNLL Echo NL
The following gives the meaning of each flag in detail:
_F_o_r_: _U_s_e_:
` \'
| \!
~ \^
{ \(
} \)
\ \\
The primary calls to ioctl() have the following form:
ioctl( fildes, command, arg ) struct termio *arg;
The following commands use this form:
ioctl( fildes, command, arg ) int arg;
The following command uses this form:
read(0, &c, sizeof(char));
that returns zero (failure) rather than waiting for input if there is no current typed character.
To do so, you must do the following:
termiob.c_cc[VMIN] = 0;
termiob.c_cc[VTIME] = 0;
#include <termio.h> #include <stdlib.h>
void
ttyinit()
{
struct termio termiob;
ioctl(0, TCGETA, &termiob); /* get tty characteristics */
termiob.c_cc[VMIN] = 0;
termiob.c_cc[VTIME] = 0; /* non-blocking read */
ioctl(0, TCSETA, &termiob); /* set new mode */
}
int
ttycheck()
{
static int done = 0;
char c;
if (done)
return 0;
if (read(0, &c, 1) != 0) {
if (c == 'a')
return 0;
else if (c != ' ') {
++done;
return 0;
}
/* After <space>, pause until another character is typed */
while (read(0, &c, 1) == 0)
;
}
return 1;
}
main()
{
ttyinit();
while (1) {
printf("Still checking ...\n");
if (!ttycheck())
exit(EXIT_SUCCESS);
}
}
For another example of how to manipulate the termio structure, see the entry for ioctl().