Go to the first, previous, next, last section, table of contents.


Ports and File Descriptors

Conventions largely follow those of scsh, section The Scheme shell (scsh).

Guile ports are currently based on C stdio streams. Ports can be buffered or unbuffered. Unbuffered ports can be specified by including 0 in a port mode string. Note that some system call interfaces (e.g., recv!) will accept ports as arguments, but will actually operate directly on the file descriptor underlying the port. Any port buffering is ignored, including the one character buffer used to implement peek-char and unread-char.

File descriptors are generally not useful for Scheme programs; however they can be needed when interfacing with foreign code and the Unix environment.

A file descriptor can be extracted from a port and later converted back to a port. However a file descriptor is just an integer, and the garbage collector doesn't recognise it as a reference to the port. If all other references to the port were dropped, then it's likely that the garbage collector would free the port, with the side-effect of closing the file descriptor prematurely.

To assist the programmer in avoiding this problem, each port has an associated "revealed count" which can be used to keep track of how many times the underlying file descriptor has been stored in other places. The idea is for the programmer to ensure that the revealed count will be greater than zero if the file descriptor is needed elsewhere.

For the simple case where a file descriptor is "imported" once to become a port, it does not matter if the file descriptor is closed when the port is garbage collected. There is no need to maintain a revealed count. Likewise when "exporting" a file descriptor to the external environment, setting the revealed count is not required if the port is kept open while the file descriptor is in use.

To correspond with traditional Unix behaviour, the three file descriptors (0, 1 and 2) are automatically imported when a program starts up and assigned to the initial values of the current input, output and error ports. The revealed count for each is initially set to one, so that dropping references to one of these ports will not result in its garbage collection: it could be retrieved with fdopen or fdes->ports.

primitive: port-revealed port
Returns the revealed count for port.

primitive: set-port-revealed! port count
Sets the revealed count for a port to a given value. The return value is unspecified.

primitive: fileno port
Returns the integer file descriptor underlying port without changing its revealed count.

procedure: port->fdes port
Returns the integer file descriptor underlying port. As a side effect the revealed count of port is incremented.

primitive: fdopen fdes modes
Returns a new port based on the file descriptor fdes with modes given by the string modes. The revealed count of the port is initialized to zero. The modes string is the same as that accepted by section File Ports.

primitive: fdes->ports fdes
Returns a list of existing ports which have fdes as an underlying file descriptor, without changing their revealed counts.

procedure: fdes->inport fdes
Returns an existing input port which has fdes as its underlying file descriptor, if one exists, and increments its revealed count. Otherwise, returns a new input port with a revealed count of 1.

procedure: fdes->outport fdes
Returns an existing output port which has fdes as its underlying file descriptor, if one exists, and increments its revealed count. Otherwise, returns a new output port with a revealed count of 1.

primitive: primitive-move->fdes port fdes
Moves the underlying file descriptor for port to the integer value fdes without changing the revealed count of port. Any other ports already using this descriptor will be automatically shifted to new descriptors and their revealed counts reset to zero. The return value is zero if the file descriptor does not need to be moved or one if it does.

procedure: move->fdes port fd
Moves the underlying file descriptor for port to the integer value fdes and sets its revealed count to one. Any other ports already using this descriptor will be automatically shifted to new descriptors and their revealed counts reset to zero. The return value is unspecified.

procedure: release-port-handle port
Decrements the revealed count for a port.

primitive: force-output [port]
Flush the specified output port, or the current output port if port is omitted. The return value is unspecified.

primitive: flush-all-ports
Flush all open output ports. The return value is unspecified.

primitive: fsync port/fd
Copies any unwritten data for the specified output file descriptor to disk. If port/fd is a port, its buffer is flushed before the underlying file descriptor is fsync'd. The return value is unspecified.

primitive: open path flags [mode]
Open the file named by path for reading and/or writing. flags is an integer specifying how the file should be opened. mode is an integer specifying the permission bits of the file, if it needs to be created, before the umask is applied. The default is 666 (Unix itself has no default).

flags can be constructed by combining variables using logior. Basic flags are:

Variable: O_RDONLY
Open the file read-only.
Variable: O_WRONLY
Open the file write-only.
Variable: O_RDWR
Open the file read/write.
Variable: O_APPEND
Append to the file instead of truncating.
Variable: O_CREAT
Create the file if it does not already exist.

See the Unix documentation of the open system call for additional flags.

primitive: open-fdes path flags [modes]
Similar to open but returns a file descriptor instead of a port.

primitive: close port/fd
Similar to close-port (see section Closing Ports), but also works on file descriptors. A side effect of closing a file descriptor is that any ports using that file descriptor are moved to a different file descriptor and have their revealed counts set to zero.

