|
|
|
TSION adds C-coded foreign functions to TinyScheme for TCP/IP networking and I/O event dispatching. The latter capability allows you to build programs structured on an event loop: the program is idle until an I/O event (e.g., data received on a network connection) is detected, at which time the "dispatcher" calls a Scheme "callback" function to handle the event (e.g., read and process input from the network connection).
This library has the actual TSION extensions and can be linked with any TinyScheme-based program (along with the CSOFT library mentioned below). Groups of functions can be left in or left out by calling or not calling the routines that register the functions:
#include "tsion.h" /* TinyScheme I/O Network functions. */ ... /* Create the Scheme engine. */ scheme sc = scheme_init_new (); /* Load the initialization file. */ FILE *file = fopen ("init.scm", "r") ; scheme_load_file (sc, file) ; fclose (file) ; /* Add the TSION extensions. */ addFuncsDRS (sc) ; addFuncsIOX (sc) ; addFuncsLFN (sc) ; addFuncsMISC (sc) ; addFuncsNET (sc) ; addFuncsREX (sc) ; addFuncsSKT (sc) ; addFuncsTCP (sc) ; ...
The TinyScheme code base and existing extensions focus on dynamic libraries. My library is static, but it's not that big. The size(1) command shows a text size of 60K bytes for tinyscheme versus 110K bytes for my tsion. If you're running on a machine that supports dynamic loading, I don't think you'll notice a shortage of memory. IMHO!
tsion (description and command-line invocation) is the basic stand-alone tinyscheme intepreter with network extensions.
tsiond (description and command-line invocation) is a network server that provides each client with its own tinyscheme interpreter with network extensions.
ECHOD (source) is an example of a brief, event-loop-based network server that simultaneously handles multiple clients. When a client connects to ECHOD, any data written to ECHOD is echoed back to the client.
ECHOLD (source), like ECHOD, is an example of a brief, event-loop-based network server that simultaneously handles multiple clients. When a client connects to ECHOLD, any data written to ECHOLD is echoed back to the client. Whereas ECHOD uses the TCP extensions to handle raw TCP/IP I/O, ECHOLD uses the LFN extensions to handle I/O on a line-by-line basis.
TinyScheme, easily downloaded from the
TinyScheme
website, is not so easily built. Source file scheme.c
doubles as the basis for the libraries and also for the main executable.
Furthermore, there is a single Makefile for all platforms and it can be
difficult to figure out how to tweak it for your target platform. To
make (no pun intended) life easier for you, here are some Makefiles for
different platforms. All of them create a separate tinyscheme.c
source file from scheme.c
and all of them install the distribution
into the /usr/local
directory tree.
- Makefile.linux - a starting point for any gcc-based platform.
- Makefile.solaris - identical to
Makefile.linux
.- Makefile.freebsd - doesn't need "-ldl" since the dynamic loading library has been merged into the C library.
- Makefile.cygwin - doesn't use TinyScheme's built-in strlwr() function.
See the Nintendo DS installation instructions
for information on building TinyScheme for the DS. There are a lot of
"switch(){}
" statements in "scheme.c
" without
catch-all "default: break ;
" statements, so the "-Wall" compiler
option in the Makefiles generates a lot of warning messages. You may
want to delete the "-Wall" option if the messages bother you - and to make it
easier to spot error messages!
On Windows with Visual C++ 6.0 or Visual Studio, place the following workspace/solution files in the main TinyScheme directory and the project files in subdirectories libtinyscheme and tinyscheme. (The Visual Studio files were converted to their Visual C++ 6.0 counterparts using Stephane Rodriguez's "VC++7 to VC++6 Project Converter". I no longer have Visual C++ 6.0 installed, so I can't vouch for the correctness of the conversion.)
- TinyScheme.sln - Visual Studio 2003 and later.
- libtinyscheme.vcproj
- tinyscheme.vcproj
- TinyScheme.dsw - Visual C++ 6.0.
- libtinyscheme.dsp
- tinyscheme.dsp
Remember, the project files go into subdirectories!
The source code for TSION (the library and the application) is included in my CSOFT distribution. Building the software is a simple matter:
libgpl
directory and run the appropriate Makefile. If you don't see an
appropriate Makefile, Makefile.linux
will usually work
for GCC-based builds. (Ignore the warning messages about "long long"s
coming out of the CORBA code and about "signedness" that might come
out of the networking code.)
libxdr
directory and run the appropriate Makefile
to build libxdr.
csoft
workspace or solution. Doing so will automatically
build both libgpl and libxdr.
tsion
directory and build everything
(libtsion.a, tsion, and
tsiond) using the appropriate Makefile.
tsion
workspace or solution.
In all cases, you might need to modify TSION's Makefiles or Visual C++/Studio
project files to point to where the TinyScheme header files and libraries
are found. The UNIX Makefiles assume the header files are in
"/usr/local/include/tinyscheme/
" and the libraries are in
"/usr/local/lib/
". The Windows project files assume the
TinyScheme header files are found in a TinyScheme source directory at the
same level as the csoft
directory; the TinyScheme library is
found somewhere below the libtinyscheme subdirectory (in
a Debug or Release subdirectory).
Before running TinyScheme or tsion or tsiond ,
you need to set environment variable TINYSCHEMEINIT to point to the TinyScheme
initialization file, "init.scm
". On the UNIX-based platforms,
I use "/usr/local/share/tinyscheme/init.scm
"; under Windows,
I use the "init.scm
" in TinyScheme's source code directory.
The CSOFT library and the TSION library and application are covered by the MIT License. (Also see the TinyScheme License.) Basically, you are free to use the software however you see fit, in commercial or non-commerical applications. I only ask that, if your time permits, you report any bugs or portability problems you encounter. Suggestions for improvements and enhancements are welcome, but I do not guarantee I will act upon them.
The NET group defines functions for translating IP addresses, host names, and service ports.
Source: funcs_net.c
(net-addr "host")
Lookup host and return its IP address as an integer in network-byte-order.
(net-host
IP-address [dotted?])
Lookup IP-address (an integer in network-byte-order) and return
the corresponding host name string. If dotted? is present and
#f
, the address is returned in dotted IP format; otherwise,
the host name is returned.
(net-port
"service" [udp?])
Lookup service in the network services database (the "/etc/services
" file) and return the corresponding port number. If udp? is present and#t
, the UDP port is returned; otherwise, the TCP port is returned.
The SKT group defines functions for monitoring sockets:
Source: funcs_skt.c
(skt-startup)
(skt-cleanup)
Startup and shutdown the socket library; return#t
upon success and#f
otherwise. These functions are not needed on most platforms.
(skt-peer fd)
Determine the host at the other end of network socket connection
fd and returns its IP address as an integer in
network-byte-order; #f
is returned in the event of an error.
(skt-port fd)
Get the number of the port to which socket fd is bound;
#f
is returned in the event of an error.
(skt-readable? fd)
(skt-up? fd)
(skt-writeable? fd)
Check ifReturn
- data is waiting to be read from socket fd,
- fd's network connection is still up, and
- data can be written to fd, respectively.
#t
if the predicate is true and#f
otherwise.
(skt-setbuf
fd recvSize sendSize)
Set the size of socket fd's receive buffer to recvSize bytes and the size of its send buffer to sendSize bytes. If a buffer size is less than zero, the respective buffer retains its current size. Return#t
if the buffer sizes were modified successfully and#f
otherwise.
The TCP group defines functions for establishing and communicating over TCP/IP network connections.
Source: funcs_tcp.c
(tcp-listen
"service"|port [backlog])
(tcp-answer
endpoint [timeout])
The first function creates a "listening" endpoint bound to the named service port at which the application will listen for connection requests from clients. (Alternatively, you may specify the port number directly.) At most backlog requests may be pending; if this argument is not specified, a platform-specific maximum is used. An opaque handle for the listening endpoint is returned for use in subsequent calls totcp-answer
;#f
is returned in the event of an error.
The second function,tcp-answer
, waits at most timeout seconds for a connection request to be received on the listening endpoint (previously returned bytcp-listen
). If a request is received, accept the request. The operating system automatically creates a new endpoint (the "data" endpoint) through which the server can talk to the client. An opaque handle is returned for the new data endpoint;#f
is returned in the event of an error.
(tcp-call
"service[@host]"|port
[noWait?])
(tcp-complete
endpoint [timeout [destroy?])
The first function,tcp-call
, requests a network connection to the server at "service[@host]". (Alternatively, you may specify a port number on the local host.) If the noWait? flag is not present or is#f
,tcp-call
waits until the connection is established (or refused) before returning. If the noWait? flag is#t
,tcp-call
initiates the connection attempt and returns immediately; the application should subsequently invoketcp-complete
to complete the connection. In all cases, an opaque handle for the data endpoint is returned;#f
is returned in the event of an error.
The second function, tcp-complete
, waits for an asynchronous,
network connection attempt to complete (if it is fated to complete).
The function will wait at most timeout seconds for the
call to complete. If this argument is not present or is negative,
tcp-complete
will wait as long as necessary. A timeout of
zero seconds causes an immediate return if the connection is not yet
established.
If the connection attempt times out or otherwise fails and destroy? is not present or is#t
, endpoint will automatically be destroyed. This mode is useful when the application plans to make a single go/no-go call totcp-complete
.
If, under the same circumstances, destroy? is#f
, endpoint will not be destroyed; the application is responsible for executingtcp-destroy
explicitly in the event of an error. This mode is useful when the application plans to periodically calltcp-complete
(perhaps with a timeout of zero) until the connection is successfully established.
If a connection is not (or not yet) successfully established,
#f
is returned.
(tcp-debug value)
Set the TCP/IP networking debug flag to value, an integer number. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.
(tcp-destroy endpoint)
Close a listening or data endpoint; endpoint should no longer be referenced.
(tcp-fd endpoint)
Get endpoint's socket; endpoint may be a listening
or a data endpoint. The socket is an integer; in the event of an error,
#f
is returned.
(tcp-name endpoint)
Return endpoint's name as a string. The name is in one of three formats:
- "
port
" - if endpoint is a listening point,- "
port#host
" - if endpoint is a server-side connection (i.e., created bytcp-answer
), or- "
port@host
" - if endpoint is a client-side connection (i.e., created bytcp-call
).
(tcp-pending? endpoint)
(tcp-readable? endpoint)
(tcp-up? endpoint)
(tcp-writeable? endpoint)
Check ifReturn
- any connection requests from potential clients are waiting to be answered on listening endpoint,
- data is waiting to be read from endpoint,
- endpoint's network connection is still up, and
- data can be written to endpoint, respectively.
#t
if the predicate is true and#f
otherwise.
(tcp-read
endpoint length [timeout])
Read length bytes of arbitrary data from endpoint into a string buffer and return the buffer to the caller. The data can be arbitrary binary data and can contain embedded NULs.
Because of the way network I/O works, a single record written to a
connection by one task may be read in multiple "chunks" by the task
at the other end of the connection. This is taken into account by
tcp-read
and, if you ask it for 100 bytes, it will
automatically perform however many network reads are necessary to
collect the 100 bytes.
If length is negative, tcp-read
returns after
reading the first "chunk" of input received; the number of bytes read
from that first "chunk" is limited to the absolute value of
length. The actual string of bytes read is returned to the
caller.
The function will wait at most timeout seconds for the first data to arrive. If timeout is not present or is negative,tcp-read
will wait as long as necessary to read the requested amount of data. A timeout of zero allows a read only if input is immediately available. If timeout is specified and is greater than zero,tcp-read
will return the amount of data actually read when timeout expires. Finally, in the event of an error,#f
is returned.
(tcp-write
endpoint string [timeout])
Write arbitrary data from a string to endpoint.
Because of the way network I/O works, attempting to output a given amount
of data to a network connection may require multiple network writers.
This is taken into account by tcp-write
and, if you ask it to
output 100 bytes, it will perform however many network writes are necessary
to output the full 100 bytes of data to the connection.
The funcction will wait at most timeout seconds for the data to be output. If this argument is not present or is negative,tcp-write
will wait as long as necessary to output all of the data. A zero timeout specifies no wait: if endpoint is not ready for writing,tcp-write
returns immediately. If the connection is ready for writing,tcp-write
returns after outputting whatever it can.
If timeout is present and positive,tcp-write
outputs whatever it can in the given time interval. In all cases, the number of bytes actually written is returned to the caller;#f
is returned in the event of an error.
The LFN group defines functions for sending and receiving carriage-return/line-feed (CR/LF)-terminated text over a network connection:
Source: funcs_lfn.c
(lfn-create
endpoint [options])
Create a LF-terminated network stream on top of the previously-created TCP/IP endpoint. The stream takes ownership of endpoint, which will automatically be destroyed when the stream is destroyed. The stream is returned as an opaque handle to the caller.
The optional options string contains zero or more of the following UNIX command line-style options:
- "
-input size
"- specifies the size of the stream's internal input buffer; the default is 2048 bytes. NOTE that this is only a limit on the input buffer, not on incoming strings.
- "
-output length
"- specifies the maximum output message size for the stream; the default is 2047 bytes.
(lfn-debug value)
Set the LF-terminated networking debug flag to value, an integer number. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.
(lfn-destroy stream)
Close LF-terminated network stream and its underlying TCP/IP endpoint; stream should no longer be referenced.
(lfn-fd stream)
Get stream's socket. The socket is an integer;
in the event of an error, #f
is returned.
(lfn-name stream)
Return stream's name as a string. The name is in one of two formats:
- "
port#host
" - if the stream's underlying TCP/IP endpoit is a server-side connection or- "
port@host
" - if the underlying endpoint is a client--side connection.
(lfn-readable? stream)
(lfn-up? stream)
(lfn-writeable? stream)
Check ifReturn
- data (either buffered or outstanding on the socket) is waiting to be read from stream,
- stream's network connection is still up, and
- data can be written to stream, respectively.
#t
if the predicate is true and#f
otherwise. NOTE that LF-terminated input is buffered, so an application must keep reading and processing lines of input untillfn-readable?
returns#f
.
(lfn-getline
stream [timeout])
Read the next CR/LF-delimited line of input from stream and
return the input as a string with the line terminators removed;
#f
is returned in the event of an error.
The function will wait at most timeout seconds for buffered or pending socket data to be available. If timeout is not present or is negative,lfn-getline
will wait as long as necessary to read the next line of input; a timeout of zero allows a read only if input is immediately available. If timeout is specified and is greater than zero,lfn-getline
will wait that many seconds for the first piece of data to become available. Once the first data arrives,lfn-getline
will take as long as necessary to read a full line of input, regardless of the timeout.
(lfn-putline
stream string
[crlf [timeout]])
Write a line of output, string, to stream;#t
is returned if the write is successful and#f
otherwise.
Optional bit mask crlf specifies line terminators to be appended to the output string: 0 = no terminator, 1 = LF only, 2 = CR only, and 3 = CR/LF. Zero (the default if this argument is not present) is typically used if the application explicitly puts the line terminators in the output string.
The funcction will wait at most timeout seconds to begin writing string. If this argument is not present or is negative,lfn-putline
will wait as long as necessary to output all of the data. A zero timeout specifies no wait: if stream is not ready for writing,lfn-putline
returns immediately. If the connection is ready for writing,lfn-putline
returns after writing the entire string.
If timeout is present and positive,lfn-putline
will wait that many seconds to begin writing string. Once output begins,lfn-putline
will continue to write the entire string, regardless of the timeout value.
(lfn-read
stream length [timeout])
Read length bytes of arbitrary data from stream into a string buffer and return the buffer to the caller. The data can be arbitrary binary data and can contain embedded NULs.
Because of the way network I/O works, a single record written to a
connection by one task may be read in multiple "chunks" by the task
at the other end of the connection. This is taken into account by
lfn-read
and, if you ask it for 100 bytes, it will
automatically perform however many network reads are necessary to
collect the 100 bytes.
If length is negative, lfn-read
returns after
reading the first "chunk" of input received; the number of bytes read
from that first "chunk" is limited to the absolute value of
length. The actual string of bytes read is returned to the
caller.
The function will wait at most timeout seconds for the first data to arrive. If timeout is not present or is negative,lfn-read
will wait as long as necessary to read the requested amount of data. A timeout of zero allows a read only if input is immediately available. If timeout is specified and is greater than zero,lfn-read
will return the amount of data actually read when timeout expires. Finally, in the event of an error,#f
is returned.
(lfn-write
stream string [timeout])
Write arbitrary data from string to stream.
Because of the way network I/O works, attempting to output a given amount
of data to a network connection may require multiple network writers.
This is taken into account by lfn-write
and, if you ask it to
output 100 bytes, it will perform however many network writes are necessary
to output the full 100 bytes of data to the connection.
The funcction will wait at most timeout seconds for the data to be output. If this argument is not present or is negative,lfn-write
will wait as long as necessary to output all of the data. A zero timeout specifies no wait: if stream is not ready for writing,lfn-write
returns immediately. If the connection is ready for writing,lfn-write
returns after outputting whatever it can.
If timeout is present and positive,lfn-write
outputs whatever it can in the given time interval. In all cases, the number of bytes actually written is returned to the caller;#f
is returned in the event of an error.
The IOX group defines functions for monitoring and responding to network I/O events.
There are 4 functions - iox-after
, iox-every
,
iox-onio
, and iox-whenidle
- used to register
"callbacks" in response to different types of events. When a monitored event
occurs, the registered callback function is executed with three arguments:
(function callback userData reason)
where callback is the handle returned when the callback was registered, userData is arbitrary data supplied by the application when the callback was registered, and reason is a bit mask specifying the reason(s) for the callback (0x1=readable, 0x2=writeable, 0x4=OOB, 0x8=timer, 0x10=idle). Constants are predefined for the reasons:
IOX_READ
- socket is readable.IOX_WRITE
- socket is writeable.IOX_EXCEPT
- socket has out-of-bound input available for reading.IOX_IO
- the bit-wise OR of the three conditions above.IOX_FIRE
- timer has fired.IOX_IDLE
- dispatcher is idle.IOX_CANCEL
- callback is canceled.
Source: funcs_iox.c
(iox-create)
Create an I/O event dispatcher. An opaque handle is returned for the
dispatcher; #f
is returned in the event of an error.
(iox-debug value)
Set the I/O event dispatcher debug flag to value, an integer number. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.
(iox-destroy dispatcher)
Invoke each of dispatcher's registered callbacks with reason
IOX_CANCEL
and then destroy the dispatcher.
(iox-monitor
dispatcher [timeout])
Monitor and dispatch I/O events, timers, and idle tasks for timeout seconds using dispatcher. If the timeout argument is not present or is less than zero, the dispatcher will monitor events forever. When the timeout interval is complete,iox-monitor
returns#t
. In the event of an error (usually no more events to monitor),#f
is returned.
(iox-after dispatcher function
userData delay)
Register a single-shot timer of delay seconds duration with dispatcher. The timer interval can include a fractional number of seconds; e.g., 2.75 seconds. An opaque handle for the registered callback is returned to the caller and can be used to cancel the callback withiox-cancel
before the timer fires. When delay seconds have elapsed, function is called with 3 arguments: the callback handle, the application-supplied userData, and the reason (IOX_FIRE
) the callback is being invoked. After being invoked, the single-shot timer is automatically canceled.
(iox-every dispatcher function
userData delay interval)
Register a periodic timer with dispatcher. The timer fires
after an initial delay number of seconds and then every
interval seconds after that. The time durations can include
fractional numbers of seconds; e.g., 2.75 seconds. An opaque handle for
the registered callback is returned to the caller and can be used to
cancel the callback with iox-cancel
when the timer is no
longer needed.
When the timer fires, function is called with 3 arguments: the callback handle, the application-supplied userData, and the reason (IOX_FIRE
) the callback is being invoked. To stop the timer, it must be explicitly canceled by callingiox-cancel
.
(iox-onio dispatcher function
userData reason fd)
Register I/O file descriptor fd with dispatcher. Mask reason is the bit-wise OR of the types of I/O events to monitor:IOX_READ
for input-pending,IOX_WRITE
for output-ready, andIOX_EXCEPT
for OOB-input-pending. An opaque handle for the registered callback is returned to the caller and can be used to cancel the callback withiox-cancel
.
When an event of the monitored types is detected on the I/O source, function is called with 3 arguments: the callback handle, the application-supplied userData, and the reason (IOX_READ
,IOX_WRITE
, orIOX_EXCEPT
) the callback is being invoked.
To register a callback for a TCP/IP listening socket (created bytcp-listen
), specifyIOX_READ
as the event type to be monitored. When a connection request is received from a client, the listening socket becomes readable. The callback should then executetcp-answer
to accept the connection request.
(iox-whenidle dispatcher
function userData)
Register an idle task with dispatcher. An opaque handle for the registered callback is returned to the caller and can be used to cancel the callback withiox-cancel
. When the dispatcher is idle (i.e., no I/O or timers immediately pending), function is called with 3 arguments: the callback handle, the application-supplied userData, and the reason (IOX_IDLE
) the callback is being invoked. After function completes, dispatcher re-queues the idle task for later processing. The application is responsible for explicitly canceling the callback usingiox-cancel
.
(iox-cancel callback)
Cancel callback, where callback is the opaque handle returned when the callback was registered. The status of canceling the callback,#t
or#f
, is returned to the caller.
(iox-dispatcher callback)
Get callback's dispatcher, where callback is the opaque handle returned when the callback was registered. This capability is useful when a callback needs to access its dispatcher. For example, a callback that answers a network connection request may wish to register an I/O callback for the new data connection.
The DRS group consists of functions used to scan lists of files in directories.
Source: funcs_drs.c
(drs-create "pathname")
Create a directory scan for the directory specified in pathname. The pathname must contain wildcard characters for the files in the directory, "*" at a minimum. If the scan is successfully created, an opaque handle is returned for use in other DRS functions; #f is returned in the event of an error.
(drs-destroy scan)
Destroy the specified directory scan.
(drs-first scan)
Get the first matching file in a directory scan. The file's full pathname is returned as a string; #f is returned if there are no matching files.
(drs-next scan)
Get the next matching file in a directory scan. The file's full pathname is returned as a string; #f is returned if there are no more matching files.
(drs-count scan)
Get the number of files in a directory scan that matched the wildcard file specification supplied to DRS-CREATE.
(drs-get scan index)
Get the indexed, index, matching file in a directory scan. Indices are numbered from 1 to the value returned by DRS-COUNT. The file's full pathname is returned as a string; #f is returned if the index is out of range. Getting a file name by index does not affect the sequence of file names returned by DRS-FIRST and DRS-NEXT.
The REX group is a collection of functions for matching and replacing patterns of text using regular expressions. The underlying regular expression package (REX_UTIL) used to implement the Scheme functions was written circa 1990, before the advent of POSIX and Perl regular expressions. Consequently, the syntax for matching expressions and replacing text is slightly different than what you might expect; for example, subexpressions are explicitly labeled in regular expressions and don't require you to parse parentheses. Different, but in a sensibly consistent way. (And portable to a variety of operating systems and platforms.)
Source: funcs_rex.c
(rex-create "regexp")
Compile a regular expression into a form suitable for matching with
REX-MATCH and REX-REPLACE. An opaque handle is returned for the
compiled pattern; #f
is returned in the event of an error.
See LIBGPL's REX_UTIL package for the syntax of regular expressions recognized by REX-CREATE.
(rex-debug value)
Set the regular expression debug flag to value, an integer number. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.
(rex-destroy pattern)
Destroy compiled regular expression pattern.
(rex-error)
Get more error information after REX-CREATE fails to compile a regular expression. The information is returned as a string; #f is returned if there is no error information.
(rex-match
pattern "text")
Attempt to match compiled regular expression pattern in target string text. If the match is successful, a Scheme list is returned whose first element is the entire string of text matched by the regular expression and whose remaining elements are the strings matched by the subexpresions ("$n"), if any, in the regular expression:
("full match" "subexp0" "subexp1" ...))
If no match is found, #f
is returned.
(rex-replace
pattern "text"
"replacement" global?)
Perform a search-and-replace operation on string text.
The search string (specified by previously-compiled regular
expression pattern) is located in the source string and
replaced by the substitution text, replacement. This
process may be done once or, if global? is #t
,
repeatedly throughout the whole string. REX-REPLACE is intended to
perform ex(1)-style subsitutions on a line of text:
s/regexp/replacement/[g]
REX-REPLACE returns a Scheme pair whose car is the new text after substitutions have been made and whose cdr is the number of substitutions that were made:
("newText" . numSubstitutions)
If no substitutions were made, REX-REPLACE returns the old text and zero for the number of substitutions.
See LIBGPL's REX_UTIL package for the special character sequences used to control the replacement process; e.g., inserting matched subexpressions, etc.
The MISC group is a miscellaneous collection of unrelated functions.
Source: funcs_misc.c
(getenv "name")
Get the value of environment variable name. The value is
returned as a string to the caller. If the environment variable is
not defined, then #f
is returned.
(grab value)
This function stores a pointer to value internally for use by C code. The function is not especially useful otherwise and simply returns its input, value.
(tv-tod)
Return the current time of day (GMT) as a pair consisting of the number of seconds and microseconds since the start of January 1, 1970.