previous next top contents index framed top this page unframed
Every implementation of the STREAMS package guarantees at least one TTY stream connected to the controlling terminal. This stream is always available in the STREAMS system variable $tty. In some cases, $tty may be a half-duplex TTY, that is, $isHalfDuplex(tty) is TRUE. Half-duplex TTYs have restricted functionality (see Section 11.8).
Some systems support the ability to open an auxiliary serial port with terminal-like characteristics. On such systems, TTY streams to serial lines other than the controlling terminal may be opened using a name of the form ttystr>xxx, where xxx is the (operating-system- and installation-dependent) name of the terminal line.
11.1. $tty
The controlling terminal is opened automatically by the STREAMS package
and is available through the STREAMS system variable $tty.
Input from the initial $tty stream comes from the keyboard and
output usually goes to the screen, unless the primary input and output
of the MAINSAIL process were somehow redirected by some external means.
File I/O done on files opened with the NTTY device MODULE always goes through the current $tty stream. When cmdFile and logFile are opened through NTTY, they also go through the $tty stream.
If programs using $tty open or access the controlling terminal through non-STREAMS means, the mode setting logic for the controlling terminal may be confused and the redirection of $tty subverted. Such access therefore has undefined effects.
On systems that support the stream
MODULEs PTYPRO and PROCESS, these may
be used to start external processes
in which $tty is not the physical
terminal.
The processes that may be run may possibly be restricted to
MAINSAIL and specially written non-MAINSAIL processes on some systems.
11.2. Meaning of $eos on TTY Streams
On input, the $eos error return
means that there is no more input
available.
This condition might be due to the user typing a special
control character (such as CTRL-D under UNIX).
In that case, a subsequent input may get more data. Alternatively,
the $eos return might indicate a permanent condition, such as the
end of a batch job input file.
On output, $eos means that no more data can be written.
When $text is read from a TTY stream
in $line mode, and no special
TTY-specific bits are set, reading occurs in units of lines, line
editing characters are available to the user at the keyboard to
correct mistakes on input, and the characters read are echoed to the
output end of the stream.
When any of the buffering bits other than $line
is used for TTY input,
both line editing and the echoing of input to the output are disabled
until a read is done from the TTY stream
in which $line is specified.
When text is written to a TTY stream in $line mode,
eol characters are modified as necessary to cause the
cursor to move to the beginning of the next line. Typically it is
necessary to supply both a carriage return character and a linefeed
character to the actual physical terminal.
When output is done in a
buffering mode other than $line, e.g.,
$unbuffered, no such manipulation
of eol characters takes place.
It is then the program's responsibility
to ensure that the desired sequence of characters is sent.
That sequence
is available as the $stream field $unbufferedEol.
For example, under UNIX, the
STRING eol contains the single character
linefeed.
If this alone were output to most terminals, the cursor would
not move back to the first column of the screen; i.e.:
would produce:
while either:
or:
would produce:
Aside from the side effects of echoing
and eol manipulation associated
with $line,
the $line and $unbuffered bits work for TTYs as they do for
all other streams.
The $fillBuffer and $packet buffering modes are of
little use for TTY streams because such streams are unreliable when
connected to a physical terminal line.
However, these modes might be
useful over a TTY stream that is connected
to a parent process instead
of a physical terminal.
System-specific interrupt characters and flow control characters
introduce a slight complication into programming a TTY stream.
By default, interrupt characters have a special effect and are not
passed to the program. The flow control characters are not
available to the program, either for reading or writing.
Unless some special bits are set for TTY stream I/O,
the programmer must
be careful not to expect to read octets that correspond to
interrupt or flow control characters
or to write flow control characters
and have them received at the other end of a TTY stream.
Since these
characters are usually nonprinting characters,
normal applications do
not need to worry about this limitation.
However, special applications
such as screen editors and terminal emulators
must take special action.
To vary these characteristics from the default, additional
ctrlBits
bits are provided for the stream input functions. The additional bits
are:
11.3. TTY-Specific I/O Bits
TTY streams have some additional characteristics not present in other
stream types. They are also unable to send or receive certain octet
values (i.e., special control characters) unless some special bits are
specified to the stream I/O PROCEDUREs.
The characteristics of TTY
streams include:
$writeStream($tty,"Hi" & eol & "Hi")
Hi
Hi
$writeStream($tty,"Hi" & eol & "Hi",$line)
$writeStream($tty,"Hi" & $tty.$unbufferedEol & "Hi")
Hi
Hi
These bits are ignored for non-TTY streams or in implementations where they cannot be supported.
For example, to read a character without echo and without waiting for an eol, $cReadStream($tty,$text!$unbuffered) could be used, provided that $tty is not a half-duplex terminal. The program may want to echo the character it read. If it does not do so explicitly, the user does not see any echo.
The system PROCEDURE ttycWrite(char) functions similarly to
$cWriteStream($tty,char,$text!$line). To cause char to be
displayed immediately rather than waiting for an eol (full-duplex
systems only), $cWriteStream($tty,char,$text!$unbuffered)
could be used
instead. However, when $unbuffered is set,
it is the responsibility of the program to make
sure that the sequence of characters
$tty.unbufferedEol is output at the
end of a line.
This character sequence is not necessarily the same as
the STRING constant eol. Figure 11–1. TTY-Specific PROCEDUREs
11.4. TTY-Specific PROCEDUREs
LONG INTEGER
PROCEDURE $getBaudRate
(POINTER($stream) st;
OPTIONAL BITS ctrlBits);
BOOLEAN
PROCEDURE $setBaudRate
(POINTER($stream) st;
LONG INTEGER baud;
OPTIONAL BITS ctrlBits);
LONG INTEGER
PROCEDURE $writeStreamBreak
(POINTER($stream) st;
OPTIONAL BITS ctrlBits;
OPTIONAL LONG INTEGER timeout);
The PROCEDURE $getBaudRate returns the baud rate of the TTY stream st, 0L if the rate is unknown, and negative failure values if st is not a valid stream or some other error occurs.
The PROCEDURE $setBaudRate sets the baud rate of the TTY stream st to baud, returning TRUE if it was successful and FALSE otherwise.
Setting errorOK in ctrlBits for these procedures suppresses a fatal error message; the error text is then put in st.$lastInputError.
The PROCEDURE $writeStreamBreak sends a BREAK on a TTY stream, returning a nonnegative value if the function is implemented and succeeds, or a negative failure value otherwise. Breaks are typically read as one or more null characters (i.e., $nulChar). Setting errorOK in ctrlBits suppresses a fatal error message; the error text is then put in st.$lastOutputError.
$writeStreamBreak is implemented for PTY streams as well as
TTY streams; see Section 11.9.1.
11.5. TTY-Specific Fields of $stream
The TTY-specific fields of $stream
give the character sequences corresponding to specially interpreted
characters (normally these are control characters) that may be typed
by the user to cause special actions.
Figure 11–2. TTY-Specific Fields of $stream
| STRING $unbufferedEol; # How to write eol in $unbuffered # mode. This is typically a two- # character STRING, even though # length(eol) = 1. INTEGER # Characters received in $unbuffered mode when: $returnKey, # A return key is pressed $linefeedKey, # A linefeed key is pressed $eofIndicator, # An end-of-file character is typed # Line editing characters for this TTY: $erase, # Erase the most recent character sent $altErase, # Erase the most recent character sent $wordErase, # Erase the most recent word sent $lineErase, # Erase the entire line $reprint, # Reprint the current line being input $quoteNext, # quote the next character # Flow control characters for this TTY: $startOutput, # An XON (e.g., CTRL-Q) $stopOutput, # An XOFF (e.g., CTRL-S) # Interrupt characters for this TTY: $interrupt, # The interrupt character $discardOutput; # Clear (discard) pending output |
If any of the functions implied by these fields is not supported by a given system, the corresponding characters are -1. The only fields that are guaranteed to be defined are $unbufferedEol, $returnKey, and $erase.
Using these character field definitions, a program that wishes to read characters in a mode other than $line may intelligently interpret the special incoming character sequences according to the host system conventions to achieve each of these functions.
The $startOutput and $stopOutput characters tell a program what characters are reserved for flow control (unless $noFlow mode is in effect).
The complete set of characters reserved for interrupts may not be
determined.
The character $interrupt is the standard interrupt character
(the one that may possibly be trapped by the STREAMS package and that
otherwise causes program termination) if such a character is available
for this system and TTY.
The character $discardOutput is the character
the user may type to discard the pending output to the terminal.
Neither of these characters may be read
from the TTY unless $noInterrupt is set.
11.6. Is My $tty Interactive?
A program may determine whether its $tty has the characteristics
of a true terminal or not. If not, it should not expect interaction
with a real user.
IF $isaTty($tty) THEN # I am interactive or PTYPRO
EL # I am batch or PROCESS
On UNIX, a program for which $isaTty($tty) is FALSE might also be running with its standard input coming from a pipe or file set up by the shell.
This test works if the system supports a means to determine the
difference between an interactive and “batch” terminal.
Otherwise,
$isaTty(st) always returns TRUE.
11.7. Am I a Cooperative Child?
A program may determine whether
its parent expects to talk to it through
the $parent stream by checking
whether $parent is NULLPOINTER, e.g.:
IF $parent THEN # I am a cooperative child
Cooperative children may or may not have an interactive TTY.
11.8. Half-Duplex TTY Streams
On half-duplex TTY streams,
the only allowed buffering bit for input is
$line.
For output, both the $unbuffered (default) and $line bits are
supported, but $unbuffered text output may not behave
differently from $line output. The programmer must use adaptive
programming tests in a portable program to find alternative methods
if the program would normally perform $unbuffered, $packet, or
$fillBuffer I/O and it is to be run on a half-duplex system, e.g.:
IF NOT $isHalfDuplex(st) THEN
# Full-Duplex Case
$readStream(st,...,$unbuffered);
EB # Half-Duplex Case: Cannot turn off echo
positionCursorToTopOfScreen(st); # user-supplied function
$readStream(st,...,$line);
repositionCursor(st) END; # user-supplied function
PTY is an acronym for “pseudo-TTY”. The interaction of the parent program with the PTY is much like the interaction of a user with a terminal keyboard and screen. It is the “other end” of the child process's $tty.
Interaction Between PTY and $tty
| In the Parent Coroutine | In the Child Coroutine | |
|---|---|---|
| $writeStream(pty,...); | sends its output to | $readStream($tty,...); |
| $readStream(pty,...); | gets its input from | $writeStream($tty,...); |
The coroutine that opens the PTY stream is responsible for simulating a person sitting at a terminal. It must write characters to the PTY to simulate typing at the keyboard and read characters from the PTY that would normally appear on the screen (including echo of the characters it wrote).
On systems that support process creation and control, PTY streams may be used to create and talk to an independent program running in a separate (child) process external to the creating (parent) process. On systems that support transparent pseudoterminals, any program may be run through the PTY without restriction, not just MAINSAIL programs. On such systems, the standard system “shell” (command interpreter) may be run.
To the child process that is running through the PTY, everything appears as if it were connected to a true interactive terminal. The child process may turn echo on and off, read characters in $line or $unbuffered mode, interpret interrupt characters specially or not, and interpret flow control specially or not as it chooses. The parent process itself does not use these modes when reading from or writing to the PTY.
PTY streams are used to communicate with child processes when the details of the interaction are unknown to the program that opens the PTY. Typically, the program that opens a PTY serves merely as an intermediary that accepts keystrokes from a user (passing them on to the child process) and displays the resultant input from the PTY on the screen. For example, a window manager can use PTYs to implement a window that talks to a separate job.
The only buffering mode that makes sense in general for both input and output on PTYs is $unbuffered. The output is made available to the child process immediately. The child process may or may not choose to buffer when it does its input, but that is entirely separate. PTY input should be done in $unbuffered mode since it is based on the available characters written by the child. Because the exact interaction expected by the child is generally unknown, it is not generally useful to perform input from the PTY in $line mode (doing so could cause the parent to fail to display, e.g., a prompt not terminated by eol, until after the text responding to the prompt had been set, an undesirable interaction).
The use of PTY streams to control child processes is described in Section 7.4.
On both input and output, $eos means that the process controlled by the PTY is no longer alive.
There are no PTY-specific I/O bits. The only buffering mode supported is $unbuffered.
Figure 11–3. PTY-Specific PROCEDUREs
11.9.1. PTY-Specific PROCEDUREs
LONG INTEGER
PROCEDURE $writeStreamBreak
(POINTER($stream) pty;
OPTIONAL BITS ctrlBits;
OPTIONAL LONG INTEGER timeout);
LONG INTEGER
PROCEDURE $writeStreamInterrupt
(POINTER($stream) pty;
OPTIONAL BITS ctrlBits;
OPTIONAL LONG INTEGER timeout);
The PROCEDURE $writeStreamBreak sends a BREAK on a PTY stream, returning a nonnegative value if the function is implemented, or a negative failure value otherwise. Breaks are typically read on the other end as one or more null characters (i.e., $nulChar). Setting errorOK in ctrlBits suppresses a fatal error message; the error text is then put in pty.$lastOutputError.
The PROCEDURE $writeStreamInterrupt signals an interrupt to the child process. If the child has not enabled itself to catch the interrupt or if interrupt catching is not implemented, the child will probably be killed. The bit errorOK suppresses error messages. An OPTIONAL timeout may be given to return early if the PROCEDURE blocks.
In addition, a PTY stream pty
has an associated character pty.$interrupt. If
this character is nonnegative,
it causes an interrupt if it is written to
the PTY using $cWriteStream
or as part of a $writeStream, e.g.,
$cWriteStream(pty,pty.$interrupt).
11.9.2. PTY-Specific Fields of $stream
The PTY-specific fields give the character sequences corresponding to
specially interpreted characters
(normally these are control characters)
that may be typed by the user to cause special actions.
These are the
same as the TTY-specific fields (see Figure 11–2).
If any of the fields is not supported by a given system, the corresponding character is -1. The only fields that are guaranteed to be defined are $unbufferedEol, $returnKey, and $erase.
MAINSAIL STREAMS User's Guide, Chapter 11