streams(7) streams(7)NAME streams - an interface for character I/O DESCRIPTION Streams is a mechanism that is used in the UNIX kernel for some device drivers. These drivers are usually for communi- cations or tty type applications. To most programs, this interface is, with a few exceptions, the same as that of traditional UNIX character devices. When used with a streams line-discipline, this interface is the same as that of normal UNIX terminals. A/UX supports the version of streams implemented under UNIX V.2.1, which is a functional subset of that provided by later UNIX implementations. It is upwardly compatible with such systems. The main difference between streams and other character dev- ice drivers is that the streams interface is message based. Commands and data exchanged between devices, processes and line disciplines (streams modules) are sent in messages. A number of special ioctl functions have been defined to send and receive these messages. A stream is built by opening a stream style device (the ability of a device to ``stream'' is defined by the writer of the device's device-driver, either a device streams or it doesn't). When the device is open it consists of the device and the ``stream head,'' the interface to the process that opened the device. The device and the stream head can communicate by means of messages across the full-duplex stream. Processes can com- municate with the stream head by means of system calls such as read(2), write(2) and ioctl(2). Using the I_PUSH, a stream module can be pushed (in a LIFO or stacked manner) onto the stream. More than one stream module can be pushed onto such a stream at a time. The module closest to the stream head may be removed using the I_POP ioctl call. Closing a stream causes the modules to be popped from the stream, the device to be closed, and the stream dismantled. Modules exist in the kernel and are referenced by name. There are two standard streams modules: line A tty style line discipline. When pushed, it im- plements all the functionality described by ter- mio(7). Most terminal-style communications lines use this module. April, 1990 1
streams(7) streams(7)shlr The shell layering module. shlr responds to shell layering ioctls to implement shell layering on stream based ttys. Normally shl(1) is the only utility that uses this module. The streams system implements a number of ioctls, all of the ioctls described in termio(7) are provided for compatabili- ty. Some devices and/or modules may not respond to these calls. In particular many of the line discipline related ioctls will either fail or be ignored unless the module line has been pushed onto the stream. In addition the following streams related ioctls are supported, they are defined in the include file <sys/stropts.h>. I_STR ioctl(fd, I_STR, &strioctl) struct strioctl strioctl; This ioctl builds an ioctl packet and sends it down the stream. It may be interpreted by any module on the stream or by the device at the end. The packet is returned with data and an indication of success or failure. The data structure strioctl is used to describe the packet to be sent. It has 4 fields: ic_cmd The command to be sent ic_timout How long to wait for the ioctl to succeed before failing (in seconds), values 0 and -1 have special meanings, 0 means wait for the system default time, -1 means wait forever. ic_dp Points to the address of the data to be sent down the stream, or the address at which data returned from the stream is to be stored. ic_len Is the length of the data to be sent, in bytes, or the size of the buffer into which returned data is to be stored. Errors: EFAULT if ic_dp references an invalid address. Any other device/module specific error message. I_NREAD n=ioctl(fd, I_NREAD, &first); I_NREAD returns the number of messages in the queue at the streams head as its result. It also 2 April, 1990
streams(7) streams(7)returns the number of bytes in the first message in the queue to the address referenced by its ar- gument. Errors: EFAULT if the argument references an invalid ad- dress. I_PUSH ioctl(fd, I_PUSH, module) char *module; This ioctl pushes the streams module named by the null-terminated string module onto an open stream. Errors: EFAULT if the module name references an invalid address. EINVAL if the module name does not describe an existing streams module in the A/UX kernel. Any other error the streams module might return if it decides not to allow the push. I_POP ioctl(fd, I_POP, 0) The ioctl removes the streams module closest to the process on the stream. Errors: EINVAL if no such module exists I_LOOK ioctl(fd, I_LOOK, buff) char buff[FMNAMESZ+1]; This returns the name of the streams module closest to the process on a stream. Errors: EFAULT if the buffer for the name is located at an invalid address. EINVAL if there are no modules pushed onto the stream. I_FLUSH ioctl(fd, I_FLUSH, flushtype) This generates a message that is sent down the queue to flush messages waiting at modules down the stream. The parameter can be one of three al- lowed values: FLUSHR flush messages coming down the stream towards the process April, 1990 3
streams(7) streams(7)FLUSHW flush messages moving up the stream away from the process FLUSHRW flush all messages in the stream Errors: EINVAL the parameter is not one of the above values EAGAIN insufficient resources are avail- able to send the message up the queue and it should be retried at a later time. I_SRDOPT ioctl(fd, I_SRDOPT, srdtype) This ioctl changes the manner in which the stream head treats incoming messages as they are passed to a process as part of a read(2) system call. The parameter can take one of three possible values: RNORM in stream mode - messages are read from the stream and message boundaries are ignored (except for 0 length messages which are always returned as separate messages and are normally treated as end of file markers) RMSGN a read terminates at either the end of the message or when the read buffer is full. Any message data remaining is available from future reads. RMSGD a read terminates when either the end of the message is found or the read buffer is full. Any unread data is discarded. When a stream is first opened, it has the default operating mode of RNORM. It is also possible for upstream modules to change this. Errors: EINVAL the parameter is not one of the above values I_GRDOPT ioctl(fd, I_GRDOPT, &opt) int opt; This call returns the current read option (as specified above under I_SRDOPT). 4 April, 1990
streams(7) streams(7)Errors: EFAULT if the argument is a valid address I_FIND find = ioctl(fd, I_FIND, buff) char buff[FMNAMESZ+1]; This call returns 1 if a module of the name given in the null-terminated string passed in the argu- ment is present in the stream, or 0 if the module does not exist. Errors: EINVAL if the name is not the name of a module in the kernel. EFAULT if the address of the name passed as the argument is not valid. I_MNAME ioctl(fd, I_MNAME, &par) union { int depth; char buff[FMNAMESZ+1]; } par; This ioctl returns the name of the module or driver at the depth on the stream specified by the parameter. The stream head is at depth 0. The last module found on the stream will be the driver. Note: this ioctl is not necessarily provided on all systems that provide a stream interface. It should not be used if program portability is a factor. Errors: EFAULT if the address of the parameter is invalid EINVAL if the depth is less than 0 or references a module past the driver at the end of the stream Terminal Lines When using a stream based terminal, it is usually necessary to push a line discipline module onto the stream before use. In almost all cases this is done by /etc/getty or /etc/init when you log onto your system. When you are opening an unused terminal line it may then be required. Pushing more than one line discipline onto a stream should be avoided as the results are undefined and will not be useful. Two methods are provided to make pushing line disciplines easier. They both can be used on non stream based character drivers without any undue effect and they will avoid the multiple pushing of line disciplines if one is already pushed. April, 1990 5
streams(7) streams(7)line_push(3) is a library routine that is passed the file descriptor of and open device (from open(2)). It will push a line discipline onto the device if it is a streaming dev- ice and there is not one pushed already. /etc/line_sane(1M) is a utility that can be run from shell scripts (such as those started from /etc/inittab(4)). It takes one parameter, an integer representing an open file descriptor on which the line discipline is to be pushed. It behaves similarily to line_push(3) above. Further Functionality The following extensions are provided to the streams system. They are not necessarily provided with other streams imple- mentations and should not be used if portability is impor- tant. select(2) allows a process to wait for input from more than one open device, socket or stream FIONBIO allows a process to make non blocking reads to a stream (see termio(7)) FIONASYNC sends a SIGIO signal to a process when input is available from the queue (see termio(7)) FIONREAD returns the number of characters available to be read from the stream head (this is dif- ferent from I_NREAD above) (see termio(7)) SEE ALSO line_sane(1M), close(2), ioctl(2), open(2), read(2), select(2), write(2), line_push(3). Building A/UX Device Drivers. 6 April, 1990