Gauche supports most of POSIX.1 functions and other system functions popular among Unix variants as built-in procedures.
Lots of Scheme implementations provide some sort of system interface
under various APIs. Some are just called by different names
(e.g, delete-file
or remove-file
or unlink
to delete
a file), some do more abstraction introducing new Scheme objects.
Instead of just picking one of such interfaces, I decided to implement
Gauche’s system interface API in two layers; the lower level layer,
described in this section, follows the operating system’s API
as close as possible. On top of that, the higher-level APIs are
provided, with considering compatibility to the existing systems.
The low level system interface has the name sys-
name
and usually correspond to the system call name.
I tried to keep the interface similar whenever reasonable.
Gauche restarts a system call after it is interrupted by a signal by default. See Signal for the details.
If you are familiar with system programming in C, see also C to Scheme mapping, which shows correspondence between C standard library functions and Gauche procedures.
• Program termination: | ||
• Command-line arguments: | ||
• Environment inquiry: | ||
• Filesystems: | ||
• Unix groups and users: | ||
• Locale: | ||
• Signal: | ||
• System inquiry: | ||
• Time: | ||
• Process management: | ||
• I/O multiplexing: | ||
• Garbage collection: | ||
• Memory mapping: | ||
• Miscellaneous system calls: |
Gauche has a few ways to terminate itself (other than returning
from main
). The exit
procedure is a graceful way
with all proper cleanups. sys-exit
and sys-abort
may be used in emergency where proper cleanup is impossible.
[R7RS+ process-context]
Terminates the current process with the exit code code.
The optional code argument specifies the exit status; #t
indicates a success (exit code 0),
#f
indicates a failure (exit code 1),
and an exact integer specifies other exit code (only the lower 8 bits are
used). Any other values of code makes the exit code to be
70 (EX_SOFTWARE
.
Note that R7RS does not specify how code is translated to OS’s
exit status, except that #t
indicates a success and #f
indicates a failure. Portable code should only pass #t
or #f
.
When a string is given to fmtstr, it is passed to
format
(see Output), with the rest arguments args,
to produce a message to the standard error port
(not the current error port; see Common port operations).
In fact, the exiting procedure is a bit more complicated. The precise steps of exiting is as follow.
exit-handler
is checked.
If it is not #f
, the value is called as a procedure
with three arguments: code, fmtstr, and a list of rest
arguments. It is the default procedure of exit-handler
that prints out the message to the standard error port.
If an error occurs within exit handler, it is captured and
discarded. Other exceptions are not caught.
Scm_AddCleanupHandler
are invoked. These are usually responsible for under-the-hood cleanup
jobs for each application that embeds Gauche. From the Scheme world
there’s not much to care.
exit(3)
.
The exit-handler
mechanism allows the application to hook its
exit operation. Note that it is not for simple cleanup jobs;
dynamic-wind
, guard
or unwind-protect
are more appropriate.
exit-handler
is for more specific use just upon application exit.
For example, GUI applications may want to post a dialog
instead of printing to stderr.
For this reason, the library code shouldn’t change exit-handler
;
only the application knows what to do when it exits.
Another useful case is when you
want to call a third-party code which calls exit
inside. In
that case you may swap the exit-handler
for the one
that raises a non-error exception while calling the third-party code.
Non-error exception isn’t caught in exit
, effectively
interrupts the steps explained above. (Yet the after thunks
of dynamic handlers are processed just like normal exception
handling case.)
Your application code can then capture the exception.
You can use parameterize
to swap exit-handler
dynamically
and thread-safely (see Parameters).
(guard (e [(eq? e 'exit-called) (handle-exit-as-desired)]) (parameterize ((exit-handler (lambda (c f a) (raise 'exit-called)))) (call-third-party-library)))
Generally, calling exit
while other threads are running
should be avoided, since it only rewinds the dynamic handlers active
in the calling threads, and other threads will be killed abruptly.
If you have to do so for some reason,
you may be able to use exit-handler
to tell to other threads
that the application is exiting. (There’s no general way, and
Gauche doesn’t even have a list of all running threads; it’s application’s
responsibility).
Note on design: Some languages integrates exit handling
into exception handling, treating exit as a kind of exception.
It is a tempting idea, so much that we’ve tried it. It didn’t
work out well in Gauche; a big annoyance was that when
an after thunk raised an exception during
rewinding dynamic-wind
s, it shadowed the original
exit exception.
A parameter that holds an exit handler, a procedure to be called
when exit
is called. It takes three arguments,
the exit code, the format string and the list of arguments for the format
string. See exit
above for the details.
Its value can also be #f
, in that case, no handler will
be called.
The default handler shows the formatted message to the standard error port.
If the handler raises an error, it is captured and discarded. If the handler raises other conditions, it won’t be captured and propagate to outer controls.
[POSIX]
Terminates the current process with the exit code code.
If code is #t
, the exit code is 0;
if it is #f
, the exit code is 1;
if it is an exact integer, its lower 8 bits is used for the
exit code. If code is any other value,
exit code is 70 (EX_SOFTWARE
).
(This is the same as exit
).
This procedure calls _exit(2)
directly.
No cleanup is done. Unflushed file output is discarded.
[POSIX] Calls POSIX abort(). This usually terminates the running process and dumps core. No cleanup is done.
The recommended way to get command-line arguments passed to a
Scheme script is the argument to the main
procedure
(see Writing Scheme scripts). For the convenience,
there are a few ways to access to the command-line arguments
globally.
Note that a Scheme code may not always be called with a command-line
argument—for example, an application-embedded Scheme scriptlet may
not have the concept of command-line at all. That’s why the main
argument is preferred, since it is an explicit interface; if main
is called, the caller is responsible to pass in something.
That said, here are how to access the command-line arguments:
[R7RS+ process-context][SRFI-193] When called without arguments, it returns a list of command-line arguments, including the program name in the first element, as a list of strings.
When Gauche is used as an embedded language, it is application’s discretion to set up this parameter. If the application does nothing, this parameter will have an empty list. When you use this parameter in the library you have to deal with that situation.
When called with one argument, a list of string, it will become the
new value of the parameter. You can use parameterize
to
switch the value of command-line
dynamically
(see Parameters). Note that R7RS only defines zero-argument
command-line
.
[SRFI-193]
While a Scheme program is run as a script, this parameter holds
the absolute path of the Scheme source file being run. Run as a script
means either it is passed as the script file to gosh
, or
the file is directly load
ed from the toplevel REPL.
If this function is called from the context outside of script execution,
#f
is returned.
Deprecated.
These variables are bound to the program name and the list of command-line
arguments, respectively. In Gauche scripts that are invoked by gosh
command, *program-name*
is usually the name of the script, as
given to gosh
. When gosh
is invoked interactively,
*program-name*
contains a zero-length string ""
,
and *argv*
is an empty list.
These variables exist in user
module.
They are mainly kept for the backward compatibility.
These names are compatible to STk, but other Scheme implementation uses
different conventions. The command-line
parameter above is
preferred.
When Gauche is used as an embedded language, it’s the host application’s discretion to set up these variables. Generally, you can’t count on those variables to exist. That’s another reason you should avoid using them.
[POSIX]
Returns the value of the environment variable name as a string,
or #f
if the environment variable is not defined.
For the portable code, you may want to use SRFI-98’s
get-environment-variable
(see srfi.98
- Accessing environment variables),
which is also in R7RS.
Note: Most systems doesn’t guarantee thread-safety of getenv
while
environment is being modified; however, Gauche mutexes environment
accessing/mutating APIs internally, so you don’t need to worry
about the race condition as far as you use Gauche procedures.
Returns the current environment as a list of strings. Each string
is a form of NAME=VALUE
, where NAME
is the name of
the environment variable and VALUE
is its value. NAME
never contains a character #\=
. This is useful when you want
to obtain the all environment variables of the current process.
Use sys-getenv
if you want to query a specific environment
variable.
A convenience procedure for sys-environ
. When the list of
environment strings (like what sys-environ
returns) is given
to envlist, this procedure splits name and value of
each environment variable and returns an assoc list.
When envlist is omitted, this procedure calls sys-environ
to get the current environment variables.
For the portable code, you may want to use SRFI-98’s
get-environment-variables
(see srfi.98
- Accessing environment variables),
which is also in R7RS.
(sys-environ->alist '("A=B" "C=D=E")) => (("A" . "B") ("C" . "D=E"))
sys-setenv inserts an environment variable name with
the value value.
Both name and value must be a string.
If the optional argument overwrite is #f
(default),
the environment is untouched if a variable with name already
exists. If overwrite is true, the variable is overwritten.
For sys-putenv
, you have to give a single string
with the form of NAME=VALUE
, that is, concatenating name
and value with #\=
. If the environment variable with
the same name exists, it will be overwritten.
These API reflects POSIX setenv(3)
and putenv(3)
.
However, unlike putenv(3)
, modifying the string passed
to sys-putenv
afterwards won’t affect the environment.
These procedures are only available when a feature identifier
gauche.sys.setenv
exists. Use cond-expand
(see Feature conditional) to check their availability.
(cond-expand [gauche.sys.setenv ... use sys-setenv or sys-putenv ... ] [else ... fallback code ...])
These procedures are thread-safe as far as you access and modify the environment through Gauche API.
Remove the environment variable with name (sys-unsetenv
),
or all environment variables. sys-clearenv
is handy
when you need to run subprocess, but you cannot trust the inherited
environment.
These procedures are only available when a feature identifier
gauche.sys.unsetenv
exists. Use cond-expand
(see Feature conditional) to check their availability.
(cond-expand [gauche.sys.unsetenv ... use sys-unsetenv or sys-clearenv ... ] [else ... fallback code ...])
SRFI-98 (see srfi.98
- Accessing environment variables) also defines
a subset of above procedures to access to the environment variables.
Portable programs may want to use them instead.
These functions returns a string that tells information about Gauche runtime itself.
[SRFI-176]
Returns an alist of various runtime information.
The information is the same as what displayed with gosh -V
.
The result is affected by the value of the environemnt variable
GAUCHE_VERSION_INFO_EXCLUSION
. See Environment variables,
for details.
Returns the number of available processors on the running platform. Return value is always a positive exact integer. If Gauche can’t get the information, 1 is returned.
However,
If an environment variable GAUCHE_AVAILABLE_PROCESSORS
is
defined and its value can be interpreted as a positive integer,
then the value is returned regardless of what the hardware/OS tells.
System calls that deal with filesystems.
See also file.util
- Filesystem utilities, which defines high-level APIs
on top of the procedures described here.
• Directories: | ||
• Directory manipulation: | ||
• Pathnames: | ||
• File stats: | ||
• Other file operations: |
See also Directory utilities for high-level API.
path must be a string that denotes valid pathname of an existing directory. This function returns a list of strings of the directory entries. The returned list is not sorted. An error is signaled if path doesn’t exists or is not a directory.
Provides a traditional Unix glob(3) functionality; returns a list of pathnames that matches the given pattern.
This feature used to be a wrapper of system-provided glob
function,
hence it was named sys-glob
. However, as of Gauche version 0.8.12,
it was reimplemented in Scheme on top of other system calls, to overcome
incompatibilities between platforms and for the opportunity to put
more functionalities. So we renamed it glob
.
The old name sys-glob
is kept for compatibility, but new
programs should use glob
.
The pattern argument may be a single glob pattern, or a list of glob patterns. If a list is given, pathnames that matches any one of the pattern are returned. If you’re a unix user, you already know how it works.
gosh> (glob "*.scm") ("ext.scm" "test.scm") gosh> (glob "src/*.[ch]") ("src/ext.c" "src/ext.h") gosh> (glob '("*.scm" "src/*.c")) ("ext.scm" "src/ext.c" "test.scm")
Unlike shell’s glob, if there’s no matching pathnames, ()
is returned.
By default, the result is sorted using built-in sort
procedure
(see Sorting and merging). You can pass alternative procedure
to sorter argument; it should be a procedure that takes single
list, and returns a sorted list. It can also be #f
, in which
case the result isn’t sorted at all.
In fact, globbing is a very useful tool to search hierarchical
data structure in general, not limited to the filesystems.
So the glob
function is implemented separately from
the filesystem. Using keyword arguments,
you can glob from any kind of tree data structure.
It is just that their default values are set to look at
the filesystems.
The separator argument should be a char-set, and used
to split the pattern into components. Its default is
#[/]
. It is not used to the actual pathnames to match.
The folder is a procedure that walks through the data structure. It is called with five arguments:
(folder proc seed parent regexp non-leaf?)
proc is a procedure that takes two arguments. The folder
should call proc with every node in the parent whose
component name matches regexp, passing around the seed value
just like fold
. It should return the final value returned
by proc. For example, if cons
is given to proc
and ()
is given to seed, the return value of the folder
is a list of nodes that matches the regexp.
The representation of a node is up to the implementation of
folder. It can be a
pathname, or some sort of objects, or anything. The glob
procedure does not care what it is; the glob
procedure
merely passes the node to subsequent call to folder
as
parent argument, or returns a list of nodes as the result.
The parent argument is basically a node, and
folder traverses its children to find the match.
The exception is the initial call of folder—
at the beginning glob
knows nothing about each node.
When glob
needs to match an absolute path, it
passes #t
, and when glob
needs to match a relative path,
it passes #f
, as the initial parent value.
The regexp argument is used to filter the child nodes.
It should be matched against the component name of the child,
not including its directory names. As a special case, it can
be a symbol dir?
; if that’s the case, the folder should
return node itself, but it may indicate node
as a directory; e.g. if node is represented as a pathname,
the folder returns a pathname with trailing directory separator.
As special cases,
if node is a boolean value and regexp is dir?
,
the folder should return the node representing root node or
current node, respectively; e.g. if node is represented
as a pathname, the folder may return "/"
and "./"
for those cases.
The non-leaf argument is a boolean flag. If it is true, the filter should omit the leaf nodes from the result (e.g. only include the directories).
Now, here’s the precise spec of glob pattern matching.
Each glob pattern is a string to match pathname-like strings.
A pathname-like string is a string consists of one or more
components, separated by separators.
The default separator is #[/]
; you can change it
with separator keyword argument.
A component cannot contain separators, and cannot
be a null string. Consecutive separators are
regarded as a single separator. A pathname-like
string optionally begins with, and/or ends with a separator character.
A glob pattern also consists of components and separator characters. In a component, following characters/syntax have special meanings.
*
When it appears at the beginning of a component, it matches
zero or more characters except a period (.
). And it
won’t match if the component of the input string begins with
a period.
Otherwise, it matches zero or more sequence of any characters.
**
If a component is just **
, it matches zero or more
number of components that match *
. For example, src/**/*.h
matches all of the following patterns.
src/*.h src/*/*.h src/*/*/*.h src/*/*/*/*.h ...
?
When it appears at the beginning of a component, it matches
a character except a period (.
). Otherwise, it matches
any single character.
[chars]
Specifies a character set. Matches any one of the set.
The syntax of chars is the same as Gauche’s character set
syntax (see Character Sets). For the compatibility of the
traditional glob, the !
character can be used to complement
the character set, e.g. [!abc]
is the same as [^abc]
.
\
Include the next character literally in the pattern. This can be used to include above special characters in the pattern.
This is actually a low-level construct of the glob function. Actually, glob is simply written like this:
(define (glob patterns . opts) (apply glob-fold patterns cons '() opts))
The meaning of pattern, separator, folder and sorter is the same as explained above.
For each pathname that matches pattern, glob-fold
calls proc with the pathname and a seed value. The initial
seed value is seed, and the value proc returns becomes
the next seed value. The result of the last call to proc
becomes the result of glob-fold
. If there’s no matching
pathnames, proc is never called and seed is returned.
This is a utility function to generate a procedure suitable to
pass the folder keyword argument of glob-fold
and glob
.
Without arguments, this returns the same procedure which is used
in glob-fold
and glob
by default.
The keyword arguments root-path and current-path specify
the paths where glob-fold
starts to search.
gosh> (glob "/tmp/*.scm") ("/tmp/x.scm" "/tmp/y.scm") gosh> (glob "/*.scm" :folder (make-glob-fs-fold :root-path "/tmp")) ("/tmp/x.scm" "/tmp/y.scm") gosh> (glob "*.scm" :folder (make-glob-fs-fold :current-path "/tmp")) ("/tmp/x.scm" "/tmp/y.scm")
See File stats, to check if a path is actually a directory.
[POSIX] If filename is a file it is removed. On some systems this may also work on an empty directory, but portable scripts shouldn’t depend on it.
[POSIX] Renames a file old to new. The new name can be in different directory from the old name, but both paths must be on the same device.
[POSIX]
Creates a file name which is supposedly unique, and returns it.
This is in POSIX, but its use is discouraged because of potential
security risk. Use sys-mkstemp
below if possible.
Creates and opens a file that has unique name, and returns two values; opened port and the created filename. The file is created exclusively, avoiding race conditions. template is used as the prefix of the file. Unlike Unix’s mkstemp, you don’t need padding characters. The file is opened for writing, and its permission is set to 600.
Creates a directory that has unique name, and returns the name. template is used as the prefix of the directory. Unlike Unix’s mkdtemp, you don’t need padding characters. The directory’s permission is set to 700.
[POSIX] Creates a hard link named new to the existing file existing.
[POSIX]
Removes pathname. It can’t be a directory.
Returns #t
if it is successfully removed, or
#f
if pathname doesn’t exist.
An error is signaled otherwise.
There are similar procedures, delete-file
/remove-file
in file.util
module, while they raises an error when the
named pathname doesn’t exist (see File operations).
R7RS defines delete-file
, which you may want to use in portable
programs.
Creates a symbolic link named new to the pathname existing. On systems that doesn’t support symbolic links, this function is unbound.
If a file specified by path is a symbolic link, its content is returned. If path doesn’t exist or is not a symbolic link, an error is signaled. On systems that don’t support symbolic links, this function is unbound.
[POSIX]
Makes a directory pathname with mode mode.
(Note that mode is masked by the current umask;
see sys-umask
below).
The parent directory of pathname must exist and be writable
by the process. To create intermediate directories at once, use
make-directory*
in file.util
(Directory utilities).
[POSIX]
Removes a directory pathname. The directory must be empty.
To remove a directory with its contents, use remove-directory*
in file.util
(Directory utilities).
[POSIX]
Sets umask setting to mode. Returns previous umask setting.
If mode is omitted or #f
, just returns the current umask without
changing it.
See man umask
for more details.
See also Pathname utilities, for high-level APIs.
Converts pathname according to the way specified by keyword arguments. More than one keyword argument can be specified.
absolute
If this keyword argument is given and true, and pathname is not an absolute pathname, it is converted to an absolute pathname by appending the current working directory in front of pathname.
expand
If this keyword argument is given and true, and pathname begins
with ‘~
’, it is expanded as follows:
~
”, or begins
with “~/
”, then the character “~
” is replaced
for the pathname of the current user’s home directory.
~
’ until either ‘/
’ or
the end of pathname are taken as a user name, and the user’s
home directory is replaced in place of it. If there’s no such
user, an error is signaled.
canonicalize
Tries to remove pathname components “.
” and “..
”.
The pathname interpretation is done purely in textural level, i.e.
it doesn’t access filesystem to see the conversion reflects the
real files. It may be a problem if there’s a symbolic links to
other directory in the path.
sys-basename
returns a basename, that is the last component of
pathname. sys-dirname
returns the components of pathname
but the last one. If pathname has a trailing ‘/
’,
it is simply ignored.
(sys-basename "foo/bar/bar.z") ⇒ "bar.z" (sys-basename "coo.scm") ⇒ "coo.scm" (sys-basename "x/y/") ⇒ "y" (sys-dirname "foo/bar/bar.z") ⇒ "foo/bar" (sys-dirname "coo.scm") ⇒ "." (sys-dirname "x/y/") ⇒ "x"
These functions doesn’t check if pathname really exists.
Some boundary cases:
(sys-basename "") ⇒ "" (sys-dirname "") ⇒ "." (sys-basename "/") ⇒ "" (sys-dirname "/") ⇒ "/"
Note: The above behavior is the same as Perl’s basename
and
dirname
. On some systems, the command basename
may return "/"
for the argument "/"
, and
"."
for the argument "."
.
sys-realpath
returns an absolute pathname of pathname
that does not include “.
”, “..
” or symbolic links.
If pathname does not exist, it includes a dangling symbolic
link, or the caller doesn’t have enough permission to access to
the path, an error is signaled.
Note: the POSIX realpath(3)
function is known to be unsafe, so
Gauche avoids using it and implements sys-realpath
in its own.
Returns the default directory name suitable to put temporary files.
On Unix-like systems, the environment variable TMPDIR
and TMP
are first checked, then falls back to /tmp
.
On Windows-native systems, it uses GetTempPath
Windows API.
It checks environment variables TMP
, TEMP
, and
USERPROFILE
in this order, and falls back to Windows system
directory.
On both platforms, the returned pathname may not exist, or may not be writable by the calling process.
In general, user programs and libraries are recommended to use
temporary-directory
(see Directory utilities) instead;
sys-tmpdir
should be used only
if you now the raw value the platform provides.
See also File attribute utilities, for high-level APIs.
[R7RS file] Returns true if path exists.
Returns true if path is a regular file, or is a directory, respectively. They return false if path doesn’t exist at all.
An object that represents struct stat
, attributes of an
entry in the filesystem. It has the following read-only slots.
<sys-stat>
: type ¶A symbol represents the type of the file.
regular | a regular file |
directory | a directory |
character | a character device |
block | a block device |
fifo | a fifo |
symlink | a symbolic link |
socket | a socket |
If the file type is none of the above, #f
is returned.
Note: Some operating systems don’t have the socket
file type
and returns fifo
for socket files. Portable programs should
check both possibilities to see if the given file is a socket.
<sys-stat>
: perm ¶An exact integer for permission bits of struct stat
.
It is the same as lower 9-bits of "mode" slot; provided for the convenience.
<sys-stat>
: mode ¶<sys-stat>
: ino ¶<sys-stat>
: dev ¶<sys-stat>
: rdev ¶<sys-stat>
: nlink ¶<sys-stat>
: uid ¶<sys-stat>
: gid ¶<sys-stat>
: size ¶An exact integer for those information of struct stat
.
[POSIX]
Returns a <sys-stat>
object of path, or
the underlying file of port-or-fd, which
may be a port or a positive exact integer file descriptor, respectively.
If path is a symbolic link, a stat of the file the link points
to is returned from sys-stat
.
If port-or-fd is not associated to a file, sys-fstat
returns
#f
.
Like sys-stat
, but it returns a stat of a symbolic link
if path is a symbolic link.
gosh> (describe (sys-stat "gauche.h")) #<<sys-stat> 0x815af70> is an instance of class <sys-stat> slots: type : regular perm : 420 mode : 33188 ino : 845140 dev : 774 rdev : 0 nlink : 1 uid : 400 gid : 100 size : 79549 atime : 1020155914 mtime : 1020152005 ctime : 1020152005
Deprecated.
Use slot-ref
to access information of <sys-stat>
object.
[POSIX] Returns a boolean value of indicating whether access of pathname is allowed in amode. This procedure signals an error if used in a suid/sgid program (see the note below). amode can be a combinations (logical or) of following predefined flags.
R_OK
¶Checks whether pathname is readable by the current user.
W_OK
¶Checks whether pathname is writable by the current user.
X_OK
¶Checks whether pathname is executable (or searchable in case pathname is a directory) by the current user.
F_OK
¶Checks whether pathname exists or not, regardless of the access permissions of pathname. (But you need to have access permissions of the directories containing pathname).
Note: Access(2) is known to be a security hole if used in suid/sgid program to check the real user’s privilege of accessing the file.
Change the mode of the file named path or an opened file specified by port-or-fd to mode. mode must be a small positive integer whose lower 9 bits specifies POSIX style permission.
Change the owner and/or group of the file named path to owner-id and group-id respectively. owner-id and group-id must be an exact integer. If either of them is -1, the corresponding ownership is not changed.
Change the file’s access time and modification time to atime
and mtime, respectively. The arguments can be either #f
(indicating the current time), #t
(do not change),
a real numebr (number of seconds from Epoch),
or <time>
object (See Time).
See also touch-file
(see File operations).
[POSIX]
An interface to chdir(2)
.
See also current-directory
(see Directory utilities).
[POSIX] Creates a pipe, and returns two ports. The first returned port is an input port and the second is an output port. The data put to the output port can be read from the input port.
Buffering can be :full
, :line
or :none
,
and specifies the buffering mode of the ports opened on the pipe.
See File ports, for details of the buffering mode.
The default mode is sufficient for typical cases.
(receive (in out) (sys-pipe) (display "abc\n" out) (flush out) (read-line in)) ⇒ "abc"
Note: the returned value is changed from version 0.3.15, in which
sys-pipe
returned a list of two ports.
[POSIX] creates a fifo (named pipe) with a name path and mode mode. Mode must be a positive exact integer to represent the file mode.
[POSIX] port-or-fd may be a port or an integer file descriptor.
Returns #t
if the port is connected to the console, #f
otherwise.
[POSIX] port-or-fd may be a port or an integer file descriptor.
Returns the name of the terminal connected to the port,
or #f
if the port is not connected to a terminal.
[POSIX] Truncates a regular file named by path or referenced by port-or-fd to a size of length bytes. If the file is larger than length bytes, the extra data is discarded. If the file is smaller than that, zero is padded.
Unix group information. Has following slots.
<sys-group>
: name ¶Group name.
<sys-group>
: gid ¶Group id.
<sys-group>
: passwd ¶Group password.
<sys-group>
: mem ¶List of user names who are in this group.
[POSIX]
Returns <sys-group>
object from an integer group id gid
or a group name name, respectively.
If the specified group doesn’t exist, #f
is returned.
Convenience function to convert between group id and group name.
Unix user information. Has following slots.
<sys-passwd>
: name ¶User name.
<sys-passwd>
: uid ¶User ID.
<sys-passwd>
: gid ¶User’s primary group id.
<sys-passwd>
: passwd ¶User’s (encrypted) password. If the system uses the shadow password file, you just get obscure string like "x".
<sys-passwd>
: gecos ¶Gecos field.
<sys-passwd>
: dir ¶User’s home directory.
<sys-passwd>
: shell ¶User’s login shell.
<sys-passwd>
: class ¶User’s class (only available on some systems).
[POSIX]
Returns <sys-passwd>
object from an integer user id uid
or a user name name, respectively.
If the specified user doesn’t exist, #f
is returned.
Convenience functions to convert between user id and user name.
This is the interface to crypt(3)
. Key and salt
must be a string, and an encrypted string is returned.
On systems where crypt(3)
is not available, call to this
function signals an error.
This routine is only for the code that needs to check password
against the system’s password database.
If you are building user database on your own, you must use
crypt.bcrypt
module (see crypt.bcrypt
- Password hashing) instead of
this routine.
[POSIX]
Sets/gets the locale of the category category to the locale locale.
category must be an exact integer; the following pre-defined
variables are available. locale must be a string locale name,
or #f
if you’re merely querying the current locale.
Returns the locale name on success, or #f
if the system
couldn’t change the locale. If you pass #f
to the locale,
it returns the current locale name without changing it.
Predefined variables for possible category value of
sys-setlocale
.
[POSIX] Returns an assoc list of various information for formatting numbers in the current locale.
An example session. It may differ on your system settings.
(sys-localeconv) ⇒ ((decimal_point . ".") (thousands_sep . "") (grouping . "") (int_curr_symbol . "") (currency_symbol . "") (mon_decimal_point . "") (mon_thousands_sep . "") (mon_grouping . "") (positive_sign . "") (negative_sign . "") (int_frac_digits . 127) (frac_digits . 127) (p_cs_precedes . #t) (p_sep_by_space . #t) (n_cs_precedes . #t) (n_sep_by_space . #t) (p_sign_posn . 127) (n_sign_posn . 127)) (sys-setlocale LC_ALL "fr_FR") ⇒ "fr_FR" (sys-localeconv) ⇒ ((decimal_point . ",") (thousands_sep . "") (grouping . "") (int_curr_symbol . "FRF ") (currency_symbol . "F") (mon_decimal_point . ",") (mon_thousands_sep . " ") (mon_grouping . "\x03\x03") (positive_sign . "") (negative_sign . "-") (int_frac_digits . 2) (frac_digits . 2) (p_cs_precedes . #f) (p_sep_by_space . #t) (n_cs_precedes . #f) (n_sep_by_space . #t) (p_sign_posn . 1) (n_sign_posn . 1))
Gauche can send out operating system’s signals to the other processes (including itself) and can handle the incoming signals.
In multithread environment, all threads share the signal handlers, and each thread has its own signal mask. See Signals and threads, for details.
When a system call is interrupted by a signal, and a programmer defines a handler for the signal that doesn’t transfer control to other context, the system call is restarted after the handler returns by default.
Here are some calls that are not simply restarted by signal interruption.
close
This may be called through sys-close
, close-port
, or even
implicitly when the underlying file is closed. When a signal interrupts
this call, the passed fd is no longer in use. Simply restarting it can
be a race if another thread just grabs the fd.
dup2
This is called via port-fd-dup!
. When dup2
returns
EINTR
, the newfd is no longer in use and some other thread
may grab it before restarting it.
sleep
nanosleep
These calls tells the remaining time when they are interrupted. We restart them with that remaining time, not the original argument, so that the total sleep time would be close to what was given originally.
On Windows native platforms, signals don’t work except
some limited support of sys-kill
.
• Signals and signal sets: | ||
• Sending signals: | ||
• Handling signals: | ||
• Masking and waiting signals: | ||
• Signals and threads: |
Each signal is referred by its signal number (a small integer) defined on the underlying operating system. Variables are pre-defined to the system’s signal number. System’s signal numbers may be architecture dependent, so you should use those variables rather than using literal integers.
These variables are bound to the signal numbers of POSIX signals.
These variables are bound to the signal numbers of system-dependent signals. Not all of them may be defined on some systems.
For portable code, you can use SRFI-238’s codeset (see srfi.238
- Codesets).
Besides each signal numbers, you can refer to a set of signals
using a <sys-sigset>
object.
It can be used to manipulate the signal mask, and to install a signal
handler to a set of signals at once.
[POSIX]
Interface to strsignal(3)
. The argument must be an exact
integer.
Returns the system message associated with the signal with the number
signum, as a string.
if no such message is available, or signum is not a valid signal number,
this function may return #f
or some generic message provided
by the system.
For portable code, you can use SRFI-238’s codeset (see srfi.238
- Codesets).
A set of signals. An empty sigset can be created by
(make <sys-sigset>) ⇒ #<sys-sigset []>
Creates and returns an instance of <sys-sigset>
with members signal …. Each signal
may be either a signal number, another <sys-sigset>
object, or #t
for all available signals.
(sys-sigset SIGHUP SIGINT) ⇒ #<sys-sigset [HUP|INT]>
Sigset must be a <sys-sigset>
object.
Those procedures adds and removes the specified signals from
sigset respectively, and returns the result. sigset itself
is also modified.
signal may be either a signal number, another <sys-sigset>
object, or #t
for all available signals.
Fills sigset by all available signals, or empties sigset.
Returns the human-readable name of the given signal number. (Note that signal numbers are system-dependent.)
For portable code, you can use SRFI-238’s codeset (see srfi.238
- Codesets).
(sys-signal-name 2) ⇒ "SIGINT"
To send a signal, you can use sys-kill
which works like
kill(2)
.
[POSIX] Sends a signal sig to the specified process(es). Sig must be a positive exact integer. pid is an exact integer and specifies the target process(es):
On Windows native platforms, sys-kill
may take positive integer
or a process handle (<win:handle>
instance) as pid.
Only SIGKILL
, SIGINT
and SIGABRT
are allowed
as sig; Gauche uses TerminateProcess
to terminate
the target process for SIGKILL
,
and sends the target process
CTRL_C_EVENT
and CTRL_BREAK_EVENT
for
SIGINT
and SIGABRT
, respectively.
There’s no Scheme equivalence for raise()
, but you can use
(sys-kill (sys-getpid) sig)
.
You can register signal handling procedures in Scheme. (In multithread environment, signal handlers are shared by all threads; see Signals and threads for details).
When a signal is delivered to the Scheme process, the VM just records it and processes it later at a ’safe point’ where the state of VM is consistent. We call the signal is pending when it is registered by the VM but not processed yet.
(Note that this makes handling of some signals such as SIGILL
useless, for the process can’t continue sensible execution after
recording the signal).
If the same signal is delivered more than once before VM processes the first one, the second one and later have no effect. (This is consistent to the traditional Unix signal model.) In other words, for each VM loop a signal handler can be invoked at most once per each signal.
When too many signals of the same kind are pending,
Gauche assumes something has
gone wrong (e.g. infinite loop inside C-routine) and aborts the
process. The default of this limit is set rather low (3), to allow
unresponsive interactive script to be terminated by typing Ctrl-C
three times. Note that the counter is individual for each signal;
Gauche won’t abort if one SIGHUP
and two SIGINT
s are
pending, for example. You can change this limit by
set-signal-pending-limit
described below.
When you’re using the gosh
interpreter, the default
behavior for each signal is as in the following table.
SIGABRT, SIGILL, SIGKILL, SIGSTOP, SIGSEGV, SIGBUS
Cannot be handled in Scheme. Gosh
follows the system’s
default behavior.
SIGCHLD, SIGTSTP, SIGTTIN, SIGTTOU, SIGWINCH
No signal handles are installed for these signals by gosh
,
so the process follows the system’s default behavior.
A Scheme programs can install its own signal handler if necessary.
SIGCONT
If gosh
is running with input editing mode, a signal handler
is installed to restore terminal status. Otherwise, no signal
handler is installed by default, and a Scheme program can
install its own signal handler if necessary.
SIGHUP, SIGQUIT, SIGTERM
Gosh
installs a signal handler for these signals
that exits from the application with code 0.
SIGPIPE
Gosh
installs a signal handler that does nothing—that is,
this signal is effectively ignored by default.
It is a design choice. Since Gauche delays actual handling
of signals, SIGPIPE
would be handled after the system call
that tries to write to a broken pipe returns with EPIPE
.
That makes the signal a lot less useful, for we can handle the
situation with error handlers for <system-error>
with EPIPE
.
The default Unix behavior of SIGPIPE
is to terminate
the process. It is useful for the traditional command-line tools
that are often piped together—if one of downstream commands fails,
the upstream process receives SIGPIPE
and the entire
command chain is shut down without a fuss. The signal is, however, rather an
annoyance for other types of output such as sockets.
Gauche does support this “exit when pipe gets stuck” convention
by ports. A port can be configured as sigpipe sensitive;
if writing to that port caused EPIPE
, it terminates the
process. By default, standard output and standard error output
are configured in that way.
SIGPWR, SIGXCPU, SIGUSR1, SIGUSR2
On Linux platforms with thread support, these signals are used by the system and not available for Scheme. On other systems, these signals behaves the same as described below.
other signals
Gosh
installs the default signal handler, which raises
<unhandled-signal-error>
condition (see Conditions).
Scheme programs can override it by its own signal handler.
If you’re using Gauche embedded in some other application, it may redefine the default behavior.
Use the following procedures to get/set signal handlers from Scheme.
Signals may be a single signal number or a <sys-sigset>
object, and handler should be either #t
, #f
,
#<undef>
, or a procedure that takes one argument.
If handler is a procedure, it will be called when the process
receives one of specified signal(s), with the received signal
number as an argument.
By default, the signals in signals are blocked
(in addition to the signal mask in effect at that time) during
handler is executed, so that handler won’t be
reentered by the same signal(s). You can provide
a <sys-sigset>
object to the sigmask arg
to specify the signals to be blocked explicitly.
Note that the signal mask
is per-thread; if more than one thread unblocks a signal, the handler
may still be invoked during execution of the handler (in other thread)
even if you specify sigmask. You have to set the threads’
signal mask properly to avoid such situation.
It is safe to do anything in handler, including throwing an error or invoking continuation captured elsewhere. (However, continuations captured inside handler will be invalid once you return from handler).
If handler is #t
, the operating system’s default
behavior is set to the specified signal(s). If handler
is #f
, the specified signals(s) will be ignored.
If handler is #<undef>
(see Undefined values),
it indicates Gauche to leave the current OS’s signal handler as it is.
This value isn’t as much use in set-signal-handler!
as
in get-signal-handler
: If #<undef>
is passed
to set-signal-handler!
, it immediately returns without
modifying anything. However, if you get #<undef>
from get-signal-handler
, you can know that the
signal handler behavior hasn’t been modified by Gauche.
(Note that once Gauche ever installs a signal handler,
there is no way to revert back to make get-signal-handler
return #<undef>
).
Note that signal handler setting is shared among threads in multithread environment. The handler is called from the thread which is received the signal. See Signals and threads for details.
Returns the handler setting, or signal mask setting, of a signal signum,
respectively. See set-signal-handler!
for the meaning of
the return value of get-signal-handler
.
Returns an associative list of all signal handler settings.
Car of each element of returned list is a <sys-sigset>
object,
and cdr of it is the handler (a procedure or a boolean value)
of the signals in the set.
Gets/sets the maximum number of pending signals per each signal type. If the number of pending signals exceeds this limit, Gauche aborts the process. See the explanation at the beginning of this section for the details. Limit must be a nonnegative exact integer. In the current implementation the maximum number of limit is 255. Setting limit to zero makes the number of pending signals unlimited.
A convenience macro to install signal handlers temporarily during execution of thunk. (Note: though this is convenient, this has certain dangerous properties described below. Use with caution.)
Each Handler-clause may be one of the following forms.
(signals expr …)
Signals must be an expression that will yield either a signal,
a list of signals, or a <sys-sigset>
object.
Installs a signal handler for signals that evaluates
expr … when one of the signals in signals is delivered.
(signals => handler)
This form sets the handler of signals to handler,
where handler should be either #t
, #f
or a procedure that takes one argument.
If handler is a procedure, it will be called when the process
receives one of specified signal(s), with the received signal
number as an argument.
If handler is #t
, the operating system’s default
behavior is set to the specified signal(s). If handler
is #f
, the specified signals(s) will be ignored.
When the control exits from thunk, the signal handler setting
before with-signal-handlers
are recovered.
CAVEAT: If you’re setting more than one signal handlers,
they are installed in serial. If a signal is delivered before
all the handlers are installed, the signal handler state may be
left inconsistent. Also note that the handler setting is a global state;
you can’t set "thread local" handler by with-signal-handlers
,
although the form may be misleading.
A Scheme program can set a signal mask, which is a set of signals to be blocked from delivery. If a signal is delivered which is completely blocked in the process, the signal becomes "pending". The pending signal may be delivered once the signal mask is changed not to block the specified signal. (However, it depends on the operating system whether the pending signals are queued or not.)
In multithread environment, each thread has its own signal mask.
Modifies the current thread’s signal mask, and returns the previous
signal mask. Mask should be a <sys-sigset>
object
to specify the new mask, or #f
if you just want to query
the current mask without modifying one.
If you give <sys-sigset>
object to mask,
how argument should be one of the following
integer constants:
SIG_SETMASK
Sets mask as the thread’s signal mask.
SIG_BLOCK
Adds signals in mask to the thread’s signal mask.
SIG_UNBLOCK
Removes signals in mask from the thread’s signal mask.
Atomically sets thread’s signal mask to mask and
suspends the calling thread. When a signal that is not blocked
and has a signal handler installed is delivered, the associated
handler is called, then sys-sigsuspend
returns.
[POSIX]
Mask must be a <sys-sigset>
object.
If any of signals in mask is/are pending in the OS,
atomically clears one of them and returns the signal number
of the cleared one. If there’s no signal in mask
pending, sys-sigwait
blocks until any of the signals
in mask arrives.
You have to block all signals in mask in all threads
before calling sys-sigwait
. If there’s a thread
that doesn’t block the signals, the behavior of
sys-sigwait
is undefined.
Note: Sys-sigwait
uses system’s sigwait
function,
whose behavior is not defined if there’s a signal
handler on the signals it waits. To avoid complication,
sys-sigwait
resets the handlers set to the signals
included in mask before calling sigwait
to SIG_DFL
,
and restores them after sigwait
returns. If another thread
changes signal handlers while sys-sigwait
is waiting,
the behavior is undefined; you shouldn’t do that.
The semantics of signals looks a bit complicated in the multithread environment. Nevertheless, it is pretty comprehensible once you remember a small number of rules. Besides, Gauche sets up the default behavior easy to use, while allowing programmers to do tricky stuff.
If you don’t want to be bothered by the details, just remember one thing, with one sidenote. By default, signals are handled by the primordial (main) thread. However, if the main thread is suspended on mutex or condition variable, the signal may not be handled at all, so be careful.
Now, if you are curious about the details, here are the rules:
Now, these rules have several implications.
If there are more than one thread that don’t block a particular signal, you can’t know which thread receives the signal. Such a situation is much less useful in Gauche than C programs because of the fact that the signal handling can be delayed indefinitely if the receiver thread is waiting on mutex or condition variable. So, it is recommended to make sure, for each signal, there is only one thread that can receive it.
In Gauche, all threads created by make-thread
(see Thread procedures) blocks all the signals by default
(except the reserved ones). This lets all the signals
to be directed to the primordial (main) thread.
Another strategy is to create a thread dedicated for handling
signals. To do so, you have to block the signals in the
primordial thread, then create the signal-handling thread,
and within that thread you unblock all the signals.
Such a thread can just loop on sys-pause
.
(thread-start! (make-thread (lambda () (sys-sigmask SIG_SETMASK (make <sys-sigset>)) ;;empty mask (let loop () (sys-pause) (loop)))))
Complicated application may want to control per-thread signal handling precisely. You can do so, just make sure that at any moment only the designated thread unblocks the desired signal.
[POSIX] Returns a list of five elements,
(sysname nodename release version machine)
.
Returns the host name. If the system doesn’t have gethostname(),
the second element of the list returned by sys-uname
is used.
Returns the domain name. If the system doesn’t have getdomainname(),
"localdomain"
is returned.
[POSIX] Returns the current working directory by a string.
If the current working directory couldn’t be obtained from the system,
an error is signaled. See also sys-chdir
(see Other file operations), current-directory
(see Directory utilities).
[POSIX] Returns integer value of real and effective group id of the
current process, respectively.
Use sys-gid->group-name
or sys-getgrgid
to obtain
the group’s name and other information associated to the returned
group id (see Unix groups and users).
[POSIX] Sets the effective group id of the current process.
[POSIX]
Returns integer value of real and effective user id of the
current process, respectively.
Use sys-uid->user-name
or sys-getpwuid
to obtain
the user’s name and other information associated to the returned
user id (see Unix groups and users).
[POSIX] Sets the effective user id of the current process.
Returns true iff the process is running with suid/sgid-ed (that is, the program’s suid and/or sgid bit is set.)
Note: If the platform has issetugid()
call, we use it.
Otherwise, we remember whether the real (user|group) id and the
effective (user|group) id differ or not at the initialization time.
(In the latter case, we can’t detect the case that the process
changes [e]uid/[e]gid before initializing Gauche; keep it in mind if
libgauche is used as an embedded Scheme engine).
[POSIX] Returns a list of integer ids of supplementary groups.
Sets the current process’s groups to the given list of integer group ids. The caller must have the appropriate privilege.
This procedure is only available when the feature id
gauche.sys.setgroups
exists. Use cond-expand
for
the portable program:
(cond-expand [gauche.sys.setgroups (sys-setgroups '(0 1))] [else])
[POSIX] Returns a string of the name of the user logged in on the
controlling terminal of the current process.
If the system can’t determine the information, #f
is returned.
[POSIX] Returns a process group id of the current process.
Returns a process group id of the process specified by pid. If pid is zero, the current process is used.
Note that getpgid()
call is not in POSIX. If the system
doesn’t have getpgid()
, sys-getpgid
still works if
pid is zero (it just calls sys-getpgrp
), but signals
an error if pid is not zero.
[POSIX] Sets the process group id of the process pid to pgid.
If pid is zero, the process ID of the
current process is used. If pgid is zero, the process ID
of the process specified by pid
is used. (Hence
sys-setpgid(0, 0)
sets the process group id of the
current process to the current process id).
[POSIX] Creates a new session if the calling process is not a process group leader.
[POSIX] Returns the current process id and the parent process id, respectively.
[POSIX]
[POSIX] Returns the name of the controlling terminal of the process.
This may be just a "/dev/tty"
. See also sys-ttyname
.
[POSIX]
Get and set resource limits respectively.
Resource is an integer constant to specify the resource
of concern. The following constants are defined.
(The constants marked as bsd and/or linux indicates that they
are not defined in POSIX but defined in BSD and/or Linux.
Other systems may or may not have them. Consult getrlimit
manpage of your system for the details.)
RLIMIT_AS RLIMIT_CORE RLIMIT_CPU RLIMIT_DATA RLIMIT_FSIZE RLIMIT_LOCKS RLIMIT_MEMLOCK (bsd/linux) RLIMIT_MSGQUEUE (linux) RLIMIT_NICE (linux) RLIMIT_NOFILE RLIMIT_NPROC (bsd/linux) RLIMIT_RSS (bsd/linux) RLIMIT_RTPRIO (linux) RLIMIT_SIGPENDING (linux) RLIMIT_SBSIZE RLIMIT_STACK RLIMIT_OFILE
[POSIX] Adds inc, which must be an exact integer, to the current process’s nice value. Only the root user can specify negative inc value. Returns the new nice value.
Errno must be an exact nonnegative integer representing a system error number. This function returns a string describing the error.
For portable code, you can use SRFI-238’s codeset (see srfi.238
- Codesets).
To represent errno, the following constants are defined. Each constant is bound to an exact integer representing the system’s error number. Note that the actual value may differ among systems, and some of these constants may not be defined on some systems.
E2BIG EHOSTDOWN ENETDOWN ENXIO EACCES EHOSTUNREACH ENETRESET EOPNOTSUPP EADDRINUSE EIDRM ENETUNREACH EOVERFLOW EADDRNOTAVAIL EILSEQ ENFILE EPERM EADV EINPROGRESS ENOANO EPFNOSUPPORT EAFNOSUPPORT EINTR ENOBUFS EPIPE EAGAIN EINVAL ENOCSI EPROTO EALREADY EIO ENODATA EPROTONOSUPPORT EBADE EISCONN ENODEV EPROTOTYPE EBADF EISDIR ENOENT ERANGE EBADFD EISNAM ENOEXEC EREMCHG EBADMSG EKEYEXPIRED ENOKEY EREMOTE EBADR EKEYREJECTED ENOLCK EREMOTEIO EBADRQC EKEYREVOKED ENOLINK ERESTART EBADSLT EL2HLT ENOMEDIUM EROFS EBFONT EL2NSYNC ENOMEM ESHUTDOWN EBUSY EL3HLT ENOMSG ESOCKTNOSUPPORT ECANCELED EL3RST ENONET ESPIPE ECHILD ELIBACC ENOPKG ESRCH ECHRNG ELIBBAD ENOPROTOOPT ESRMNT ECOMM ELIBEXEC ENOSPC ESTALE ECONNABORTED ELIBMAX ENOSR ESTRPIPE ECONNREFUSED ELIBSCN ENOSTR ETIME ECONNRESET ELNRNG ENOSYS ETIMEDOUT EDEADLK ELOOP ENOTBLK ETOOMANYREFS EDEADLOCK EMEDIUMTYPE ENOTCONN ETXTBSY EDESTADDRREQ EMFILE ENOTDIR EUCLEAN EDOM EMLINK ENOTEMPTY EUNATCH EDOTDOT EMSGSIZE ENOTNAM EUSERS EDQUOT EMULTIHOP ENOTSOCK EWOULDBLOCK EEXIST ENAMETOOLONG ENOTTY EXDEV EFAULT ENAVAIL ENOTUNIQ EXFULL EFBIG
These procedures convert between integer error number and the symbol
of its unix name (e.g. EINTR
).
If the given error number or name isn’t available on the running
platform, those procedures return #f
. See sys-strerror
above for potentially available error names.
Valid error names and their actual values differ among platforms. These procedures make it easy to write portable meta-code that deal with system errors.
For portable code, you can use SRFI-238’s codeset (see srfi.238
- Codesets).
Gauche has two representations of time, one is compatible to POSIX API, and the other is compatible to SRFI-18, SRFI-19 and SRFI-21. Most procedures accept both representations; if not, the representation the procedure accepts is indicated as either ’POSIX time’ or ’SRFI time’.
POSIX time is represented by a real number which is a number of seconds
since Unix Epoch (Jan 1, 1970, 0:00:00GMT).
Procedure sys-time
, which corresponds to POSIX time(2)
,
returns this time representation.
SRFI-compatible time is represented by an object of <time>
class,
which keeps seconds and nanoseconds, as well as the type of the time
(UTC, TAI, duration, process time, etc).
Current-time
returns this representation.
[POSIX] Returns the current time in POSIX time (the time since Epoch (00:00:00 UTC, January 1, 1970), measured in seconds). It may be a non-integral number, depending on the architecture.
Note that POSIX’s definition of “seconds since the Epoch” doesn’t take leap seconds into account.
Returns two values. The first value is a number of seconds,
and the second value is a fraction in a number of microseconds,
since 1970/1/1 0:00:00 UTC. If the system doesn’t have
gettimeofday
call, this function calls time()
;
in that case, microseconds portion is always zero.
Represents struct tm
, a calendar date. It has the following slots.
<sys-tm>
: sec ¶Seconds. 0-61.
<sys-tm>
: min ¶Minutes. 0-59.
<sys-tm>
: hour ¶Hours. 0-23.
<sys-tm>
: mday ¶Day of the month, counting from 1. 1-31.
<sys-tm>
: mon ¶Month, counting from 0. 0-11.
<sys-tm>
: year ¶Years since 1900, e.g. 102 for the year 2002.
<sys-tm>
: wday ¶Day of the week. Sunday = 0 .. Saturday = 6.
<sys-tm>
: yday ¶Day of the year. January 1 = 0 .. December 31 = 364 or 365.
<sys-tm>
: isdst ¶A flag that indicates if the daylight saving time is in effect. Positive if DST is in effect, zero if not, or negative if unknown.
[POSIX] Converts time to <sys-tm>
object, represented in GMT
or local timezone, respectively. Time can be either POSIX-time or
SRFI-time.
[POSIX] Converts time to it string representation, using POSIX ctime(). Time can be either POSIX-time or SRFI-time.
[POSIX] Returns the difference of two times in the real number of seconds. Time0 and time1 can be either POSIX-time or SRFI-time.
[POSIX] Converts <sys-tm>
object tm to a string representation.
[POSIX] Converts <sys-tm>
object tm to a string representation,
according to a format string format.
See your system’s manual entry of strftime
for the
supported format.
It may return an empty string if the formatting results in an unusually lengthy string.
[POSIX] Converts <sys-tm>
object tm, expressed as local time,
to the POSIX-time (number of seconds since Epoch).
Deprecated.
The <time>
object also represents a point of time.
<time>
: type ¶Indicates time type. time-utc
is the default, and that
represents the number of seconds since Unix Epoch.
SRFI-19 (see srfi.19
- Time data types and procedures) adds more types.
<time>
: second ¶Second part of the time.
<time>
: nanosecond ¶Nanosecond part of the time.
[SRFI-18][SRFI-21]
Returns the <time>
object representing the current time in
time-utc
. See srfi.19
- Time data types and procedures, for
it redefines current-time
to allow optional argument to
specify time type.
[SRFI-18][SRFI-19][SRFI-21]
Returns #t
if obj is a time object.
The argument must be either a <time>
object, a real number,
or #f
. If it is an absolute <time>
object, it specifies
an absolute point of time. If it is a <time>
object of
time-duration
type, it is taken as a relative time from the current time.
If it is a real number, it specifies
the number of seconds from the current time.
This procedure returns #f
if the argument is #f
,
and a UTC <time>
object for an absolute point of time otherwise.
Most procedures that takes ‘timeout’ argument accepts <time
object,
real number or #f
. This procedure is useful to process
such argument in the same way.
The optional current-time is, if provided, must be an
absolute <time>
object or #f
. If it is a <time>
object, it is used as the current time instead of the actual current time.
[SRFI-226+] Returns a time object that is x seconds after the given time. The type of returned time object is the same as time. The argument x must be a finite real number. If it is negative, returnd time is before the given time.
This procedure is mainly to write code compatibe to SRFI-226.
For Gauche-specific code, you can use absolute-time
above.
See Time procedures, for another way to compute with time
difference by add-duration
/subtract-duration
.
[SRFI-18][SRFI-21]
Converts between time object and the number of seconds (POSIX-time).
Time argument of time->seconds
has to be a <time>
object.
The following procedures provide pretty raw, direct interface
to the system calls.
See also gauche.process
- High-level process interface, which provides
more convenient process handling on top of these primitives.
[POSIX]
Runs command, which must be a string, in a subprocess.
command is usually passed
to sh
, so the shell metacharacters are interpreted.
If the operating system fails to spawn a subshell, a <system-error>
is thrown. Otherwise, it waits until the subshell terminates, and
the integer termination status of the subshell is
returned.
The termination status must be interpreted as the same way as
the return value of sys-wait
, described below. For example,
if you want to get exit status, you have to test the result with
sys-wait-exited?
, then apply sys-wait-exit-status
.
In general, analyzing the result of sys-system
properly is cumbersome,
for nonzero code may indicate subshell’s abnormal exit or signalled status
or the command’s abnormal exit or signalled status.
We recommend to use do-process
etc. of gauche.process
module if you need to handle subprocess’ exit status
(see gauche.process
- High-level process interface).
On Windows native platforms this will pass the argument to cmd.exe
.
We strongly discourage invoking cmd.exe
with externally
supplied arguments, since it is impossible to safely escape
arbitrary string for cmd.exe
arguments on Windows.
[POSIX]
Fork the current process. Returns 0 if you’re in the child process,
and a child process’ pid if you’re in the parent process.
All the opened file descriptors are shared between the parent and
the child. See fork(2)
of your system for details.
If the child process runs some Scheme code and exits instead of
calling sys-exec
, it should call sys-exit
instead of exit
to terminate itself.
Normal exit call tries to flush the file
buffers, and on some OS it messes up the parent’s file buffers.
It should be noted that sys-fork
is not safe when
multiple threads are running. Because fork(2)
copies
the process’ memory image which includes any mutex state,
a mutex which is locked by another thread at the time of sys-fork
remains locked in the child process, nevertheless the child process
doesn’t have the thread that unlock it!
(This applies to the internal mutexes as well, so even you don’t
use Scheme mutex explicitly, this situation can always happen.)
If what you want is to spawn another program in a multi-threaded application,
use sys-fork-and-exec
explained below.
If you absolutely need to run Scheme code in the
child process, a typical technique is that you fork a manager process
at the beginning of application, and whenever you need a new process
you ask the manager process to fork one for you.
This procedure is not available on Windows native platforms.
[POSIX+] Execute command with args, a list of arguments. The current process image is replaced by command, so this function never returns.
All elements of args must be strings. The first element of
args is used as argv[0]
, i.e. the program name.
(NB: On Windows, you can invoke batch files (*.bat, *.cmd)
using sys-exec
and sys-fork-and-exec
, but you can’t
use characters ()%!^<>&|"
within the command-line arguments,
since there’s no comprehensive way to escape them safely.
You can pass them if you directly invoke an executable file.)
The keyword argument directory must be a string of a
directory name or #f
.
If it is a string, sys-exec
change current working directory
there before executing the program.
The iomap keyword argument, when provided, specifies how the open file descriptors are treated. It must be the following format:
((to-fd . from-port-or-fd) ...)
To-fd must be an integer, and from-port-or-fd must be an integer file descriptor or a port. Each element of the list makes the file descriptor of from-port-or-fd of the current process be mapped to the file descriptor to-fd in the executed process.
If iomap is provided,
any file descriptors other than specified in the iomap list will be closed
before exec()
. Otherwise, all file descriptors in the current
process remain open.
(sys-exec "ls" '("ls" "-l")) ⇒ ;; ls is executed. (let ((out (open-output-file "ls.out"))) (sys-exec "ls" '("ls" "-l") :iomap `((2 . 1) (1 . ,out))) ⇒ ;; ls is executed, with its stderr redirected ;; to the current process's stdout, and its ;; stdout redirected to the file "ls.out".
The sigmask keyword argument can be an instance of <sys-sigset>
or #f
(See Signal, for the details of signal masks).
If it is an instance of <sys-sigset>
, the signal mask of calling
thread is replaced by it just before exec(2)
is called.
It is useful, for example, to run an external program from a thread where
all signals are blocked (which is the default; see Signals and threads).
Without setting sigmask, the exec
ed process inherits
calling thread’s signal mask and become a process that blocks all signals,
which is not very convenient in most cases.
Finally, environment keyword argument specifies
the environment where the new process sees.
If it is #f
(default), the new process sees the same enviornment
of the caller process.
Otherwise, it must be a list of strings.
Each string must be a form of "NAME=VALUE"
, where NAME
is the name of envionemnt variable, and VALUE is its value.
Environment variable’s name cannot contain =
, while its value can.
This format is compatible with what sys-environ
returns
(see Environment inquiry),
so that you can get the current enviornment with sys-environ
,
add/remove/modify some of its entries, and pass it to this argument.
When sys-exec
encounters an error, most of the time it raises an error condition.
Once the file descriptors are permuted, however, it would be impractical
to handle errors in reasonable way (you don’t even know stderr is still
available!), so Gauche simply exits on the error.
On Windows native platforms, only redirections of stdin, stdout and stderr are handled. Singal mask is ignored, for Windows doesn’t have signals as the means of interprocess communication.
Like sys-exec
, but executes fork(2)
just before
remapping I/O, altering signal mask and call execvp(2)
.
Returns child’s process id. The meanings of arguments are
the same as sys-exec
.
It is strongly recommended to use this procedure instead of
sys-fork
and sys-exec
combination when you need
to spawn another program while other threads are running.
No memory allocation nor lock acquisition is done between
fork(2)
and execvp(2)
,
so it’s pretty safe in the multithreaded environment.
On Windows native platforms, this procedure returns a
Windows handle object (<win:handle>
) of the created
process instead of an integer process ID. See below for
Windows process handle specific API.
Like sys-exec
, only redirections of stdin, stdout and stderr
are handled on Windows native platforms.
When a true value is given to the detached keyword argument, the executed process is detached from the current process group and belongs to its own group. That is, it won’t be affected to the signal sent to the process group the caller process currently belongs to. It is a part of the common idioms to start a daemon process.
On Unix platforms, besides the executed process gets its own session
by setsid(2)
, it performs extra fork(2)
to make its
parent be the init
process (pid=1).
(Note: It means the running process is actually a grandchild of the
calling process, although that relationship isn’t preserved.
The returned pid is the running process’s one,
not the intermediate process that exits immediately.)
On Windows native platforms,
this flag causes the new process to be
created with the CREATE_NEW_PROCESS_GROUP
creation flag.
[POSIX] Calls system’s wait(2)
. The process suspends its execution
until one of the child terminates. Returns two exact integer values,
the first one is the child’s process id, and the second is a status code.
The status code can be interpreted by the following functions.
[POSIX] This is an interface to waitpid(3)
, an extended version of
wait.
pid is an exact integer specifying which child(ren) to be waited. If it is a positive integer, it waits for that specific child. If it is zero, it waits for any member of this process group. If it is -1, it waits for any child process. If it is less than -1, it waits for any child process whose process group id is equal to the absolute value of pid.
If there’s no child process to wait, or a specific pid is
given but it’s not a child process of the current process,
an error (<system-error>
, ECHILD
) is signaled.
The calling process suspends until one of those child process is terminated, unless true is specified to the keyword argument nohang.
If true is specified to the keyword argument untraced, the status of stopped child process can be also returned.
The return values are two exact integers, the first one is the child process id, and the second is a status code. If nohang is true and no child process status is available, the first value is zero.
On Windows native platforms, this procedure may also accept
a Windows process handle (<win:handle>
) object as pid to
wait the specific process. You can pass -1
as pid
to wait for any children, but you cannot wait for a specific
process group.
[POSIX]
The argument is an exit status returned as a second value
from sys-wait
or sys-waitpid
.
sys-wait-exited?
returns #t
if the child process is
terminated normally. sys-wait-exit-status
returns the exit
code the child process passed to exit(2)
, or the return value
of main()
.
[POSIX]
The argument is an exit status returned as a second value
from sys-wait
or sys-waitpid
.
sys-wait-signaled?
returns #t
if the child process
is terminated by an uncaught signal.
sys-wait-termsig
returns the signal number that terminated the child.
[POSIX]
The argument is an exit status returned as a second value
from sys-waitpid
.
sys-wait-stopped?
returns #t
if the child process is
stopped. This status can be caught only by sys-waitpid
with
true untraced argument. sys-wait-stopsig
returns the
signum number that stopped the child.
On Windows native platforms, exit code is not structured as on Unix.
You cannot distinguish a process being exited voluntarily or
by forced termination. Gauche uses exit code #xff09
to
terminate other process with sys-kill
,
and the above sys-wait-*
procedures are adjusted accordingly,
so that sys-wait-signaled?
can likely to be used to check
whether if the child process is terminated by Gauche.
(See Signal, for the details of signal support on Windows.)
Sys-wait-stopped?
never returns true
on Windows native platforms (yet).
The following procedures are to access Windows process handle. They are only available on Windows native platforms.
[Windows]
Returns #t
iff obj is a Windows process handle object.
[Windows] Returns an integer PID of the process represented by a Windows process handle handle. An error is signaled if handle is not a valid Windows process handle.
Note that the API to get a pid from a process handle is only
provided on or after Windows XP SP1. If you call this
procedure on Windows version before that, -1
will be
returned.
The interface functions for select(2)
.
The higher level interface is provided on top of these
primitives; see gauche.selector
- Simple dispatcher.
Represents fd_set
, a set of file descriptors. You can make
an empty file descriptor set by make method:
(make <sys-fdset>)
Creates a new <sys-fdset>
instance with file descriptors
specified by elt …. Each elt can be an
integer file descriptor, a port, or a <sys-fdset>
instance.
In the last case, the descriptors in the given fdset is copied
to the new fdset.
Gets and sets specific file descriptor bit of fdset.
port-or-fd may be a port or an integer file descriptor.
If port-or-fd is a port that doesn’t have associated file descriptor,
sys-fdset-ref
returns #f
, and sys-fdset-set!
doesn’t
modify fdset. flag must be a boolean value.
You can use generic setter of sys-fdset-ref
as this:
(set! (sys-fdset-ref fdset port-or-fd) flag) ≡ (sys-fdset-set! fdset port-or-fd flag)
Copies the content of src-fdset into dest-fdset. Returns dest-fdset.
Empties and returns fdset.
Converts an fdset to a list of integer file descriptors and vice versa.
In fact, list->sys-fdset
works just like
(lambda (fds) (apply sys-fdset fds))
, so it accepts ports
and other fdsets as well as integer file descriptors.
Returns the maximum file descriptor number in fdset.
Waits for a set of file descriptors to change status.
readfds, writefds, and exceptfds are <fdset>
objects to represent a set of file descriptors to watch.
File descriptors in readfds are watched to see if characters
are ready to be read. File descriptors in writefds are
watched if writing to them is ok. File descriptors in exceptfds
are watched for exceptions. You can pass #f
to one or more
of those arguments if you don’t care about watching the condition.
timeout specifies maximum time sys-select
waits for
the condition change. It can be a real number, for number of microseconds,
or a list of two integers, the first is the number of seconds and
the second is the number of microseconds. If you pass #f
,
sys-select
waits indefinitely.
sys-select
returns four values. The first value is a number
of descriptors it detected status change. It may be zero if
timeout expired. The second, third and fourth values are <fdset>
object that contains a set of descriptors that changed status
for reading, writing, and exception, respectively.
If you passed #f
to one or more of readfds,
writefds and exceptfds, the corresponding return value
is #f
.
sys-select!
variant works the same as sys-select
, except
it modifies the passed <fdset>
arguments.
sys-select
creates new <fdset>
objects and
doesn’t modify its arguments.
The garbage collector runs implicitly whenever it is necessary, and you don’t usually need to worry about it. However, in case if you do need to worry, here are a few procedures you can use.
Trigger a full GC. It may be useful if you want to reduce interference of GC in certain parts of code by calling this immediately before that.
Returns a list of lists, each inner list contains a keyword and related statistics number (integer).
(gc-stat) ⇒ ((:total-heap-size 7925760) (:free-bytes 524288) (:bytes-since-gc 473792) (:total-bytes 9925872) (:unmapped-bytes 0) (:heap-size-full 7925760) (:free-bytes-full 524288) (:allocated-bytes-before-gc 9452080) (:non-gc-bytes 0) (:gc-cycle 4) (:num-markers 15) (:bytes-reclaimed-since-gc 947824) (:reclaimed-bytes-before-gc 1615840) (:explicitly-freed-bytes-since-gc 0) (:obtained-from-os-bytes 9302016))
The meaning of each keyword is as follows. The list of available keywords
may change depending on GC version.
(The descriptions about GC_*()
calls and GC_prof_stats_s
are for those who know Boehm GC.)
:total-heap-size
Heap size in bytes, not including the area unmapped to OS.
(The value GC_get_heap_size()
returns.)
:heap-size-full
Heap size in bytes, including the area unmapped to OS.
(The value of heapsize_full
field of GC_prof_stats_s
.)
:free-bytes
Total bytes contained in free blocks.
(The value GC_get_free_bytes()
returns.)
:free-bytes-full
Total bytes contained in free and unmapped blocks.
(The value of free_bytes_full
field of GC_prof_stat_s
.)
:unmapped-bytes
Amount of memory unmapped to OS.
(The value GC_get_unmapped_bytes()
returns.)
:bytes-since-gc
Number of bytes allocated since the recent collection.
(The value GC_get_bytes_since_gc()
returns).
:allocated-bytes-before-gc
Number of bytes allocated before the recent collection.
This value may wrap if the process has allocated so many bytes.
(The value of allocd_bytes_before_gc
field of GC_prof_stat_s
.)
:non-gc-bytes
Number of bytes not considered for collection.
(The value of non_gc_bytes
field of GC_prof_stat_s
.)
:gc-cycle
Garbage collection cycle number. The value may wrap.
(The value of gc_no
field of GC_prof_stat_s
.)
:num-markers
Number of marker threads, excluding the initiating one.
(The value of markers_m1
field of GC_prof_stat_s
.)
:bytes-reclaimed-since-gc
Approx. number of reclaimed bytes after the recent collection.
(The value of bytes_reclaimed_since_gc
field of GC_prof_stat_s
.)
:reclaimed-bytes-before-gc
Approx. number of bytesreclaimed before the recent collection.
The value may wrap.
(The value of reclaimed_bytes_before_gc
field of GC_prof_stat_s
.)
:explicitly-freed-bytes-since-gc
Number of bytes freed explicitly since the recent collection.
(The value of expl_freed_bytes_since_gc
field of GC_prof_stat_s
.)
:obtained-from-os-bytes
Total amount of memory obtained from OS in bytes.
(The value of obtained_from_os_bytes
field of GC_prof_stat_s
.)
An object representing a mapped memory pages. It is returned
from sys-mmap
, and can be passed to make-view-uvector
to access. It has the following read-only slots.
<memory-region>
: address ¶The address of the mapping. Not useful in the Scheme world, but you may need to pass this to foreign functions.
<memory-region>
: size ¶The size of the mapping, in bytes.
<memory-region>
: protection ¶The bitmask represents memory protection. It is a bitwise OR of integer
constants
PROT_READ
, PROT_WRITE
, PROT_EXEC
and PROT_NONE
.
See sys-mmap
below for thedetails.
<memory-region>
: flags ¶the flags passed to the sys-mmap
. See sys-mmap
below
for the details.
[POSIX]
Maps files into memory using mmap(2)
(or
MapViewOfFileEx
on Windows). Returns
a <memory-region>
object, which can be accessed
via make-view-uvector
.
The port argument must be either a port or #f
.
If it is a port, it must have underlying file. If it is #f
,
the mapping becomes “anonymous” (not backed with a file); in that
case, MAP_ANONYMOUS
flag must also be specified in flags.
The prot argument specifies the protection bits of the memory region; it must be an integer created by bitwise-OR of the following constants:
PROT_EXEC
The mapped pages may be executed.
PROT_READ
The mapped pages may be read.
PROT_WRITE
The mapped pages may be written.
PROT_NONE
Pages may not be accessed.
The flags argument must be an integer created by bitwise-OR of the following constants:
MAP_SHARED
The mapping is shared among processes. If you update the mapped pages, other processes mapping the same region can see it, too.
MAP_PRIVATE
The mapping is private to this process. If you update the mapped pages, it stays in the process and is not visible from outside.
MAP_ANONYMOUS
The pages don’t have a backing file.
The size argument must be a positive exact integer, and the
offset argument must be a non-negative exact integer. They specify
the region of the file to be mapped; size bytes starting
from offset bytes. The offset must be a multiple of
the page size. If offfset is omitted, 0 is assumed.
If you’re mapping non-file-backed memory (when port is #f
),
offset is ignored.
You don’t need to unmap
the mapped pages explicitly; when the created
<memory-region>
object is garbage collected, the memory
is unmapped.
This procedure creates a uniform vector that works as a “window”
to the memory region mem, which must be
a <memory-region>
object. If the underlying memory content
changes, it is visible through the uvector. If the memory region is
writeble and you mutate the uvector, it is reflected to the underlying
memory region.
The class argument must be one of the uniform vector class
(e.g. <u8vector>
), and length is the length of the
uvector to be created. The length is the number of elements,
not the number of bytes. The memory is accessed with the native
endianness. Length can be #f
, in that case up to the end of the
memory region is used.
The offset argument specifies the offset from the beginning of memory region, in number of bytes. It must be a multiple of the uvector’s element size.
If the memory region is read-only (i.e. it is mapped without PROT_WRITE
),
the resulting uvector is immutable. Otherwise, it is mutable by default,
but ynou can give a true value to immutable? argument to create
an immutable uvector.
The memory region isn’t garbage collected as long as there’re uvectors that referencing the region.
[POSIX] Suspends the process until it receives a signal whose action is to either execute a signal-catching function or to terminate the process. This function only returns when the signal-catching function returns. The returned value is undefined.
Note that just calling pause()
doesn’t suffice the above semantics
in Scheme-level. Internally this procedure calls sigsuspend()
with the current signal mask.
[POSIX] Arranges a SIGALRM signal to be delivered after seconds. The previous settings of the alarm clock is canceled. Passing zero to seconds doesn’t schedule new alarm. Returns the number of seconds remaining until previously scheduled alarm was due to be delivered (or zero if no alarm is active).
[POSIX] Suspends the calling thread until the specified number of seconds elapses.
Note that libc’s sleep(3)
could return before the specified interval
if the calling thread receives a signal; in that case,
sys-sleep
automatically restarts sleep(3)
again with
remaining time interval
(after invoking Scheme signal handlers if there’s any) by default.
So you can count on the thread does sleep at least the specified
amount of time.
If you do want sys-sleep
to return prematurely upon receiving
a signal, you can give a true value to an optional argument no-retry.
The reason that we retries by default is that Gauche’s GC may use
signals to synchronize between threads. If GC is invoked by one thread
While another thread is sleeping on sleep(3)
, it may return
prematurely. It could happen often if other threads allocate a lot,
which could make sys-sleep
unreliable.
Returns zero if it sleeps well (which is always the case if no-retry is false), or the number of unslept seconds if it is woke up by a signal.
To be portable across POSIX implementation, keep seconds less than 65536.
Some systems may be using alarm(2)
to implement sleep(3)
,
so you shouldn’t mix sys-sleep
and sys-alarm
.
[POSIX]
Suspends the calling thread until the specified number of nanoseconds elapses.
The argument nanoseconds can be
a <time>
object (see Time), or a real number.
The system’s nanosleep(2)
could return before the specified interval
if the calling thread receives a signal; in that case,
sys-nanosleep
automatically restarts nanosleep(2)
again with
remaining time interval
(after invoking Scheme signal handlers if there’s any) by default.
So you can count on the thread does sleep at least the specified
amount of time.
The reason that we retries by default is that Gauche’s GC may use
signals to synchronize between threads. If GC is invoked by one thread
while another thread is sleeping on nanosleep(2)
, it may return
prematurely. It could happen often if other threads allocate a lot,
which could make sys-nanosleep
unreliable.
Returns #f
if nanoseconds elapsed (which is always
the case if no-retry
is #f
),
or a <time>
object that indicates the remaining time if sys-nanosleep
is interrupted by a signal.
;wait for 0.5 sec (sys-nanosleep 500000000) ;wait for 1.3 sec (sys-nanosleep (make <time> :second 1 :nanosecond 300000000))
Note: On Windows native platforms, this function is emulated using
Sleep
. The argument is rounded up to millisecond resolution,
and it won’t be interrupted by a signal.
A pseudo random number generator.
sys-random
returns a random number between 0 and a positive
integer rand_max, inclusive. This is a straightforward
interface to random(3)
. If the underlying system doesn’t have
random(3)
, lrand48(3)
is used.
sys-srandom
sets the seed of the random number generator.
It uses either srandom(3)
or srand48(3)
, depending on
the system.
The intention of these functions are to provide an off-the-stock handy
random number generator (RNG) for applications that doesn’t
sensitive to the quality and/or speed of RNG. For serious statistics
analysis, use Mersenne Twister RNG in math.mt-random
module (see math.mt-random
- Mersenne Twister Random number generator).
Bound to a positive integer that sys-random
may return.
[Windows] This procedure is only available on Windows native platforms. Returns a Windows file handle associated to the given port or integer file descriptor. Throws an error if the given argument does not have associated file handle.