elk/doc/unix/unix.ms

1662 lines
47 KiB
Plaintext

.so ../util/tmac.scheme
.Ul
.TL
Reference Manual for the
.sp .5
Elk UNIX Extension
.AU
Oliver Laumann
.
.Ch "Introduction"
.
.PP
This reference manual describes the primitive procedures and record types
defined by the UNIX extension to Elk.
.PP
The UNIX extension provides easy access to most widely available
UNIX system calls and C library functions from within Scheme programs.
The extension supports a wide range of different UNIX platforms without
restricting its functionality to the lowest common denominator or the
.Ix POSIX
POSIX 1003.1 functions.
To simplify writing portable Scheme programs, the extension
attempts to hide differences between the types of supported UNIX flavors.
For example, programmers do not have to deal with the idiosyncrasies
of the \f2wait()\fP, \f2waitpid()\fP, \f2wait3()\fP, and \f2wait4()\fP
system calls or the \f2mktemp()\fP, \f2tmpnam()\fP, and \f2tempnam()\fP
functions.
.PP
The UNIX extension defines procedures for low-level,
file-descriptor-based I/O; creation of pipes; file/record locking; file
and directory system calls; process creation and control; signal
handling; error handling; and obtaining information about date, time,
users, limits, process resources, etc.
Terminal control is not yet supported by the current version.
.PP
The reference manual assumes that you are familiar with the most common
UNIX system calls and C library functions; this document does not
attempt to duplicate the contents of the standard UNIX documentation.
Detailed descriptions are provided for functions that differ from
the standard UNIX semantics.
.
.Ch "Using the UNIX Extension"
.
.PP
The UNIX extension is loaded by evaluating
.Ss
(require 'unix)
.Se
in the interactive toplevel or in a Scheme program.
.PP
This causes the files \f2unix.scm\fP and \f2unix.o\fP to be loaded
into the interpreter (\f2unix.o\fP has to be linked with the
interpreter on platforms that do not support dynamic loading of
object files).
In addition, the
.Ix "record extension"
\f2record\fP extension is automatically loaded if it is not yet present.
The record extension is documented in a separate reference manual.
.PP
Loading the UNIX extension causes the
.Ix features
features \f2unix\fP and \f2unix.o\fP to be provided.
Optionally, one or more of the following features (described below) may
be provided by the extension to indicate that certain UNIX features
are available:
.Ss
unix:wait-options
unix:wait-process
unix:record-locks
unix:file-locking
unix:symlinks
unix:reliable-signals
.Se
.Ix unix:wait-options
.Ix unix:wait-process
.Ix unix:record-locks
.Ix unix:file-locking
.Ix unix:symlinks
.Ix unix:reliable-signals
.
.Ch "Record Types"
.
.PP
Several procedures return their results as Scheme
.Ix records
records.
All record types defined by the UNIX extension are stored in variables
with names of the form \f2<something>-record\fP (such as
\f2system-record\fP or \f2passwd-record\fP).
In addition, a type predicate, a record constructor, and accessor functions
.Ix "type predicate"
.Ix "record constructor"
.Ix "accessor functions"
for all record fields are defined for each record type.
For example, a \f2system\fP record type with the fields \f2hostname\fP,
\f2sysname\fP, and \f2osname\fP is defined, resulting in variable
\f2system-record\fP holding the record type descriptor, and the functions
.Ss
(system-record? obj)
(make-system-record)
.sp .5
(system-hostname system-record)
(system-sysname system-record)
(system-osname system-record)
.Se
Use \f2define-record-modifiers\fP if you need the
.Ix "modifier functions"
modifier functions for any of the records as well (see the record
extension reference manual for details).
.LP
The following
.Ix "record types"
record types are defined by the UNIX extension:
.sp .5
.KS
.TS
allbox, tab(~);
c c
lf5 lf5.
Record Type~Fields
_
stat~type mode ino dev nlink uid gid size atime mtime ctime
time~T{
seconds minutes hours day-of-month month year weekday
.br
day-of-year dst
T}
nanotime~nanoseconds minuteswest dst
system~hostname sysname osname
passwd~name password uid gid gecos homedir shell
group~name password gid members
resources~user-time system-time (...)
lock~exclusive? whence start length
wait~pid status code core-dump? resources
.TE
.KE
.Ix stat-record
.Ix time-record
.Ix nanotime-record
.Ix system-record
.Ix passwd-record
.Ix group-record
.Ix resources-record
.Ix lock-record
.Ix wait-record
.
.Ch "Error Handling"
.
.PP
The default error behavior of the primitive procedures defined by
the UNIX extension is to invoke the standard Scheme
.Ix "error handler"
error handler if a UNIX system call or library function fails.
As an alternative, if a specific error action is to be performed
by the application, a primitive procedure can be invoked under
control of the
.Ix unix-errval
\f2unix-errval\fP form.
In this case, a unique
.Ix "error object"
\f2error object\fP is returned if a UNIX function signals an error.
The standard UNIX system error message and the UNIX error number
are made available to the application in any case.
Details of the error handling facilities are described in the
section ``Error Functions'' below.
.
.Ch "Conventions"
.
.PP
In the following sections, the names of procedure arguments can
dictate that the arguments are of specific types.
If an argument name is also the name of a Scheme data
type, the argument must be an object of that type.
For example, a procedure with an argument named \f2string\fP must
be invoked with a string.
File descriptor arguments (named \f2fdescr\fP, or \f2fdescr\*1\fP,
\f2fdescr\*2\fP, etc.) and arguments named \f2length\fP are always
non-negative integers;
filename arguments (\f2filename\fP) are strings or symbols;
and arguments with the suffix ``?'' are booleans.
.
.Ch "Low-Level I/O, File Descriptors"
.
.Pr unix-close fdescr
.LP
.Ix close
The UNIX \f2close()\fP system call.
\f2unix-close\fP returns the non-printing object.
.
.[[
.Pr unix-dup fdescr
.Pr unix-dup fdescr\*1 fdescr\*2
.]]
.LP
.Ix dup
.Ix dup2
\f2unix-dup\fP invokes the \f2dup()\fP (first form) or \f2dup2()\fP
(second form) system call.
The result is a new file descriptor (an integer).
.
.[[
.Pr unix-open filename flags
.Pr unix-open filename flags mode
.]]
.LP
.Ix open
The UNIX \f2open()\fP system call.
\f2flags\fP is a list of one or more symbols specifying the bitmask
argument of the \f2open()\fP system call.
.LP
At least the flag symbols \f2read\fP, \f2write\fP, \f2append\fP,
\f2create\fP, \f2truncate\fP, and \f2exclusive\fP are supported;
additional symbols (such as \f2ndelay\fP) may be permitted on
certain platforms.
The procedure \f2unix-list-open-modes\fP can be used to obtain the list
of flag symbols that are supported (see below).
If \f2create\fP is present in the \f2flags\fP argument, the \f2mode\fP
argument (an integer) must be supplied.
At least one of the symbols \f2read\fP or \f2write\fP must be present
in \f2flags\fP.
.LP
\f2unix-open\fP returns a new file descriptor (an integer).
.LP
Example:
.Ss
(let ((f1 (unix-open "/etc/passwd" '(read))
(f2 (unix-open "temp" '(read write create truncate) #o666))))
...)
.Se
.
.Pr unix-list-open-modes
.LP
This procedure returns the list of \f2flag\fP symbols for the
\f2unix-open\fP procedure that are supported on the local platform.
.
.Pr unix-lseek fdescr offset whence
.LP
.Ix lseek
The UNIX \f2lseek()\fP system call.
\f2offset\fP is an integer; \f2whence\fP is one of
the symbols \f2set\fP, \f2current\fP, and \f2end\fP.
\f2unix-lseek\fP returns the new file position as an integer.
.
.Pr unix-pipe
.LP
.Ix pipe
The \f2pipe()\fP system call.
\f2unix-pipe\fP returns two file descriptors as a pair of integers.
.
.[[
.Pr unix-read-string-fill! fdescr string
.Pr unix-read-string-fill! fdescr string length
.]]
.LP
.Ix read
The \f2read()\fP system call.
\f2unix-read-string-fill\fP invokes \f2read()\fP
with the Scheme string as input buffer and the length of the string
argument (first form) or the length supplied as a third argument
(second form).
If \f2length\fP is specified, it must be an integer between 0 and
the length of \f2string\fP.
.LP
\f2unix-read-string-fill!\fP destructively overwrites the contents of the
\f2string\fP argument.
It returns the number of characters actually read (0 on EOF).
.
.[[
.Pr unix-write fdescr string
.Pr unix-write fdescr string length
.]]
.LP
.Ix write
The \f2write()\fP system call.
For a description of the arguments see \f2unix-read-string-fill!\fP above.
\f2unix-write\fP returns the number of characters actually written.
.
.[[
.Pr unix-close-on-exec fdescr
.Pr unix-close-on-exec fdescr on?
.]]
.LP
\f2unix-close-on-exec\fP returns the value of the
.Ix close-on-exec
\f2close-on-exec\fP flag for the given file descriptor as a boolean.
If invoked with a second argument, the procedure sets the
\f2close-on-exec\fP flag to the specified value and returns the
previous value.
.
.[[
.Pr unix-filedescriptor-flags fdescr
.Pr unix-filedescriptor-flags fdescr flags
.]]
.LP
\f2unix-file-descriptor-flags\fP obtains the flags currently active
for the given file descriptor (by means of the
.Ix fcntl
\f2fcntl()\fP system call) and returns them as a list of symbols.
If invoked with a second arguments (a list of symbols), the procedure
sets the flags to that argument and returns the previous value.
.LP
At least the flag symbol \f2append\fP is supported;
additional symbols (such as \f2ndelay\fP or \f2sync\fP) may be permitted on
certain platforms.
The procedure \f2unix-list-filedescriptor-flags\fP can be used to obtain
the list of file descriptor flags that are supported (see below).
.LP
Example:
.Ss
;;; Enable non-blocking I/O for file descriptor (assumes POSIX)
.sp .4
(define (set-non-blocking fd)
(let ((flags (unix-filedescriptor-flags fd)))
(unix-filedescriptor-flags fd (cons 'nonblock flags))))
.Se
.
.Pr unix-list-filedescriptor-flags
.LP
This procedure returns the list of file descriptor \f2flag\fP symbols
that can be returned and set by \f2unix-filedescriptor-flags\fP
on the local platform.
.
.Pr unix-num-filedescriptors
.LP
\f2unix-num-filedescriptors\fP returns the maximum number of file
descriptors per process in the local system.
Depending on the UNIX flavor, the procedure invokes
.Ix getdtablesize
.Ix sysconf
\f2getdtablesize()\fP or \f2sysconf()\fP or uses a static (compile-time)
limit.
.
.Pr unix-isatty? fdescr
.LP
Returns #t if the specified file descriptor points to a terminal
device, #f otherwise (the UNIX
.Ix isatty
\f2isatty()\fP library function).
.
.Pr unix-ttyname fdescr
.LP
.Ix ttyname
The UNIX \f2ttyname()\fP function.
Returns the name of a terminal device as a string, or #f if the
file descriptor is not associated with a terminal.
.
.Pr unix-port-filedescriptor port
.LP
This procedure returns the file descriptor associated with the
.Ix "file pointer"
file pointer conveyed in the specified Scheme port.
An error is signaled if the port has already been closed or if it
is a string port.
\f2unix-port-filedescriptor\fP invokes the UNIX
.Ix fileno
\f2fileno()\fP library function.
.LP
Manipulating a file descriptor obtained by \f2unix-port-filedescriptor\fP
can cause unexpected interactions with the standard Scheme I/O functions
and with the stdio buffering mechanism.
In particular, it is not a good idea to close the file descriptor
associated with the Scheme system's current input port or current
output port.
.LP
Example:
.Ss
(let ((stdout-fileno
(unix-port-filedescriptor (current-output-port))))
(if (unix-isatty? stdout-fileno)
(begin
(display (unix-ttyname stdout-fileno))
(newline))))
.Se
.
.Pr unix-filedescriptor\(mi>port fdescr type
.LP
Creates a Scheme port with a file pointer containing the specified
file descriptor.
\f2unix-filedescriptor\(mi>port\fP is based on the
.Ix fdopen
\f2fdopen()\fP stdio function.
\f2type\fP is a string and is used as the second argument for
\f2fdopen()\fP.
.LP
The type of the newly created Scheme port is determined by the
\f2type\fP argument.
If \f2type\fP begins with the character #\\r, an input port is created;
#\\w and #\\a indicate an output port.
If the second character of \f2type\fP is #\\+ (\f2update\fP), an
input-output (bidirectional) port is created.
.LP
No filename is associated with a Scheme port created by a call
to \f2unix-filedescriptor\(mi>port\fP.
Instead, the string \f2unix-filedescriptor[%d]\fP (where \f2%d\fP is
replaced by the numerical value of the file descriptor) will be
returned by calls to \f2port-file-name\fP and displayed when printing
the port.
.LP
Note that the file descriptor is closed by the
.Ix "garbage collector"
garbage collector when the Scheme port becomes inaccessible.
.
.Ch "Files and Directories"
.
.Pr unix-stat file
.LP
.Ix stat
.Ix fstat
The UNIX \f2stat()\fP/\f2fstat()\fP system call.
\f2file\fP is either a filename or a file descriptor.
.LP
\f2unix-stat\fP returns a
.Ix stat-record
\f2stat-record\fP with the following fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
_
type~symbol~file type
mode~integer~file access mode
ino~integer~inode number
dev~integer~device number
nlink~integer~number of links to file
uid~integer~file owner's user-ID
gid~integer~file owner's group-ID
size~integer~file size
atime~integer~last access time
mtime~integer~last modified time
ctime~integer~last inode change time
.TE
.KE
.LP
The file type is one of the symbols \f2directory\fP,
\f2character-special\fP, \f2block-special\fP, \f2regular\fP,
\f2symlink\fP, \f2socket\fP, \f2fifo\fP, or \f2unknown\fP.
.
.Pr unix-access? filename mode
.LP
\f2unix-access?\fP is based on the
.Ix access
\f2access()\fP system call.
\f2mode\fP is a list of zero or more of the symbols \f2read\fP,
\f2write\fP, and \f2execute\fP.
The empty list can be used to test for existence of the file.
The procedure returns #t if the specified access is granted, #f otherwise.
.
.Pr unix-chdir filename
.LP
.Ix chdir
The UNIX \f2chdir()\fP system call.
\f2unix-chdir\fP returns the non-printing object.
.
.Pr unix-chmod filename mode
.LP
.Ix chmod
The UNIX \f2chmod()\fP system call.
\f2mode\fP is an integer.
\f2unix-chmod\fP returns the non-printing object.
.
.Pr unix-chown filename uid gid
.LP
.Ix chown
The UNIX \f2chown()\fP system call.
\f2uid\fP and \f2gid\fP are integers.
\f2unix-chown\fP returns the non-printing object.
.
.Pr unix-unlink filename
.LP
.Ix unlink
The UNIX \f2unlink()\fP system call.
\f2unix-unlink\fP returns the non-printing object.
.
.Pr unix-link filename\*1 filename\*2
.LP
.Ix link
The UNIX \f2link()\fP system call.
\f2unix-link\fP returns the non-printing object.
.
.Pr unix-rename filename\*1 filename\*2
.LP
.Ix rename
The UNIX \f2rename()\fP system call.
\f2unix-rename\fP returns the non-printing object.
.LP
On platforms where the \f2rename()\fP function is not available,
the operation is performed by the equivalent sequence of
.Ix link
.Ix unlink
\f2link()\fP and \f2unlink()\fP calls with interrupts disabled
(certain restrictions apply in this case, e.\|g.\& directories cannot
be renamed).
.
.Pr unix-mkdir filename mode
.LP
.Ix mkdir
The UNIX \f2mkdir()\fP system call.
\f2mode\fP is an integer.
\f2unix-mkdir\fP returns the non-printing object.
.
.Pr unix-rmdir filename
.LP
.Ix rmdir
The UNIX \f2rmdir()\fP system call.
\f2unix-rmdir\fP returns the non-printing object.
.
.[[
.Pr unix-utime filename
.Pr unix-utime filename atime mtime
.]]
.LP
.Ix utime
The UNIX \f2utime()\fP function.
\f2unix-utime\fP sets the last access and last modification time of
the given file to the current time (first form) or to the specified
times (second form).
\f2atime\fP and \f2mtime\fP are integers.
\f2unix-utime\fP returns the non-printing object.
.
.Pr unix-read-directory filename
.LP
This procedure returns the contents of the specified directory
as a list of filenames (strings).
\f2filename\fP must be the name of a directory.
\f2unix-read-directory\fP is based on the
.Ix opendir
.Ix readdir
.Ix closedir
\f2opendir()\fP, \f2readdir()\fP, and \f2closedir()\fP functions.
.LP
Example:
.Ss
;;; Return directory contents as list of (filename . filetype) pairs
.sp .4
(define (get-files-and-types directory)
(map
(lambda (file)
(cons file (stat-type (unix-stat file))))
(unix-read-directory directory)))
.sp .6
(pp (get-files-and-types "."))
.Se
.
.KS
.[[
.Pr unix-tempname
.Pr unix-tempname directory
.Pr unix-tempname directory prefix
.]]
.KE
.LP
\f2unix-tempname\fP returns a pathname that can be used as the name of a
.Ix "temporary file"
temporary file (typically in
.Ix /tmp
.Ix /usr/tmp
/tmp or /usr/tmp).
The newly created pathname is not the name of an existing file.
.LP
\f2directory\fP (a string or symbol) can be used to specify the
directory component of the pathname;
\f2prefix\fP (string or symbol), if present, may be used as a prefix
for the filename component of the pathname.
However, both arguments may be ignored by \f2unix-tempname\fP.
.LP
\f2unix-tempname\fP is based on one of the UNIX functions
.Ix tempnam
.Ix mktemp
.Ix tmpnam
\f2tempnam()\fP, \f2mktemp()\fP, and \f2tmpnam()\fP (in that order);
if none of these functions is available, an algorithm similar to
the one employed by UNIX \f2mktemp()\fP is used.
.
.Ch "Symbolic Links"
.
.PP
The following procedures are only defined on platforms that support
.Ix "symbolic links"
symbolic links.
In this case, the feature
.Ix unix:symlinks
\f2unix:symlinks\fP is provided when the UNIX extension is loaded.
.
.Pr unix-lstat filename
.LP
.Ix lstat
The UNIX \f2lstat()\fP system call.
\f2unix-lstat\fP returns a
.Ix stat-record
\f2stat-record\fP (see \f2unix-stat\fP above).
.
.Pr unix-readlink filename
.LP
.Ix readlink
The UNIX \f2readlink()\fP system call.
\f2unix-readlink\fP returns the contents of specified symbolic
link as a string.
.
.Pr unix-symlink filename\*1 filename\*2
.LP
.Ix symlink
The UNIX \f2symlink()\fP system call.
\f2unix-symlink\fP returns the non-printing object.
.
.Ch "File and Record Locking"
.
.PP
The procedures described in this section are only defined if some form
of file-based
.Ix locking
locking is available on the local system (either locking of entire files, or
.Ix "record locking"
record locking).
In this case, the feature
.Ix unix:file-locking
\f2unix:file-locking\fP is provided at the time the UNIX extension is loaded.
If the local system supports locking of individual file segments,
the feature
.Ix unix:record-locks
\f2unix:record-locks\fP is provided as well, and the locking
primitives are based on the
.Ix fcntl
\f2fcntl()\fP system call
(otherwise the
.Ix flock
\f2flock()\fP system call is used).
.
.Pr unix-set-lock fdescr lock wait?
.LP
The \f2lock\fP argument is a
.Ix lock-record
\f2lock-record\fP with these fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
_
exclusive?~boolean~T{
.nf
exclusive lock (write lock) if #t,
shared lock (read lock) otherwise
T}
whence~symbol~T{
.nf
\f2set\fP, \f2current\fP, or \f2end\fP:
interpretation of \f2start\fP (see \f2unix-lseek\fP)
T}
start~integer~relative offset in bytes
length~integer~T{
.nf
length in bytes
(0 means lock to EOF)
T}
.TE
.KE
.LP
.Ix "record locks"
If record locks are supported, the fields \f2whence\fP, \f2start\fP,
and \f2length\fP specify a segment in the file referred to
by \f2fdescr\fP that is to be locked or unlocked.
If only entire files can be locked, the contents of these fields are
ignored by the lock procedures.
.LP
An arbitrary number of
.Ix "shared lock"
shared locks for a file or file segment
may be active at a given time, but more than one
.Ix "exclusive lock"
exclusive lock,
or both shared and exclusive locks, cannot be set at the same time.
\f2fdescr\fP must be opened for reading to be able to set a
shared lock; it must be opened with write access for an exclusive lock.
A shared lock may be upgraded to an exclusive lock, and vice versa.
Mandatory locking may or may not be supported by the local system.
.LP
If the \f2wait?\fP argument is #t and the specified lock cannot be
applied, \f2unix-set-lock\fP blocks until the lock becomes available.
.LP
\f2unix-set-lock\fP returns #t if the specified lock could be applied,
#f otherwise.
.
.Pr unix-remove-lock fdescr lock
.LP
This procedure removes the specified file lock or record lock from
the file pointed to by \f2fdescr\fP.
\f2lock\fP is a \f2lock-record\fP; see \f2unix-set-lock\fP above for
a description.
\f2unix-remove-lock\fP returns the non-printing object.
.
.Pr unix-query-lock fdescr lock
.LP
If record locks are not supported, this procedure always returns #f.
If record locks are supported, \f2unix-query-lock\fP returns
information about the first lock that would cause a call to
\f2unix-set-lock\fP with \f2lock\fP to fail or block, or #f if no
such lock exists (i.\|e.\& if claiming the specified lock would succeed).
Information about the lock is returned as a pair; the car is an
integer (the process-ID of the the process that owns the lock),
the cdr is a \f2lock-record\fP.
The process-ID may be meaningless in a network environment.
.
.Ch "Obtaining Password and Group File Entries"
.
.PP
The procedures defined in this section are used to obtain entries
from the system's
.Ix "passwd database"
.Ix "group database"
\f2passwd\fP and \f2group\fP databases.
.
.[[
.Pr unix-get-passwd
.Pr unix-get-passwd user
.]]
.LP
If invoked without an argument, this procedure returns the next
entry from the \f2passwd\fP database.
Successive calls to \f2unix-get-passwd\fP return entries in a random
order.
The \f2user\fP argument, if present, is either the login name of a user
(a string or symbol) or a numeric user-ID (an integer).
In this case, the \f2passwd\fP entry for this user is returned.
.LP
\f2unix-get-passwd\fP returns a
.Ix passwd-record
\f2passwd-record\fP with the following fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
_
name~string~login name
password~string~login password
uid~integer~numeric user-ID
gid~integer~numeric primary group-ID
gecos~string~contents of GECOS field
homedir~string~home directory of user
shell~string~login shell of user
.TE
.KE
.LP
\f2unix-get-passwd\fP is based on the UNIX
.Ix getpwent
.Ix getpwuid
.Ix getpwnam
\f2getpwent()\fP, \f2getpwuid()\fP, and \f2getpwnam()\fP functions.
.
.[[
.Pr unix-get-group
.Pr unix-get-group group
.]]
.LP
\f2unix-get-group\fP is identical to
.Ix unix-get-passwd
\f2unix-get-passwd\fP (see above), except that the system's \f2group\fP
database is used instead of the \f2passwd\fP database.
.LP
The result value is a
.Ix group-record
\f2group-record\fP with these fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
name~string~group's name
password~string~group's password
gid~integer~numeric group-ID
members~list of symbols~group members
.TE
.KE
.LP
\f2unix-get-group\fP is based on the UNIX
.Ix getgrent
.Ix getgrnam
.Ix getgrgid
\f2getgrent()\fP, \f2getgrgid()\fP, and \f2getgrnam()\fP functions.
.
.[[
.Pr unix-rewind-passwd
.Pr unix-rewind-group
.]]
.LP
These procedures rewind the \f2passwd\fP and \f2group\fP files
by calling the
.Ix setpwent
.Ix setgrent
\f2setpwent()\fP and \f2setgrent()\fP UNIX functions.
.
.[[
.Pr unix-end-passwd
.Pr unix-end-group
.]]
.LP
\f2unix-end-passwd\fP and \f2unix-end-group\fP close the \f2passwd\fP
and \f2group\fP files by calling the UNIX functions
.Ix endpwent
.Ix endgrent
\f2endpwent()\fP and \f2endgrent()\fP.
.
.Ch "Process Creation and Control"
.
.Pr unix-system string
.LP
\f2unix-system\fP starts
.Ix /bin/sh
``/bin/sh'' as a child process with \f2string\fP as input and waits until the
.Ix shell
shell terminates.
All file descriptors except standard input, standard output, and standard
error output are closed in the child process.
\f2unix-system\fP returns the
.Ix "exit code"
exit code of the shell as an integer or, if the shell was interrupted
by a signal, the
.Ix "termination status"
termination status as a list of one integer element.
If the shell could not be executed, exit code 127 is returned.
.
.[[
.Pr unix-open-input-pipe string
.Pr unix-open-output-pipe string
.]]
.LP
.Ix popen
The UNIX \f2popen()\fP function.
Both procedures create a
.Ix pipe
pipe between the caller and a
.Ix shell
shell executing the command \f2string\fP; they return a Scheme port
containing the file pointer associated with the pipe.
Closing the Scheme port, or running the garbage collector after the
port has become unused, causes the pipe to be closed by a call to the
.Ix pclose
\f2pclose()\fP function.
.LP
\f2unix-open-input-pipe\fP returns an input port that can be used
to read from the standard output of the specified command;
\f2unix-open-output-pipe\fP returns an output port that accepts
input to be sent to the standard input of the command.
.
.Pr unix-fork
.LP
.Ix fork
The UNIX \f2fork()\fP system call.
\f2unix-fork\fP returns the process-ID of the newly created process
as an integer in the parent process, and the integer 0 in the child process.
.LP
The child process, as its first action, invokes the
.Ix "onfork handlers"
\f2onfork handlers\fP that may have been registered by other Elk extensions
that are currently active (one purpose of \f2onfork\fP handlers is to
make new links to
.Ix "temporary files"
temporary files in the newly created child process).
.
.KS
.[[
.Pr unix-exec filename arguments
.Pr unix-exec filename arguments environment
.sp .5
.Pr unix-exec-path filename arguments
.Pr unix-exec-path filename arguments environment
.]]
.KE
.LP
These procedures are based on the UNIX
.Ix execv
\f2execv()\fP family of system calls and library functions.
The first argument is the name of the file to be executed.
\f2arguments\fP is a list of strings to be passed to the program
as arguments.
The \f2environment\fP argument, if present, is a list of
.Ix environment
environment variable definitions to be used as the new program's
environment.
Each element of the list is pair of strings; the car of an element is
the name of an environment variable, the cdr is the variable's value
(the
.Ix unix-environ
\f2unix-environ\fP primitive can be used to obtain the current
environment of the running program).
.LP
\f2unix-exec-path\fP searches the specified filename in a list
of directories obtained from the calling program's
.Ix PATH
PATH environment variable.
The variant of \f2unix-exec-path\fP that accepts an \f2environment\fP
argument is not available on the currently supported platforms (the
reason is that there is no \f2execvpe()\fP variant of the
\f2execvp()\fP function, although \f2execve()\fP/\f2execle()\fP
variants of \f2execv()\fP and \f2execl()\fP usually exist in UNIX).
.LP
\f2unix-exec\fP and \f2unix-exec-path\fP remove the temporary files used
by the dynamic loading module of the interpreter kernel and invoke
the finalization functions that may have been registered by extensions.
As a result, attempting to load an object file after a call to
\f2unix-exec\fP or \f2unix-exec-path\fP has returned (i.\|e.\& failed)
may not work correctly.
The finalization functions are only invoked once.
.
.KS
.[[
.Pr unix-wait
.Pr unix-wait options
.sp .5
.Pr unix-wait-process pid
.Pr unix-wait-process pid options
.]]
.KE
.LP
\f2unix-wait\fP and \f2unix-wait-process\fP are based on the UNIX
.Ix wait
\f2wait()\fP family of system calls and library functions.
Both procedures return a
.Ix wait-record
\f2wait-record\fP with the following fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
pid~integer~process-ID of the terminated child process
status~symbol~reason for process termination
code~integer~exit code or termination status (signal)
core-dump?~boolean~#t if a core-dump was produced
resources~resources-record~resources of terminated process
.TE
.KE
.LP
See \f2unix-process-resources\fP below for a description of the
\f2resources-record\fP type.
.LP
The \f2wait-record\fP result holds the process-ID and termination
status of one of the terminated (or stopped) children of the calling
process.
The value of the \f2status\fP is one of the symbols \f2stopped\fP
(if the child process has been stopped), \f2signaled\fP (child
process is terminated due to a signal), or \f2exited\fP (child
process has invoked \f2exit()\fP).
\f2code\fP holds the exit code (if \f2status\fP is \f2exited\fP),
or a signal number (if \f2status\fP is either \f2stopped\fP or
\f2signaled\fP).
The \f2resources\fP field holds the user and system time consumed
by the child process and its children in nanoseconds (additional
resources may be supplied in future versions).
The fields of the \f2resources\fP record are #f on platforms that
do not support the
.Ix wait3
.Ix wait4
\f2wait3()\fP or \f2wait4()\fP system call.
.LP
\f2unix-wait-process\fP allows to collect the termination status
of an individual process or a group of processes specified by the
integer \f2pid\fP argument.
This procedure is only defined on platforms where the
.Ix waitpid
.Ix wait4
\f2waitpid()\fP or \f2wait4()\fP system call is available.
In this case, the feature
.Ix unix:wait-process
\f2unix:wait-process\fP is provided when the UNIX extension is loaded.
.LP
If no child process is available (or, in case of
\f2unix-wait-process\fP, no process as specified by the \f2pid\fP
argument), the \f2pid\fP field in the result is set to -1, and the
\f2status\fP field is set to the symbol \f2none\fP.
.LP
The \f2options\fP argument, if present, is a list of one or more
of the symbols \f2nohang\fP and \f2untraced\fP.
Options are only supported if the feature
.Ix unix:wait-options
\f2unix:wait-options\fP is provided.
.
.Pr unix-process-resources
.LP
This procedure is based on the UNIX
.Ix times
\f2times()\fP library function.
\f2unix-process-resources\fP returns the
.Ix "resource usage"
resource usage of the calling process and its terminated children as
a pair of
.Ix resources-record
\f2resources-records\fP.
Each \f2resources-record\fP has the following fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
user-time~integer~user time in nanoseconds
system-time~integer~system time in nanoseconds
.TE
.KE
.LP
Addition fields may be supplied in future versions.
.
.Pr unix-environ
.LP
\f2unix-environ\fP returns the program's
.Ix environment
environment as a list of pairs.
The car of each element is the name of an environment variable
(a string), the cdr is the value of that variable (a string).
.
.Pr unix-getenv string
.LP
This procedure returns the value of the environment variable with
the name \f2string\fP as a string, or #f if the specified variable
is not defined.
.
.Pr unix-working-directory
.LP
\f2unix-working-directory\fP
returns the calling program's current
.Ix "working directory"
working directory as a string.
The procedure is based on the
.Ix getcwd
.Ix getwd
\f2getcwd()\fP or \f2getwd()\fP function if any of these is available
and invokes the
.Ix pwd
``pwd'' command otherwise.
.
.Pr unix-getlogin
.LP
\f2unix-getlogin\fP returns the
.Ix "login name"
login name as a string (obtained by the UNIX
.Ix getlogin
\f2getlogin()\fP library function).
.
.[[
.Pr unix-getuids
.Pr unix-getgids
.]]
.LP
\f2unix-getuids\fP (\f2unix-getgids\fP) returns the calling program's
.Ix "real user-ID"
.Ix "effective user-ID"
.Ix "real group-ID"
.Ix "effective group-ID"
real and effective user-IDs (group-IDs) as a pair of integers.
.
.Pr unix-getpids
.LP
\f2unix-getpids\fP returns the
.Ix process-ID
process-ID of the calling process and the
.Ix "parent process-ID"
parent process-ID as a pair of integers.
.
.Pr unix-getgroups
.LP
\f2unix-getgroups\fP returns the current
.Ix "supplementary group-IDs"
supplementary group-IDs of the process as a list of integers.
.LP
Example:
.Ss
;;; Get list of names of supplementary group-IDs
.sp .4
(define (get-group-names)
(map
(lambda (gid)
(group-name (unix-get-group gid)))
(unix-getgroups)))
.Se
.
.Pr unix-umask mask
.LP
.Ix umask
The UNIX \f2umask()\fP system call.
\f2mask\fP is an integer.
The procedure returns the previous value of the umask.
.
.Pr unix-nice incr
.LP
.Ix nice
The UNIX \f2nice()\fP function.
\f2incr\fP is an integer.
\f2unix-nice\fP returns the new nice value (or zero on some platforms).
.
.Pr unix-sleep seconds
.LP
.Ix sleep
The UNIX \f2sleep()\fP function.
\f2seconds\fP is a positive integer.
The procedure returns the non-printing object.
.
.Ch "Obtaining System Information"
.
.Pr unix-system-info
.LP
This procedure returns a
.Ix system-record
\f2system-record\fP with these fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Contents
hostname~string~the system's hostname
sysname~string~type of hardware platform
osname~string~operating system type and version
.TE
.KE
.LP
The hostname is determined by a call to the UNIX
.Ix gethostname
.Ix uname
\f2gethostname()\fP or \f2uname()\fP function; the system name and OS
name are obtained from the configuration file that has been used to
configure and install Elk.
.
.Pr unix-file-limit limit file
.LP
\f2unix-file-limit\fP can be used to query various system
.Ix limits
limits and options associated with files.
\f2limit\fP is a symbol identifying the type of limit;
\f2file\fP is a filename or file descriptor.
.LP
At least the following limits and options can be queried:
.sp .5
.KS
.TS
allbox, tab(~);
c c
lf5 l.
Limit/Option~Meaning
_
max-links~maximum number of links to a file or directory
max-name~maximum length of a filename
max-path~maximum length of a pathname
pipe-buf~pipe buffer size
no-trunc~T{
.nf
filename exceeding maximum length causes error
instead of being silently truncated
T}
.TE
.KE
.LP
Additional limits may be present on some platforms.
The list of limits actually supported by this procedure can
be obtained by a call to
.Ix unix-list-file-limits
\f2unix-list-file-limits\fP (see below).
.LP
If present, the
.Ix POSIX
.Ix pathconf
.Ix fpathconf
POSIX \f2pathconf()\fP/\f2fpathconf()\fP function is
used to query a limit; in this case the specified filename or file
descriptor is supplied as an argument to \f2pathconf()\fP or
\f2fpathconf()\fP.
If \f2pathconf()\fP is not available, or if calling it is not
appropriate for the type of limit, a static (compile-time) value
is returned.
.LP
The result type of \f2unix-file-limit\fP depends on the type of the
specified limit (boolean in case of \f2no-trunc\fP, integer otherwise).
.
.Pr unix-list-file-limits
.LP
This procedure returns the list of limit symbols that can be supplied
as arguments to
.Ix unix-file-limit
\f2unix-file-limit\fP (see above).
.
.Pr unix-job-control?
.LP
This predicate returns #t if UNIX job control is available on the local
system, #f otherwise.
In a
.Ix POSIX
POSIX environment, this procedure may call
.Ix sysconf
\f2sysconf()\fP.
.
.Ch "Date and Time"
.
.Pr unix-time
.LP
.Ix time
The UNIX \f2time()\fP function.
\f2unix-time\fP returns the number of seconds elapsed since
midnight\ UTC,\ January\ 1,\ 1970 (\f2The Epoch\fP) as an integer.
.
.Pr unix-nanotime
.LP
This procedure returns the number of nanoseconds elapsed since
The Epoch as an integer.
\f2unix-nanotime\fP invokes one of the UNIX functions
.Ix gettimeofday
.Ix ftime
.Ix time
\f2gettimeofday()\fP, \f2ftime()\fP, \f2time()\fP (in that order,
depending on which of these function is available), thus
providing up to microsecond resolution.
.
.[[
.Pr unix-decode-localtime time
.Pr unix-decode-utc time
.]]
.LP
Both procedures convert the specified time (a number of seconds as
returned by \f2unix-time\fP) into a
.Ix time-record
\f2time-record\fP; \f2unix-decode-localtime\fP corrects for the
local time zone and DST adjustment (based on the UNIX
.Ix localtime
.Ix gmtime
\f2localtime()\fP and \f2gmtime()\fP functions).
.LP
A \f2time-record\fP has the following fields:
.sp .5
.KS
.TS
allbox, tab(~);
c c c
lf5 l l.
Field~Type~Range
_
seconds~integer~0..61
minutes~integer~0..59
hours~integer~0..23
day-of-month~integer~1..31
month~integer~0..11
year~integer~(year - 1900)
weekday~integer~0..6
day-of-year~integer~0..365
dst~integer~1 if DST in effect
.TE
.KE
.LP
Example:
.Ss
;;; Return date as a string of the form "Nov 3, 1993"
.sp .4
(define (date-string)
(let* ((months "JanFebMarAprMayJunJulAugSepOctNovDec")
(time (unix-decode-localtime (unix-time)))
(month-inx (* 3 (time-month time))))
.sp .4
(format #f "~a ~a, ~a"
(substring months month-inx (+ 3 month-inx))
(time-day-of-month time) (+ 1900 (time-year time)))))
.Se
.
.Pr unix-time->string time
.LP
This procedure converts the specified time into a string;
it is based on the
.Ix ctime
.Ix asctime
\f2ctime()\fP and \f2asctime()\fP UNIX functions.
\f2time\fP is either an integer (number of seconds) or a
\f2time-record\fP.
.
.Ch "Signals"
.
.PP
The procedures described in this section (except \f2unix-kill\fP,
\f2unix-list-signals\fP, and \f2unix-pause\fP)
are only defined if the local system supports
.Ix "reliable signals"
reliable signals (either
.Ix BSD
BSD-style or
.Ix POSIX
POSIX signals).
In this case, the feature
.Ix unix:reliable-signals
\f2unix:reliable-signals\fP is provided when the UNIX extension
is loaded.
.
.Pr unix-kill pid signal
.LP
.Ix kill
The UNIX \f2kill()\fP system call.
\f2pid\fP is an integer; \f2sig\fP is either an integer (a signal
number) or a symbol (a
.Ix "signal name"
signal name).
At least the following signal names are supported:
.sp .5
.KS
.TS
box, tab(~);
c s s
lf5 lf5 lf5.
Signal names
_
sigalrm~sigbus~sigfpe
sighup~sigill~sigint
sigkill~sigpipe~sigquit
sigsegv~sigterm~
.TE
.KE
.LP
The list of signal names actually supported by the local system
can be obtained by calling
.Ix unix-list-signals
\f2unix-list-signals\fP (see below).
.LP
\f2unix-kill\fP returns the non-printing object.
.
.Pr unix-list-signals
.LP
This procedure returns a list of
.Ix "signal name"
signal names (symbols) that are supported by the system.
.
.Pr alarm seconds
.LP
.Ix alarm
The UNIX \f2alarm()\fP function.
\f2seconds\fP is a positive integer.
\f2unix-alarm\fP returns the number of seconds remaining from the
previously set alarm.
.
.Pr unix-pause
.LP
.Ix pause
The UNIX \f2pause()\fP function.
This procedure does not return.
.
.[[
.Pr unix-signal sig action
.Pr unix-signal sig
.]]
.LP
\f2unix-signal\fP defines or queries the action to be performed when a
.Ix signal
signal is delivered to the program.
If an \f2action\fP argument is specified, this action is associated
with the signal \f2sig\fP, and the previous action for this
signal is returned.
If no action is given (second form), \f2unix-signal\fP just returns
the action currently associated with \f2sig\fP.
.LP
\f2sig\fP is the name of a signal (see \f2unix-kill\fP for a
description).
The action associated with \f2sigbus\fP, \f2sigfpe\fP, \f2sigill\fP,
\f2sigint\fP, \f2sigkill\fP, \f2sigsegv\fP, and \f2sigabrt\fP (if
supported) cannot be altered; either because UNIX does not permit
this (\f2sigkill\fP), or because the signal can be generated as
the result of an internal fatal error (\f2sigbus\fP etc.), or
because it is used by the interpreter internally (\f2sigsegv\fP is
used by the incremental garbage collector).
The action associated with the
.Ix "interrupt signal"
\f2interrupt\fP signal can be controlled by redefining the standard Elk
.Ix interrupt-handler
\f2interrupt-handler\fP (see the Elk reference manual for details).
.LP
\f2action\fP can be one of the following:
.RS
.IP "the symbol \f2ignore\fP
the specified signal is ignored
.IP "the symbol \f2default\fP
the default action for this signal is established
.IP "the symbol \f2exit\fP
cleanup and exit: if the signal is delivered, the interpreter's
.Ix "temporary files"
temporary files are removed, the
.Ix "finalization functions"
finalization functions and static C++ destructors of dynamically loaded
extensions are invoked, and \f2exit()\fP is called with an exit code of 1
.IP "a compound procedure"
the procedure
.Ix "signal handler"
(signal handler) is invoked on delivery of the specified signal.
.IP
.RE
.LP
The procedure specified as a signal handler must accept one or more
arguments.
When the signal is delivered, the procedure is invoked with the signal
name (a symbol) as an argument.
Signal handlers must not return (i.\|e.\& they must either exit or
call a continuation).
If a signal handler returns, a message is displayed and the
.Ix reset
\f2reset\fP primitive is called.
.LP
The signal specified as an argument to \f2unix-signal\fP is added to
(removed from) the
.Ix "signal mask"
signal mask maintained by the interpreter, i.\|e.\& calls to the
.Ix disable-interrupts
\f2disable-interrupts\fP primitive block the signal from delivery.
.LP
\f2unix-signal\fP returns the previous (current) action for the
specified signal (a procedure or \f2ignore\fP, \f2default\fP, or
\f2exit\fP) or the symbol \f2handler\fP to indicate that the
signal is handled internally by the interpreter.
.
.Ch "Miscellaneous Functions"
.
.Pr unix-getpass string
.LP
\f2unix-getpass\fP displays \f2string\fP on standard output, reads a
.Ix password
password, and returns the password as a string.
The procedure invokes the UNIX
.Ix getpass
\f2getpass()\fP function.
.
.Ch "Error Functions"
.
.Sy unix-errval expression
.LP
Normally, a Scheme error is signaled by the UNIX extension whenever a
UNIX system call or library function invoked by any of the above
primitives fails.
The macro \f2unix-errval\fP allows an application to handle an error
condition in a specific way without the need to redefine the standard
.Ix "error handler"
error handler of Elk.
.LP
\f2unix-errval\fP evaluates the specified expression and returns
the result of the evaluation.
If, during evaluation of the expression, an error is signaled due
to failure of a UNIX function, the corresponding primitive
procedure returns a unique
.Ix "error object"
\f2error object\fP instead of performing normal error handling.
.LP
For example, evaluating the expression
.Ss
(unix-close 1000) ; close a bad file descriptor
.Se
would invoke the standard Scheme error handler in the normal way,
whereas evaluating
.Ss
(unix-errval (unix-close 1000))
.Se
would return an error object to allow the application to handle
the error locally.
Note that evaluation of the enclosing expression is not interrupted
when an error is signaled, i.\|e.\& the expression
.Ss
(unix-errval (begin (unix-close 1000) 5))
.Se
would return the integer 5.
.
.Pr unix-error? obj
.LP
This procedure returns #t if \f2obj\fP is the \f2error object\fP,
#f otherwise.
\f2unix-error?\fP is typically used to check whether a primitive
invoked under control of \f2unix-errval\fP has signaled an error.
.
.Pr unix-errno
.LP
.Ix errno
Returns the UNIX \f2errno\fP set by the last system call that has
failed.
.Ix "error codes"
Error codes are represented as symbols corresponding to the names of the
standard UNIX error numbers with letters converted to lower case, i.\|e.
\f2enomem\fP, \f2ebadf\fP, etc.
The exact set of error codes that can be returned is platform-dependent.
.LP
The value returned by \f2unix-errno\fP is not reset when a UNIX system
call executes successfully.
However, value of \f2unix-errno\fP is also affected by functions
from the Elk kernel (such as \f2open-input-file\fP) and possibly
other extensions that make use of system calls.
.
.Pr unix-perror string
.LP
\f2unix-perror\fP writes \f2string\fP followed by a colon and a short
message describing the last UNIX error encountered to the current
output port.
\f2unix-perror\fP makes use of the ``~E'' format specifier of the
.Ix format
format primitive.
.
.bp
.Ch "Examples"
.LP
.Ix examples
This program implements a simple program interface to the UNIX
.Ix dc
\f2dc\fP desktop calculator command.
The procedure
.Ix calc-open
\f2calc-open\fP starts the \f2dc\fP command and establishes two
.Ix pipe
pipes to/from the child process; the procedure
.Ix calc
\f2calc\fP sends its argument (a \f2dc\fP expression as a string)
as input to \f2dc\fP;
.Ix calc-close
\f2calc-close\fP closes the pipes and waits for the subprocess to
terminate.
.Ss
(require 'unix)
.sp .4
(define calc-from-dc) ; input port: standard output of dc command
(define calc-to-dc) ; output port: standard input of dc command
(define calc-dc-pid) ; process-ID of child process running dc
.sp .4
(define calc-dc-command "/bin/dc")
.sp .4
(define (calc-open)
(let* ((from (unix-pipe))
(to (unix-pipe))
(redirect-fd (lambda (a b)
(unix-dup a b) (unix-close a))))
(set! calc-dc-pid (unix-fork))
(if (zero? calc-dc-pid)
(begin
(unix-close (car from))
(unix-close (cdr to))
(redirect-fd (car to) 0)
(redirect-fd (cdr from) 1)
(unix-exec calc-dc-command '("dc")))
(begin
(unix-close (cdr from))
(unix-close (car to))
(set! calc-to-dc (unix-filedescriptor->port (cdr to) "w"))
(set! calc-from-dc (unix-filedescriptor->port (car from) "r"))))))
.sp .4
(define (calc expr)
(format calc-to-dc "~a~%" expr)
(flush-output-port calc-to-dc)
(read-string calc-from-dc))
.sp .4
(define (calc-close)
(close-output-port calc-to-dc)
(close-input-port calc-from-dc)
(unix-wait-process calc-dc-pid))
;;; Test -- print sqrt(2):
.sp .4
(calc-open)
(display (calc "10k 2v p")) (newline)
(calc-close)
.Se
.bp
.LP
The following procedure copies a file; the arguments are the source and
target file names.
The second argument may name a directory, in this case the file is
copied into the directory.
The target file must not yet exist.
.Ix copy-file
\f2copy-file\fP preserves the access mode of the source file.
.Ss
(require 'unix)
.sp .4
(define copy-buffer-size 8192)
.sp .4
(define (copy-file from to)
(let ((from-stat (unix-stat from))
(to-stat (unix-errval (unix-stat to))))
.sp .3
(if (eq? (stat-type from-stat) 'directory) ; complain if "from"
(error 'copy-file "~s is a directory" from)) ; is a directory
.sp .3
(if (and (not (unix-error? to-stat)) ; destination exists
(eq? (stat-type to-stat) 'directory)) ; and is a directory?
(set! to (format #f "~a/~a" to from)))
.sp .3
(let* ((to-fd (unix-open to '(write create exclusive)
(stat-mode from-stat)))
(from-fd (unix-open from '(read)))
(buf (make-string copy-buffer-size)))
(let loop ((num-chars (unix-read-string-fill! from-fd buf)))
(if (positive? num-chars)
(begin
(unix-write to-fd buf num-chars)
(loop (unix-read-string-fill! from-fd buf)))))
.sp .3
(unix-close from-fd)
(unix-close to-fd))))
.Se
.bp
.LP
\f2lock-vi\fP starts the
.Ix vi
.Ix editor
\f2vi\fP editor with the specified file name.
It provides exclusive access to the file during the editing session by
applying a write lock to the file and removing it when the editor finishes.
A message is displayed periodically if the lock is held by somebody else.
.Ss
(require 'unix)
.sp .4
(define (lock-vi file)
(let* ((fd (unix-open file '(read write)))
(lock ((record-constructor lock-record) #t 'set 0 0)))
.sp .4
(let loop ()
(if (not (unix-set-lock fd lock #f))
(begin
(format #t "Someone else is editing ~s...~%" file)
(unix-sleep 10)
(loop))))
.sp .4
(unix-system (format #f "vi ~a" file))
(unix-remove-lock fd lock)))
.Se
.sp
.LP
\f2pipe-size\fP attempts to determine the capacity of a
.Ix pipe
pipe.
It creates a pipe, places the write end of the pipe into
.Ix "non-blocking I/O"
non-blocking I/O mode and writes into the pipe until it is full,
counting the characters successfully written.
.Ss
(require 'unix)
.sp .4
(define (pipe-size)
(let* ((pipe (unix-pipe))
(flags (unix-filedescriptor-flags (cdr pipe)))
(len 32) ; assumes capacity is multiple of len
(noise (make-string len)))
.sp .4
;; enable non-blocking I/O for write side of pipe:
(unix-filedescriptor-flags (cdr pipe) (cons 'ndelay flags))
.sp .4
(unwind-protect
(let loop ((size 0))
(if (unix-error? (unix-errval (unix-write (cdr pipe) noise)))
(if (memq (unix-errno) '(eagain ewouldblock))
size
(error 'pipe-size "~E"))
(loop (+ size 32))))
(unix-close (car pipe))
(unix-close (cdr pipe)))))
.Se