primitive: pipe
Creates a pipe which can be used for communication. The return value is a pair in which the CAR contains an input port and the CDR an output port. Data written to the output port can be read from the input port. Note that both ports are buffered so it may be necessary to flush the output port before data will actually be sent across the pipe. Alternatively a new unbuffered output port can be created using duplicate-port with an appropriate mode string.

The next group of procedures perform a dup2 system call, if newfd (an integer) is supplied, otherwise a dup. The file descriptor to be duplicated can be supplied as an integer or contained in a port. The type of value returned varies depending on which procedure is used.

All procedures also have the side effect when performing dup2 that any ports using newfd are moved to a different file descriptor and have their revealed counts set to zero.

primitive: dup->fdes port/fd [newfd]
Returns an integer file descriptor.

procedure: dup->inport port/fd [newfd]
Returns a new input port using the new file descriptor.

procedure: dup->outport port/fd [newfd]
Returns a new output port using the new file descriptor.

procedure: dup port/fd [newfd]
Returns a new port if port/fd is a port, with the same mode as the supplied port, otherwise returns an integer file descriptor.

procedure: dup->port port/fd mode [newfd]
Returns a new port using the new file descriptor. mode supplies a mode string for the port (see section File Ports).

procedure: duplicate-port port modes
Returns a new port which is opened on a duplicate of the file descriptor underlying port, with mode string modes as for section File Ports. The two ports will share a file position and file status flags.

Unexpected behaviour can result if both ports are subsequently used and the original and/or duplicate ports are buffered. The mode string can include 0 to obtain an unbuffered duplicate port.

This procedure is equivalent to (dup->port port modes).

primitive: redirect-port old-port new-port
This procedure takes two ports and duplicates the underlying file descriptor from old-port into new-port. The current file descriptor in new-port will be closed. After the redirection the two ports will share a file position and file status flags.

The return value is unspecified.

Unexpected behaviour can result if both ports are subsequently used and the original and/or duplicate ports are buffered.

This procedure does not have any side effects on other ports or revealed counts.

primitive: port-mode port
Returns the port modes associated with the open port port. These will not necessarily be identical to the modes used when the port was opened, since modes such as "append" which are used only during port creation are not retained.

primitive: close-all-ports-except port ...
Close all open file ports used by the interpreter except for those supplied as arguments. This procedure is intended to be used before an exec call to close file descriptors which are not needed in the new process.

primitive: setvbuf port mode [size]
Set the buffering mode for port. mode can be:
_IONBF
non-buffered
_IOLBF
line buffered
_IOFBF
block buffered, using a newly allocated buffer of size bytes. However if size is zero or unspecified, the port will be made non-buffered.

This procedure should not be used after I/O has been performed with the port.

Ports are usually block buffered by default, with a default buffer size. Procedures e.g., section File Ports, which accept a mode string allow 0 to be added to request an unbuffered port.

primitive: freopen filename modes port
Reopen port on the specified filename with mode string modes as for section File Ports.

primitive: fcntl fd/port command [value]
Apply command to the specified file descriptor or the underlying file descriptor of the specified port. value is an optional integer argument.

Values for command are:

F_DUPFD
Duplicate a file descriptor
F_GETFD
Get flags associated with the file descriptor.
F_SETFD
Set flags associated with the file descriptor to value.
F_GETFL
Get flags associated with the open file.
F_SETFL
Set flags associated with the open file to value
F_GETOWN
Get the process ID of a socket's owner, for SIGIO signals.
F_SETOWN
Set the process that owns a socket to value, for SIGIO signals.
FD_CLOEXEC
The value used to indicate the "close on exec" flag with F_GETFL or F_SETFL.

primitive: select reads writes excepts [secs] [usecs]
reads, writes and excepts can be lists or vectors: it doesn't matter which, but the corresponding object returned will be of the same type. Each element is a port or file descriptor on which to wait for readability, writeability or exceptional conditions respectively. secs and usecs optionally specify a timeout: secs can be specified alone, as either an integer or a real number, or both secs and usecs can be specified as integers, in which case usecs is an additional timeout expressed in microseconds.

Buffered input or output data is (currently, but this may change) ignored: select uses the underlying file descriptor of a port (char-ready? will check input buffers, output buffers are problematic).

The return value is a list of subsets of the input lists or vectors for which the requested condition has been met.

It is not quite compatible with scsh's select: scsh checks port buffers, doesn't accept input lists or a microsecond timeout, returns multiple values instead of a list and has an additional select! interface.


Go to the first, previous, next, last section, table of contents.