The material in this section and the following one is not critical for most
applications.
You may safely skim or completely skip this section on a first reading.
Dealing with {\Unix} file descriptors in a {\Scheme} environment is difficult.
In {\Unix}, open files are part of the process environment, and are referenced
by small integers called \emph{file descriptors}. Open file descriptors are
the fundamental way i/o redirections are passed to subprocesses, since
file descriptors are preserved across fork's and exec's.
{\Scheme}, on the other hand, uses ports for specifying i/o sources. Ports are
garbage-collected {\Scheme} objects, not integers. Ports can be garbage
collected; when a port is collected, it is also closed. Because file
descriptors are just integers, it's impossible to garbage collect them---you
wouldn't be able to close file descriptor 3 unless there were no 3's in the
system, and you could further prove that your program would never again
compute a 3. This is difficult at best.
If a {\Scheme} program only used {\Scheme} ports, and never actually used
file descriptors, this would not be a problem. But {\Scheme} code
must descend to the file descriptor level in at least two circumstances:
%
\begin{itemize}
\item when interfacing to foreign code
\item when interfacing to a subprocess.
\end{itemize}
%
This causes a problem. Suppose we have a {\Scheme} port constructed
on top of file descriptor 2. We intend to fork off a program that
will inherit this file descriptor. If we drop references to the port,
the garbage collector may prematurely close file 2 before we fork
the subprocess. The interface described below is intended to fix this and
other problems arising from the mismatch between ports and file descriptors.
The {\Scheme} kernel maintains a port table that maps a file descriptor
to the {\Scheme} port allocated for it (or, {\sharpf} if there is no port
allocated for this file descriptor). This is used to ensure that
there is at most one open port for each open file descriptor.
The port data structure for file ports has two fields besides the descriptor:
\var{revealed} and \var{closed?}.
When a file port is closed with \ex{(close port)},
the port's file descriptor is closed, its entry in the port table is cleared,
and the port's \var{closed?} field is set to true.
When a file descriptor is closed with \ex{(close fdes)}, any associated
port is shifted to a new file descriptor created with \ex{(dup fdes)}.
The port has its revealed count reset to zero (and hence becomes eligible
for closing on GC). See discussion below.
To really put a stake through a descriptor's heart without waiting for
associated ports to be GC'd, you must say one of
%
\begin{code}
(close (fdes->inport fdes))
(close (fdes->output fdes))\end{code}
The \var{revealed} field is an aid to garbage collection. It is an integer
semaphore. If it is zero, the port's file descriptor can be closed when
the port is collected. Essentially, the \var{revealed} field reflects whether
or not the port's file descriptor has escaped to the {\Scheme} user. If
the {\Scheme} user doesn't know what file descriptor is associated with
a given port, then he can't possibly retain an ``integer handle'' on the
port after dropping pointers to the port itself, so the garbage collector
is free to close the file.
Ports allocated with \ex{open-output-file} and \ex{open-input-file} are
unrevealed ports---\ie, \var{revealed} is initialised to 0.
No one knows the port's file descriptor, so the file descriptor can be closed
when the port is collected.
The functions \ex{fdes->output-port}, \ex{fdes->input-port}, \ex{port->fdes}
are used to shift back and forth between file descriptors and ports. When
\ex{port->fdes} reveals a port's file descriptor, it increments the port's
\var{revealed} field. When the user is through with the file descriptor, he
can call \ex{(release-port-handle \var{port})}, which decrements the count.
The function \ex{(call/fdes fd/port \var{proc})} automates this protocol.
\ex{call/fdes} uses \ex{dynamic-wind} to enforce the protocol.
If \var{proc} throws out of the \ex{call/fdes} application,
the unwind handler releases the descriptor handle;
if the user subsequently tries to throw \emph{back} into \var{proc}'s
context, the wind handler raises an error. When the user maps a file
descriptor to a port with \ex{fdes->outport} or \ex{fdes->inport}, the port
has its revealed field incremented.
Not all file descriptors are created by requests to make ports. Some are
inherited on process invocation via \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}}, and are simply part of the
global environment. Subprocesses may depend upon them, so if a port is later
allocated for these file descriptors, is should be considered as a revealed
port. For example, when the {\Scheme} shell's process starts up, it opens ports
on file descriptors 0, 1, and 2 for the initial values of
\ex{(current-input-port)}, \ex{(current-output-port)}, and
\ex{(error-output-port)}.
These ports are initialised with \var{revealed} set to 1,
so that stdin, stdout, and stderr are not closed even if the user drops the
port.
Unrevealed file ports have the nice property that they can be closed when all
pointers to the port are dropped. This can happen during gc, or at an
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}}---since all memory is dropped at an \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}}. No one knows the
file descriptor associated with the port, so the exec'd process certainly
can't refer to it.
This facility preserves the transparent close-on-collect property
for file ports that are used in straightforward ways, yet allows
access to the underlying {\Unix} substrate without interference from
the garbage collector. This is critical, since shell programming
absolutely requires access to the {\Unix} file descriptors, as their
numerical values are a critical part of the process interface.
A port's underlying file descriptor can be shifted around with \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup(2)}}
when convenient. That is, the actual file descriptor on top of which a port is
constructed can be shifted around underneath the port by the scsh kernel when
necessary. This is important, because when the user is setting up file
descriptors prior to a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}}, he may explicitly use a file descriptor
that has already been allocated to some port. In this case, the scsh kernel
just shifts the port's file descriptor to some new location with \ex{dup},
freeing up its old descriptor. This prevents errors from happening in the
following scenario. Suppose we have a file open on port \ex{f}. Now we want
to run a program that reads input on file 0, writes output to file 1, errors
to file 2, and logs execution information on file 3. We want to run this
program with input from \ex{f}.
So we write:
%
\begin{code}
(run (/usr/shivers/bin/prog)
(> 1 output.txt)
(> 2 error.log)
(> 3 trace.log)
(= 0 ,f))\end{code}
%
Now, suppose by ill chance that, unbeknownst to us, when the operating system
opened \ex{f}'s file, it allocated descriptor 3 for it. If we blindly redirect
\ex{trace.log} into file descriptor 3, we'll clobber \ex{f}! However, the
port-shuffling machinery saves us: when the \ex{run} form tries to dup
\ex{trace.log}'s file descriptor to 3, \ex{dup} will notice that file
descriptor 3 is already associated with an unrevealed port (\ie, \ex{f}). So,
it will first move \ex{f} to some other file descriptor. This keeps \ex{f}
alive and well so that it can subsequently be dup'd into descriptor 0 for
\ex{prog}'s stdin.
The port-shifting machinery makes the following guarantee: a port is only
moved when the underlying file descriptor is closed, either by a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}}
or a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}} operation. Otherwise a port/file-descriptor association is
stable.
Under normal circumstances, all this machinery just works behind the scenes to
keep things straightened out. The only time the user has to think about it is
when he starts accessing file descriptors from ports, which he should almost
never have to do. If a user starts asking what file descriptors have been
allocated to what ports, he has to take responsibility for managing this
information.
\subsection{Port-mapping machinery}
The procedures provided in this section are almost never needed.
You may safely skim or completely skip this section on a first reading.
Here are the routines for manipulating ports in scsh. The important
points to remember are:
\begin{itemize}
\item A file port is associated with an open file, not a particular file
descriptor.
\item The association between a file port and a particular file descriptor
is never changed \emph{except} when the file descriptor is explicitly
closed. ``Closing'' includes being used as the target of a \ex{dup2}, so
the set of procedures below that close their targets are
\ex{close}, two-argument \ex{dup}, and \ex{move->fdes}.
If the target file descriptor of one of these routines has an
allocated port, the port will be shifted to another freshly-allocated
file descriptor, and marked as unrevealed, thus preserving the port
but freeing its old file descriptor.
\end{itemize}
These rules are what is necessary to ``make things work out'' with no
surprises in the general case.
\defun{fdes->inport}{fd}{port}
\defunx{fdes->outport}{fd}{port}
\defunx{port->fdes}{port}{\fixnum}
\begin{desc}
These increment the port's revealed count.
\end{desc}
\defun{port-revealed}{port}{{\integer} or \sharpf}
\begin{desc}
Return the port's revealed count if positive, otherwise \sharpf.
\end{desc}
\defun{release-port-handle}{port}{\undefined}
\begin{desc}
Decrement the port's revealed count.
\end{desc}
\defun{call/fdes}{fd/port consumer}{value(s) of consumer}
\begin{desc}
Calls \var{consumer} on a file descriptor;
takes care of revealed bookkeeping.
If \var{fd/port} is a file descriptor, this is just
\ex{(\var{consumer}\var{fd/port})}.
If \var{fd/port} is a port,
calls \var{consumer} on its underlying file descriptor.
While \var{consumer} is running, the port's revealed count is incremented.
When \ex{call/fdes} is called with port argument, you are not allowed to
throw into \var{consumer} with a stored continuation, as that would violate
the revealed-count bookkeeping.
\end{desc}
\defun{move->fdes}{fd/port target-fd}{port or fdes}
\begin{desc}
Maps fd$\rightarrow$fd and port$\rightarrow$port.
If \var{fd/port} is a file-descriptor not equal to \var{target-fd},
dup it to \var{target-fd} and close it. Returns \var{target-fd}.
If \var{fd/port} is a port, it is shifted to \var{target-fd},
by duping its underlying file-descriptor if necessary.
\var{Fd/port}'s original file descriptor is
closed (if it was different from \var{target-fd}).
Returns the port.
This operation resets \var{fd/port}'s revealed count to 1.
In all cases when \var{fd/port} is actually shifted, if there is a port
already using \var{target-fd}, it is first relocated to some other file
These procedures provide the functionality of C's \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}}.
The different routines return different types of values:
\ex{dup->inport}, \ex{dup->outport}, and \ex{dup->fdes} return
input ports, output ports, and integer file descriptors, respectively.
\ex{dup}'s return value depends on on the type of
\var{fd/port}---it maps fd$\rightarrow$fd and port$\rightarrow$port.
These procedures use the {\Unix}\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} syscall to replicate
the file descriptor or file port \var{fd/port}.
If a \var{newfd} file descriptor is given, it is used as the target of
the dup operation, \ie, the operation is a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}}.
In this case, procedures that return a port (such as \ex{dup->inport})
will return one with the revealed count set to one.
For example, \ex{(dup (current-input-port) 5)} produces
a new port with underlying file descriptor 5, whose revealed count is 1.
If \var{newfd} is not specified,
then the operating system chooses the file descriptor,
and any returned port is marked as unrevealed.
If the \var{newfd} target is given,
and some port is already using that file descriptor,
the port is first quietly shifted (with another \ex{dup})
to some other file descriptor (zeroing its revealed count).
Since {\Scheme} doesn't provide read/write ports,
\ex{dup->inport} and \ex{dup->outport} can be useful for
getting an output version of an input port, or \emph{vice versa}.
For example, if \ex{p} is an input port open on a tty, and
we would like to do output to that tty, we can simply use
\ex{(dup->outport p)} to produce an equivalent output port for the tty.
\end{desc}
\defun{seek}{fd/port offset [whence]}{\integer}
\begin{desc}
Reposition the I/O cursor for a file descriptor or port.
\var{whence} is one of \{\ex{seek/set}, \ex{seek/delta}, \ex{seek/end}\},
and defaults to \ex{seek/set}.
If \ex{seek/set}, then \var{offset} is an absolute index into the file;
if \ex{seek/delta}, then \var{offset} is a relative offset from the current
I/O cursor;
if \ex{seek/end}, then \var{offset} is a relative offset from the end of file.
The \var{fd/port} argument may be a port or an integer file descriptor.
Not all such values are seekable;
this is dependent on the OS implementation.
The return value is the resulting position of the I/O cursor in the I/O stream.
\oops{The current implementation doesn't handle \var{offset} arguments
that are not immediate integers (\ie, representable in 30 bits).}
\end{desc}
\defun{tell}{fd/port}{\integer}
\begin{desc}
Returns the position of the I/O cursor in the the I/O stream.
Not all file descriptors or ports support cursor-reporting;
This procedure does nothing when applied to an integer file descriptor
or unbuffered port.
It flushes buffered output when applied to a buffered port,
and raises a write-error exception on error. Returns no value.
\end{defundesc}
\begin{defundesc}{flush-all-ports}{}{\undefined}
This procedure flushes all open output ports with buffered data.
\end{defundesc}
\subsection{File locking}
Scsh provides {\Posix} advisory file locking.
\emph{Advisory} locks are locks that can be checked by user code,
but do not affect other I/O operations.
For example, if a process has an exclusive lock on a region of a file,
other processes will not be able to obtain locks on that region of the file,
but they will still be able to read and write the file with no hindrance.
Using advisory locks requires cooperation amongst the agents accessing
the shared resource.
\remark{
Unfortunately, {\Posix} file locks are associated with actual files,
not with associated open file descriptors.
Once a process locks a file, using some file descriptor \var{fd},
the next time \emph{any} file descriptor referencing that file is closed,
all associated locks are released.
This severely limits the utility of {\Posix} advisory file locks,
and we'd recommend caution when using them.
It is not without reason that the FreeBSD man pages refer to {\Posix}
file locking as ``completely stupid.''
Scsh moves Scheme ports from file descriptor to file descriptor with
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}} as required by the runtime,
so it is impossible to keep file locks open across one of these shifts.
Hence we can only offer {\Posix} advisory file locking directly on raw
integer file descriptors;
regrettably, there are no facilities for locking Scheme ports.
Note that once a Scheme port is revealed in scsh, the runtime will not
shift the port around with \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}}.
This means the file-locking procedures can then be applied to the port's
associated file descriptor.
}
{\Posix} allows the user to lock a region of a file with either
an exclusive or shared lock.
Locked regions are described by the \emph{lock-region} record:
If you override an existing object, then \var{old-fname}
and \var{new-fname} must type-match---either both directories,
or both non-directories.
This is required by the semantics of {\Unix}\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=rename&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{rename()}}.
\remark{
There is an unfortunate atomicity problem with the \ex{rename-file}
procedure: if you
specify no-override, but create file \ex{new-fname} sometime between
\ex{rename-file}'s existence check and the actual rename operation,
your file will be clobbered with \ex{old-fname}. There is no way to fix
this problem, given the semantics of {\Unix}\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=rename&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{rename()}};
at least it is highly unlikely to occur in practice.
do what it is claimed to do. We just threw it in for humor value.
See the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=sync&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{sync(2)}} man page for {\Unix} enlightenment.
A file is considered writeable if either (1) it exists and is writeable
or (2) it doesn't exist and the directory is writeable.
Since symlink permission bits are ignored by the filesystem, these
calls do not take a \var{chase?} flag.
Note that these procedures use the process' \emph{effective} user
and group ids for permission checking. {\Posix} defines an \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=access&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{access()}}
function that uses the process' real uid and gids. This is handy
for setuid programs that would like to find out if the actual user
has specific rights; scsh ought to provide this functionality (but doesn't
at the current time).
There are several problems with these procedures. First, there's an
atomicity issue. In between checking permissions for a file and then trying
an operation on the file, another process could change the permissions,
so a return value from these functions guarantees nothing. Second,
the code special-cases permission checking when the uid is root---if
the file exists, root is assumed to have the requested permission.
However, not even root can write a file that is on a read-only file system,
such as a CD ROM. In this case, \ex{file-not-writable?} will lie, saying
that root has write access, when in fact the opening the file for write
access will fail.
Finally, write permission confounds write access and create access.
These should be disentangled.
Some of these problems could be avoided if {\Posix} had a real-uid
variant of the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=access&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{access()}} call we could use, but the atomicity
issue is still a problem. In the final analysis, the only way to
find out if you have the right to perform an operation on a file
is to try and open it for the desired operation. These permission-checking
functions are mostly intended for script-writing, where loose guarantees
\note{This procedure is deprecated, and will probably either go away or
be substantially altered in a future release. New code should not
call this procedure. The problem is that it relies upon
Posix-notation regular expressions; the rest of scsh has been
converted over to the new SRE notation.}
\ex{file-match} provides a more powerful file-matching service, at the
expense of a less convenient notation. It is intermediate in
power between most shell matching machinery and recursive \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=find&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{find(1)}}.
Each pattern is a regexp. The procedure searches from \var{root},
matching the first-level files against pattern \vari{pat}1, the
second-level files against \vari{pat}2, and so forth.
The list of files matching the whole path pattern is returned,
in sorted order.
The matcher uses Spencer's regular expression package.
The files \ex{.} and \ex{..} are never matched. Other dot files are only
matched if the \var{dot-files?} argument is \sharpt.
A given \vari{pat}i pattern is matched as a regexp, so it is not forced
to match the entire file name. \Eg, pattern \ex{"t"} matches any
file containing a ``t'' in its name, while pattern \verb|"^t$"| matches
only a file whose entire name is ``\ex{t}''.
The \vari{pat}i patterns can be more general than stated above.
\begin{itemize}
\item A single pattern can specify multiple levels of the path by
embedding \ex{/} characters within the pattern. For example,
the pattern \ex{"a/b/c"} gives a match equivalent to the
list of patterns \ex{"a" "b" "c"}.
\item A \vari{pat}i pattern can be a procedure,
which is used as a match predicate.
It will be repeatedly called with a candidate file-name to test.
The file-name will be the entire path accumulated.
If the procedure raises an error condition, \ex{file-match} will
catch the error and treat it as a failed match.
This keeps \ex{file-match} from being blown out of the water
by applying tests to dangling symlinks and other similar situations.
\end{itemize}
Some examples:
%% UGH. Because we are using code instead of verbatim, we have to
The \ex{\ldots/env} variants take an environment specified as a
string$\rightarrow$string alist.
An environment of {\sharpt} is taken to mean the current process' environment
(\ie, the value of the external char \ex{**environ}).
[Rationale: {\sharpf} is a more convenient marker for the current environment
than {\sharpt}, but would cause an ambiguity on Schemes that identify
{\sharpf} and \ex{()}.]
The path-searching variants search the directories in the list
{\ttt exec\=path\=list} for the program.
A path-search is not performed if the program name contains
a slash character---it is used directly. So a program with a name like
\ex{"bin/prog"} always executes the program \ex{bin/prog} in the current working
directory. See \verb|$path| and \verb|exec-path-list|, below.
Note that there is no analog to the C function \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=execv&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{execv()}}.
To get the effect just do
\codex{(apply exec prog arglist)}
All of these procedures flush buffered output and close unrevealed ports
before executing the new binary.
To avoid flushing buffered output, see \verb|%exec| below.
Note that the C \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}} procedure allows the zeroth element of the
argument vector to be different from the file being executed, \eg
%
\begin{inset}
\begin{verbatim}
char *argv[] = {"-", "-f", 0};
exec("/bin/csh", argv, envp);\end{verbatim}
\end{inset}
%
The scsh \ex{exec}, \ex{exec-path}, \ex{exec/env}, and \ex{exec-path/env}
procedures do not give this functionality---element 0 of the arg vector is
always identical to the \ex{prog} argument. In the rare case the user wishes
to differentiate these two items, he can use the low-level \verb|%exec| and
\verb|exec-path-search| procedures.
These procedures never return under any circumstances.
As with any other system call, if there is an error, they raise
an exception.
\end{desc}
\defun{\%exec}{prog arglist env}\undefined
\defunx{exec-path-search}{fname pathlist}{{\str} or \sharpf}
\begin{desc}
The \ex{\%exec} procedure is the low-level interface to the system call.
The \var{arglist} parameter is a list of arguments;
\var{env} is either a string$\rightarrow$string alist or {\sharpt}.
The new program's \cd{argv[0]} will be taken from \ex{(car \var{arglist})},
\emph{not} from \var{prog}.
An environment of {\sharpt} means the current process' environment.
\verb|%exec| does not flush buffered output
(see \ex{flush-all-ports}).
All exec procedures, including \verb|%exec|, coerce the \cd{prog} and \cd{arg}
values to strings using the usual conversion rules: numbers are converted to
decimal numerals, and symbols converted to their print-names.
\ex{exec-path-search} searches the directories of \var{pathlist} looking for
an occurrence of file \ex{fname}. If no executable file is found, it returns
{\sharpf}. If \ex{fname} contains a slash character, the path search is
short-circuited, but the procedure still checks to ensure that the file exists
and is executable---if not, it still returns {\sharpf}.
Users of this procedure should be aware that it invites a potential race
condition: between checking the file with \ex{exec-path-search} and executing
it with \ex{\%exec}, the file's status might change.
The only atomic way to do the search is to loop over the candidate
file names, exec'ing each one and looping when the exec operation fails.
See \cd{$path} and \ex{exec-path-list}, below.
\end{desc}
\defun{exit}{[status]}\noreturn
\defunx{\%exit}{[status]}\noreturn
\begin{desc}
These procedures terminate the current process with a given exit status.
The default exit status is 0.
The low-level \verb|%exit| procedure immediately terminates the process
\ex{call-terminally} calls its thunk. When the thunk returns, the process
exits. Although \ex{call-terminally} could be implemented as
\codex{(\l{thunk} (thunk) (exit 0))}
an implementation can take advantage of the fact that this procedure never
returns. For example, the runtime can start with a fresh stack and also
start with a fresh dynamic environment, where shadowed bindings are
discarded. This can allow the old stack and dynamic environment to be
collected (assuming this data is not reachable through some live
continuation).
\end{defundesc}
\begin{defundesc}{suspend}{}\undefined
Suspend the current process with a SIGSTOP signal.
\end{defundesc}
\defun{fork}{[thunk]}{proc or \sharpf}
\defunx{\%fork}{[thunk]}{proc or \sharpf}
\begin{desc}
\ex{fork} with no arguments is like C \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=fork&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{fork()}}.
In the parent process, it returns the child's \emph{process object}
(see below for more information on process objects).
In the child process, it returns {\sharpf}.
\ex{fork} with an argument only returns in the parent process, returning
the child's process object.
The child process calls \var{thunk} and then exits.
\ex{fork} flushes buffered output before forking, and sets the child
process to non-interactive. \verb|%fork| does not perform this bookkeeping;
it simply forks.
\end{desc}
\defun{fork/pipe}{[thunk]}{proc or \sharpf}
\defunx{\%fork/pipe}{[thunk]}{proc or \sharpf}
\begin{desc}
Like \ex{fork} and \ex{\%fork}, but the parent and child communicate via a
pipe connecting the parent's stdin to the child's stdout. These procedures
side-effect the parent by changing his stdin.
In effect, \ex{fork/pipe} splices a process into the data stream
immediately upstream of the current process.
This is the basic function for creating pipelines.
Long pipelines are built by performing a sequence of \ex{fork/pipe} calls.
For example, to create a background two-process pipe \ex{a | b}, we write:
%
\begin{code}
(fork (\l{} (fork/pipe a) (b)))\end{code}
%
which returns the process object for \ex{b}'s process.
To create a background three-process pipe \ex{a | b | c}, we write:
%
\begin{code}
(fork (\l{} (fork/pipe a)
(fork/pipe b)
(c)))\end{code}
%
which returns the process object for \ex{c}'s process.
Note that these procedures affect file descriptors, not ports.
That is, the pipe is allocated connecting the child's file descriptor
1 to the parent's file descriptor 0.
\emph{Any previous Scheme port built over these affected file descriptors
is shifted to a new, unused file descriptor with \ex{dup} before
allocating the I/O pipe.}
This means, for example, that the ports bound to \ex{(current-input-port)}
and \ex{(current-output-port)} in either process are not affected---they
still refer to the same I/O sources and sinks as before.
Remember the simple scsh rule: Scheme ports are bound to I/O sources
and sinks, \emph{not} particular file descriptors.
If the child process wishes to rebind the current output port
to the pipe on file descriptor 1, it can do this using
\ex{with-current-output-port} or a related form.
Similarly, if the parent wishes to change the current input port
to the pipe on file descriptor 0, it can do this using
\ex{set-current-input-port!} or a related form.
Here is an example showing how to set up the I/O ports on both sides
of the pipe:
\begin{code}
(fork/pipe (\l{}
(with-current-output-port (fdes->outport 1)
(display "Hello, world.\\n"))))
(set-current-input-port! (fdes->inport 0)
(read-line) ; Read the string output by the child.\end{code}
None of this is necessary when the I/O is performed by an exec'd
program in the child or parent process, only when the pipe will
be referenced by Scheme code through one of the default current I/O
ports.
\end{desc}
\defun{fork/pipe+}{conns [thunk]}{proc or \sharpf}
\defunx{\%fork/pipe+}{conns [thunk]}{proc or \sharpf}
\begin{desc}
Like \ex{fork/pipe}, but the pipe connections between the child and parent
These routines get and set the effective and real user and group ids.
The \ex{set-uid} and \ex{set-gid} routines correspond to the {\Posix}
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=setuid&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{setuid()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=setgid&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{setgid()}} procedures.
Given that, why not have the fine-grain time procedure just
return a non-integer real for time? Following Common Lisp, I chose to
allow the system clock to report sub-second time in its own units to
lower the overhead of determining the time. This would be important
for a system that wanted to precisely time the duration of some
event. Time stamps could be collected with little overhead, deferring
the overhead of precisely calculating with them until after collection.
This is all a bit academic for the {\scm} implementation, where
we determine time with a heavyweight system call, but it's nice
to plan for the future.
\end{remarkenv}
\end{desc}
\defun{date}{}{date-record}
\defunx{date}{[time tz]}{date-record}
\begin{desc}
Simple \ex{(date)} returns the current date, in the local time zone.
With the optional arguments, \ex{date} converts the time to the date as
specified by the time zone \var{tz}.
\var{Time} defaults to the current time; \var{tz} defaults to local time,
and is as described in the time-zone section.
If the \var{tz} argument is an integer, the date's \ex{tz-name}
field is a {\Posix} time zone of the form
``\ex{UTC+\emph{hh}:\emph{mm}:\emph{ss}}'';
the trailing \ex{:\emph{mm}:\emph{ss}} portion is deleted if it is zeroes.
\oops{The Posix facility for converting dates to times, \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=mktime&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{mktime()}},
has a broken design: it indicates an error by returning -1, which
is also a legal return value (for date 23:59:59 UCT, 12/31/1969).
Scsh resolves the ambiguity in a paranoid fashion: it always
reports an error if the underlying Unix facility returns -1.
We feel your pain.
}
\end{desc}
\defun{time}{}\integer
\defunx{time}{[date]}\integer
\begin{desc}
Simple \ex{(time)} returns the current time.
With the optional date argument, \ex{time} converts a date to a time.
\var{Date} defaults to the current date.
Note that the input \var{date} record is overconstrained.
\ex{time} ignores \var{date}'s \ex{week-day} and \ex{year-day} fields.
If the date's \ex{tz-secs} field is set, the \ex{tz-name} and
\ex{summer?} fields are ignored.
If the \ex{tz-secs} field is \ex{\#f}, then the time-zone is taken
from the \ex{tz-name} field. A false \ex{tz-name} means the system's
current time zone. When calculating with time-zones, the date's
\ex{summer?} field is used to resolve ambiguities:
\begin{tightinset}
\begin{tabular}{ll}
\ex{\#f}& Resolve an ambiguous time in favor of non-summer time. \\
true & Resolve an ambiguous time in favor of summer time.
\end{tabular}
\end{tightinset}
This is useful in boundary cases during the change-over. For example,
in the Fall, when US daylight savings time changes over at 2:00 am,
1:30 am happens twice---it names two instants in time, an hour apart.
Outside of these boundary cases, the \ex{summer?} flag is ignored. For
example, if the standard/summer change-overs happen in the Fall and the
Spring, then the value of \ex{summer?} is ignored for a January or
July date. A January date would be resolved with standard time, and a
July date with summer time, regardless of the \ex{summer?} value.
The \ex{summer?} flag is also ignored if the time zone doesn't have
a summer time---for example, simple UTC.
\end{desc}
\defun{date->string}{date}\str
\defunx{format-date}{fmt date}\str
\begin{desc}
\ex{Date->string} formats the date as a 24-character string of the
form:
\begin{tightinset}
Sun Sep 16 01:03:52 1973
\end{tightinset}
\ex{Format-date} formats the date according to the format string
\var{fmt}. The format string is copied verbatim, except that tilde
characters indicate conversion specifiers that are replaced by fields from
the date record. Figure \ref{fig:dateconv} gives the full set of
conversion specifiers supported by \ex{format-date}.