## Unit posix

This unit provides services as used on many UNIX-like systems. Note that the following definitions are not all available on non-UNIX systems like Windows. See below for Windows specific notes.

This unit uses the `regex`, `scheduler`, `extras` and `utils` units.

All errors related to failing file-operations will signal a condition of kind `(exn i/o file)`.

### Constants

#### File-control Commands

`fcntl/dupfd` constant
`fcntl/getfd` constant
`fcntl/setfd` constant
`fcntl/getfl` constant
`fcntl/setfl` constant

  Operations used with `file-control`.

#### Standard I/O file-descriptors

`fileno/stdin` constant
`fileno/stdout` constant
`fileno/stderr` constant

  Standard I/O file descriptor numbers, used with procedures such as `open-input-file*` which take file descriptors.

#### Open flags

`open/rdonly` constant
`open/wronly` constant
`open/rdwr` constant
`open/read` constant
`open/write` constant
`open/creat` constant
`open/append` constant
`open/excl` constant
`open/noctty` constant
`open/nonblock` constant
`open/trunc` constant
`open/sync` constant
`open/fsync` constant
`open/binary` constant
`open/text` constant

  Open flags used with the `file-open` procedure. `open/read` is a convenience synonym for `open/rdonly`, as is `open/write` for `open/wronly`.

#### Permission bits

`perm/irusr` constant
`perm/iwusr` constant
`perm/ixusr` constant
`perm/irgrp` constant
`perm/iwgrp` constant
`perm/ixgrp` constant
`perm/iroth` constant
`perm/iwoth` constant
`perm/ixoth` constant
`perm/irwxu` constant
`perm/irwxg` constant
`perm/irwxo` constant
`perm/isvtx` constant
`perm/isuid` constant
`perm/isgid` constant

  Permission bits used with, for example, `file-open`.

### Directories

#### change-directory

`(change-directory NAME)` procedure

  Changes the current working directory to `NAME`.

#### change-directory*

`(change-directory* FD)` procedure

  Changes the current working directory to the one represented by the file-descriptor `FD`, which should be an exact integer.

#### current-directory

`(current-directory [DIR])` procedure

  Returns the name of the current working directory. If the optional argument `DIR` is given, then `(current-directory DIR)` is equivalent to `(change-directory DIR)`.

#### create-directory

`(create-directory NAME #!optional PARENTS?)` procedure

  Creates a directory with the pathname `NAME`. If the `PARENTS?` argument is given and not false, any nonexistent parent directories are also created.

  Notice that if `NAME` exists, `create-directory` won't try to create it and will return `NAME` (i.e., it won't raise an error when given a `NAME` that already exists).

#### delete-directory

`(delete-directory NAME [RECURSIVE])` procedure

  Deletes the directory with the pathname `NAME`. If `RECURSIVE` is not given or false, then the directory has to be empty.

#### directory

`(directory [PATHNAME [SHOW-DOTFILES?]])` procedure

  Returns a list with all files that are contained in the directory with the name `PATHNAME` (which defaults to the value of `(current-directory)`). Files beginning with `.` are included only if `SHOW-DOTFILES?` is given and not `#f`.

#### directory?

`(directory? FILE)` procedure

  Returns `#t` if `FILE` designates directory. Otherwise, it returns `#f`. `FILE` may be a pathname or a file-descriptor.

#### glob

`(glob PATTERN1 ...)` procedure

  Returns a list of the pathnames of all existing files matching `PATTERN1 ...`, which should be strings containing the usual file-patterns (with `*` matching zero or more characters and `?` matching zero or one character).

#### set-root-directory!

`(set-root-directory! STRING)` procedure

  Sets the root directory for the current process to the path given in `STRING` (using the `chroot` function). If the current process has no root permissions, the operation will fail.

### Pipes

#### call-with-input-pipe

#### call-with-output-pipe

`(call-with-input-pipe CMDLINE PROC [MODE])` procedure
`(call-with-output-pipe CMDLINE PROC [MODE])` procedure

  Call `PROC` with a single argument: a input- or output port for a pipe connected to the subprocess named in `CMDLINE`. If `PROC` returns normally, the pipe is closed and any result values are returned.

#### close-input-pipe

#### close-output-pipe

`(close-input-pipe PORT)` procedure
`(close-output-pipe PORT)` procedure

  Closes the pipe given in `PORT` and waits until the connected subprocess finishes. The exit-status code of the invoked process is returned.

#### create-pipe

`(create-pipe)` procedure

  The fundamental pipe-creation operator. Calls the C function `pipe()` and returns 2 values: the file-descriptors of the input- and output-ends of the pipe.

#### open-input-pipe

`(open-input-pipe CMDLINE [MODE])` procedure

  Spawns a subprocess with the command-line string `CMDLINE` and returns a port, from which the output of the process can be read. If `MODE` is specified, it should be the keyword `#:text` (the default) or `#:binary`.

#### open-output-pipe

`(open-output-pipe CMDLINE [MODE])` procedure

  Spawns a subprocess with the command-line string `CMDLINE` and returns a port. Anything written to that port is treated as the input for the process. If `MODE` is specified, it should be the keyword `#:text` (the default) or `#:binary`.

#### pipe/buf

This variable contains the maximal number of bytes that can be written atomically into a pipe or FIFO.

#### with-input-from-pipe

#### with-output-to-pipe

`(with-input-from-pipe CMDLINE THUNK [MODE])` procedure
`(with-output-to-pipe CMDLINE THUNK [MODE])` procedure

  Temporarily set the value of `current-input-port/current-output-port` to a port for a pipe connected to the subprocess named in `CMDLINE` and call the procedure `THUNK` with no arguments. After `THUNK` returns normally the pipe is closed and the standard input-/output port is restored to its previous value and any result values are returned.

      (with-output-to-pipe
        "gs -dNOPAUSE -sDEVICE=jpeg -dBATCH -sOutputFile=signballs.jpg -g600x600 -q -"
        (lambda ()
          (print #<<EOF
       %!IOPSC-1993 %%Creator: HAYAKAWA Takashi<xxxxxxxx@xx.xxxxxx.xx.xx>
       /C/neg/d/mul/R/rlineto/E/exp/H{{cvx def}repeat}def/T/dup/g/gt/r/roll/J/ifelse 8
       H/A/copy(z&v4QX&93r9AxYQOZomQalxS2w!!O&vMYa43d6r93rMYvx2dca!D&cjSnjSnjjS3o!v&6A
       X&55SAxM1CD7AjYxTTd62rmxCnTdSST0g&12wECST!&!J0g&D1!&xM0!J0g!l&544dC2Ac96ra!m&3A
       F&&vGoGSnCT0g&wDmlvGoS8wpn6wpS2wTCpS1Sd7ov7Uk7o4Qkdw!&Mvlx1S7oZES3w!J!J!Q&7185d
       Z&lx1CS9d9nE4!k&X&MY7!&1!J!x&jdnjdS3odS!N&mmx1C2wEc!G&150Nx4!n&2o!j&43r!U&0777d
       ]&2AY2A776ddT4oS3oSnMVC00VV0RRR45E42063rNz&v7UX&UOzF!F!J![&44ETCnVn!a&1CDN!Y&0M
       V1c&j2AYdjmMdjjd!o&1r!M){( )T 0 4 3 r put T(/)g{T(9)g{cvn}{cvi}J}{($)g[]J}J
       cvx}forall/moveto/p/floor/w/div/S/add 29 H[{[{]setgray fill}for Y}for showpage
       EOF
       ) ) )

### Fifos

#### create-fifo

`(create-fifo FILENAME [MODE])` procedure

  Creates a FIFO with the name `FILENAME` and the permission bits `MODE`, which defaults to

       (+ perm/irwxu perm/irwxg perm/irwxo)

#### fifo?

`(fifo? FILE)` procedure

  Returns `#t` if `FILE` names a FIFO. `FILE` may be a filename or a file-descriptor.

### File descriptors and low-level I/O

#### duplicate-fileno

`(duplicate-fileno OLD [NEW])` procedure

  If `NEW` is given, then the file-descriptor `NEW` is opened to access the file with the file-descriptor `OLD`. Otherwise a fresh file-descriptor accessing the same file as `OLD` is returned.

#### file-close

`(file-close FILENO)` procedure

  Closes the input/output file with the file-descriptor `FILENO`.

#### file-open

`(file-open FILENAME FLAGS [MODE])` procedure

  Opens the file specified with the string `FILENAME` and open-flags `FLAGS` using the C function `open(2)`. On success a file-descriptor for the opened file is returned.

  `FLAGS` is a bitmask of `open/...` values ored together using `bitwise-ior` (or simply added together). You must provide exactly one of the access flags `open/rdonly`, `open/wronly`, or `open/rdwr`. Additionally, you may provide zero or more creation flags (`open/creat`, `open/excl`, `open/trunc`, and `open/noctty`) and status flags (the remaining `open/...` values). For example, to open a possibly new output file for appending:

      (file-open "/tmp/hen.txt" (+ open/wronly open/append open/creat))

  The optional `MODE` should be a bitmask composed of one or more permission values like `perm/irusr` and is only relevant when a new file is created. The default mode is `perm/irwxu | perm/irgrp | perm/iroth`.

#### file-mkstemp

`(file-mkstemp TEMPLATE-FILENAME)` procedure

  Create a file based on the given `TEMPLATE-FILENAME`, in which the six last characters must be XXXXXX. These will be replaced with a string that makes the filename unique. The file descriptor of the created file and the generated filename is returned. See the `mkstemp(3)` manual page for details on how this function works. The template string given is not modified.

  Example usage:

       (let-values (((fd temp-path) (file-mkstemp "/tmp/mytemporary.XXXXXX")))
        (let ((temp-port (open-output-file* fd)))
          (format temp-port "This file is ~A.~%" temp-path)
          (close-output-port temp-port)))

#### file-read

`(file-read FILENO SIZE [BUFFER])` procedure

  Reads `SIZE` bytes from the file with the file-descriptor `FILENO`. If a string or bytevector is passed in the optional argument `BUFFER`, then this string will be destructively modified to contain the read data. This procedure returns a list with two values: the buffer containing the data and the number of bytes read.

#### file-select

`(file-select READFDLIST WRITEFDLIST [TIMEOUT])` procedure

  Waits until any of the file-descriptors given in the lists `READFDLIST` and `WRITEFDLIST` is ready for input or output, respectively. If the optional argument `TIMEOUT` is given and not false, then it should specify the number of seconds after which the wait is to be aborted (the value may be a floating point number). This procedure returns two values: the lists of file-descriptors ready for input and output, respectively. `READFDLIST` and WRITEFDLIST may also by file-descriptors instead of lists. In this case the returned values are booleans indicating whether input/output is ready by `#t` or `#f` otherwise. You can also pass `#f` as `READFDLIST` or `WRITEFDLIST` argument, which is equivalent to `()`.

#### file-write

`(file-write FILENO BUFFER [SIZE])` procedure

  Writes the contents of the string or bytevector `BUFFER` into the file with the file-descriptor `FILENO`. If the optional argument `SIZE` is given, then only the specified number of bytes are written.

#### file-control

`(file-control FILENO COMMAND [ARGUMENT])` procedure

  Performs the fcntl operation `COMMAND` with the given `FILENO` and optional `ARGUMENT`. The return value is meaningful depending on the `COMMAND`.

#### open-input-file*

#### open-output-file*

`(open-input-file* FILENO [OPENMODE])` procedure
`(open-output-file* FILENO [OPENMODE])` procedure

  Opens file for the file-descriptor `FILENO` for input or output and returns a port. `FILENO` should be a positive exact integer. `OPENMODE` specifies an additional mode for opening the file (currently only the keyword `#:append` is supported, which opens an output-file for appending).

#### port->fileno

`(port->fileno PORT)` procedure

  If `PORT` is a file- or tcp-port, then a file-descriptor is returned for this port. Otherwise an error is signaled.

### Retrieving file attributes

#### file-access-time

#### file-change-time

#### file-modification-time

`(file-access-time FILE)` procedure
`(file-change-time FILE)` procedure
`(file-modification-time FILE)` procedure
`(set! (file-modification-time FILE) SECONDS)` procedure

  Returns time (in seconds) of the last access, modification or change of `FILE`. `FILE` may be a filename or a file-descriptor. If the file does not exist, an error is signaled.

  `(set! (file-modification-time FILE) SECONDS)` sets the access- and modification time of `FILE` to `SECONDS`.

#### file-stat

`(file-stat FILE [LINK])` procedure

  Returns a 13-element vector with the following contents:

  index | value | field | notes
  --- | --- | --- | ---
  0 | inode number | `st_ino` |
  1 | mode | `st_mode` | bitfield combining file permissions and file type
  2 | number of hard links | `st_nlink` |
  3 | UID of owner | `st_uid` | as with `file-owner`
  4 | GID of owner | `st_gid` |
  5 | size | `st_size` | as with `file-size`
  6 | access time | `st_atime` | as with `file-access-time`
  7 | change time | `st_ctime` | as with `file-change-time`
  8 | modification time | `st_mtime` | as with `file-modification-time`
  9 | parent device ID | `st_dev` | ID of device on which this file resides
  10 | device ID | `st_rdev` | device ID for special files (i.e. the raw major/minor number)
  11 | block size | `st_blksize` |
  12 | number of blocks allocated | `st_blocks` |

  On Windows systems, the last 4 values are undefined.

  By default, symbolic links are followed and the status of the referenced file is returned; however, if the optional argument `LINK` is given and not `#f`, the status of the link itself is returned.

  Note that for very large files, the `file-size` value may be an inexact integer.

#### file-position

`(file-position FILE)` procedure

  Returns the current file position of `FILE`, which should be a port or a file-descriptor.

#### file-size

`(file-size FILE)` procedure

  Returns the size of the file designated by `FILE`. `FILE` may be a filename or a file-descriptor. If the file does not exist, an error is signaled. Note that for very large files, `file-size` may return an inexact integer.

#### regular-file?

`(regular-file? FILENAME)` procedure

  Returns true, if `FILENAME` names a regular file (not a directory, socket, etc.) This operation follows symbolic links; use either `symbolic-link?` or `file-type` if you need to test for symlinks.

#### file-owner

`(file-owner FILE)` procedure

  Returns the user-id of `FILE`. `FILE` may be a filename or a file-descriptor.

#### file-permissions

`(file-permissions FILE)` procedure

  Returns the permission bits for `FILE`. You can test this value by performing bitwise operations on the result and the `perm/...` values. `FILE` may be a filename or a file-descriptor.

#### file-read-access?

#### file-write-access?

#### file-execute-access?

`(file-read-access? FILENAME)` procedure
`(file-write-access? FILENAME)` procedure
`(file-execute-access? FILENAME)` procedure

  These procedures return `#t` if the current user has read, write or execute permissions on the file named `FILENAME`.

#### file-type

`(file-type FILE [LINK [ERROR]])` procedure

  Returns the file-type for `FILE`, which should be a filename or file-descriptor. If `LINK` is given and true, symbolic-links are not followed:

       regular-file
       directory
       fifo
       socket
       symbolic-link
       character-device
       block-device

  Note that not all types are supported on every platform. If `ERROR` is given and true, `file-type` signals an error if the file does not exist.

#### character-device?

#### block-device?

#### socket?

`(character-device? FILE)` procedure
`(block-device? FILE)` procedure
`(socket? FILE)` procedure

  These procedures return `#t` if `FILE` given is of the appropriate type. `FILE` may be a filename or a file-descriptor. Note that these operations follow symbolic links. If the file does not exist, `#f` is returned.

### Changing file attributes

#### file-truncate

`(file-truncate FILE OFFSET)` procedure

  Truncates the file `FILE` to the length `OFFSET`, which should be an integer. If the file-size is smaller or equal to `OFFSET` then nothing is done. `FILE` should be a filename or a file-descriptor.

#### set-file-position!

`(set-file-position! FILE POSITION [WHENCE])` procedure
`(set! (file-position FILE) POSITION)` procedure

  Sets the current read/write position of `FILE` to `POSITION`, which should be an exact integer. `FILE` should be a port or a file-descriptor. `WHENCE` specifies how the position is to interpreted and should be one of the values `seek/set, seek/cur` and `seek/end`. It defaults to `seek/set`.

  Exceptions: `(exn bounds)`, `(exn i/o file)`

#### change-file-mode

`(change-file-mode FILENAME MODE)` procedure

  Changes the current file mode of the file named `FILENAME` to `MODE` using the `chmod()` system call. The `perm/...` variables contain the various permission bits and can be combinded with the `bitwise-ior` procedure.

#### change-file-owner

`(change-file-owner FILENAME UID GID)` procedure

  Changes the owner information of the file named `FILENAME` to the user- and group-ids `UID` and `GID` (which should be exact integers) using the `chown()` system call.

#### file-creation-mode

`(file-creation-mode [MODE])` procedure

  Returns the initial file permissions used for newly created files (as with `umask(2)`). If `MODE` is supplied, the mode is changed to this value. You can set the mode by executing

       (set! (file-creation-mode) MODE)

  or

       (file-creation-mode MODE)

  where `MODE` is a bitwise combination of one or more of the `perm/...` flags.

### Processes

#### current-process-id

`(current-process-id)` procedure

  Returns the process ID of the current process.

#### parent-process-id

`(parent-process-id)` procedure

  Returns the process ID of the parent of the current process.

#### process-group-id

`(process-group-id PID)` procedure

  Returns the process group ID of the process specified by `PID`.

#### process-execute

`(process-execute PATHNAME [ARGUMENT-LIST [ENVIRONMENT-LIST]])` procedure

  Replaces the running process with a new process image from the program stored at `PATHNAME`, using the C library function `execvp(3)`. If the optional argument `ARGUMENT-LIST` is given, then it should contain a list of strings which are passed as arguments to the subprocess. If the optional argument `ENVIRONMENT-LIST` is supplied, then the library function `execve(2)` is used, and the environment passed in `ENVIRONMENT-LIST` (which should be of the form `("<NAME>=<VALUE>" ...)` is given to the invoked process. Note that `execvp(3)` respects the current setting of the `PATH` environment variable while `execve(3)` does not.

  This procedure never returns; it either replaces the process with a new one or it raises an exception in case something went wrong executing the program.

#### process-fork

`(process-fork [THUNK [KILLOTHERS?]])` procedure

  Creates a new child process with the UNIX system call `fork()`. Returns either the PID of the child process or 0. If `THUNK` is given, then the child process calls it as a procedure with no arguments and terminates. If `THUNK` is given and the optional argument `KILLOTHERS?` is true, then kill all other existing threads in the child process, leaving only the current thread to run `THUNK` and terminate.

#### process-run

`(process-run COMMANDLINE)` procedure
`(process-run COMMAND ARGUMENT-LIST)` procedure

  Creates a new child process. The PID of the new process is returned.

  - The single parameter version passes the `COMMANDLINE` to the system shell, so usual argument expansion can take place.
  - The multiple parameter version directly invokes the `COMMAND` with the `ARGUMENT-LIST`.

#### process-signal

`(process-signal PID [SIGNAL])` procedure

  Sends `SIGNAL` to the process with the id `PID` using the UNIX system call `kill()`. `SIGNAL` defaults to the value of the variable `signal/term`.

#### process-wait

`(process-wait [PID [NOHANG]])` procedure

  Suspends the current process until the child process with the id `PID` has terminated using the UNIX system call `waitpid()`. If `PID` is not given, then this procedure waits for any child process. If `NOHANG` is given and not `#f` then the current process is not suspended. This procedure returns three values:

  - `PID` or 0, if `NOHANG` is true and the child process has not terminated yet.
  - `#t` if the process exited normally or `#f` otherwise.
  - either the exit status, if the process terminated normally or the signal number that terminated/stopped the process.

  Note that suspending the current process implies that all threads are suspended as well.

#### process

`(process COMMANDLINE)` procedure
`(process COMMAND ARGUMENT-LIST [ENVIRONMENT-LIST])` procedure

  Creates a subprocess and returns three values: an input port from which data written by the sub-process can be read, an output port from which any data written to will be received as input in the sub-process and the process-id of the started sub-process. Blocking reads and writes to or from the ports returned by `process` only block the current thread, not other threads executing concurrently.

  Standard error for the subprocess is linked up to the current process's standard error (see `process*` if you want to reify its standard error into a separate port).

  - The single parameter version passes the string `COMMANDLINE` to the host-system's shell that is invoked as a subprocess.
  - The multiple parameter version directly invokes the `COMMAND` as a subprocess. The `ARGUMENT-LIST` is directly passed, as is `ENVIRONMENT-LIST`.

  Not using the shell may be preferrable for security reasons.

  Once both the input- and output ports are closed, an implicit `waitpid(3)` is done to wait for the subprocess to finish or to reap a subprocess that has terminated. If the subprocess has not finished, waiting for it will necessarily block all executing threads.

#### process*

`(process* COMMANDLINE)` procedure
`(process* COMMAND ARGUMENT-LIST [ENVIRONMENT-LIST])` procedure

  Like `process` but returns 4 values: an input port from which data written by the sub-process can be read, an output port from which any data written to will be received as input in the sub-process, the process-id of the started sub-process, and an input port from which data written by the sub-process to `stderr` can be read.

#### sleep

`(sleep SECONDS)` procedure

  Puts the process to sleep for `SECONDS`. Returns either 0 if the time has completely elapsed, or the number of remaining seconds, if a signal occurred.

#### create-session

`(create-session)` procedure

  Creates a new session if the calling process is not a process group leader and returns the session ID.

### Hard and symbolic links

#### symbolic-link?

`(symbolic-link? FILENAME)` procedure

  Returns true, if `FILENAME` names a symbolic link. If no such file exists, `#f` is returned. This operation does not follow symbolic links itself.

#### create-symbolic-link

`(create-symbolic-link OLDNAME NEWNAME)` procedure

  Creates a symbolic link with the filename `NEWNAME` that points to the file named `OLDNAME`.

#### read-symbolic-link

`(read-symbolic-link FILENAME [CANONICALIZE])` procedure

  Returns the filename to which the symbolic link `FILENAME` points. If `CANONICALIZE` is given and true, then symbolic links are resolved repeatedly until the result is not a link.

#### file-link

`(file-link OLDNAME NEWNAME)` procedure

  Creates a hard link from `OLDNAME` to `NEWNAME` (both strings).

### Retrieving user & group information

#### current-user-id

`(current-user-id)` procedure

      [setter] (set! (current-user-id) UID)

  Get or set the real user-id of the current process. The procedure corresponds to the getuid and setuid C functions.

#### current-effective-user-id

`(current-effective-user-id)` procedure

      [setter] (set! (current-effective-user-id) UID)

  Get or set the effective user-id of the current process.

#### user-information

`(user-information USER [AS-VECTOR])` procedure

  If `USER` specifes a valid username (as a string) or user ID, then the user database is consulted and a list of 7 values are returned: the user-name, the encrypted password, the user ID, the group ID, a user-specific string, the home directory and the default shell. When `AS-VECTOR` is `#t` a vector of 7 elements is returned instead of a list. If no user with this name or id then `#f` is returned.

  Note: on Android systems, the user-specific string is always `""`, since `pw_gecos` is not available in the C `passwd` struct on that platform.

#### current-group-id

`(current-group-id)` procedure

      [setter] (set! (current-group-id) GID)

  Get or set the real group-id of the current process.

#### current-effective-group-id

`(current-effective-group-id)` procedure

      [setter] (set! (current-effective-group-id) GID)

  Get or set the effective group-id of the current process. ID can be found, then `#f` is returned.

#### group-information

`(group-information GROUP)` procedure

  If `GROUP` specifies a valid group-name or group-id, then this procedure returns a list of four values: the group-name, the encrypted group password, the group ID and a list of the names of all group members. If no group with the given name or ID exists, then `#f` is returned.

#### get-groups

`(get-groups)` procedure

  Returns a list with the supplementary group IDs of the current user.

### Changing user & group information

#### set-groups!

`(set-groups! GIDLIST)` procedure

  Sets the supplementrary group IDs of the current user to the IDs given in the list `GIDLIST`.

  Only the superuser may invoke this procedure.

#### initialize-groups

`(initialize-groups USERNAME BASEGID)` procedure

  Sets the supplementrary group IDs of the current user to the IDs from the user with name `USERNAME` (a string), including `BASEGID`.

  Only the superuser may invoke this procedure.

#### set-process-group-id!

`(set-process-group-id! PID PGID)` procedure

      [setter] (set! (process-group-id PID) PGID)

  Sets the process group ID of the process specifed by `PID` to `PGID`.

### Record locking

#### file-lock

`(file-lock PORT [START [LEN]])` procedure

  Locks the file associated with `PORT` for reading or writing (according to whether `PORT` is an input- or output-port). `START` specifies the starting position in the file to be locked and defaults to 0. `LEN` specifies the length of the portion to be locked and defaults to `#t`, which means the complete file. `file-lock` returns a lock-object.

#### file-lock/blocking

`(file-lock/blocking PORT [START [LEN]])` procedure

  Similar to `file-lock`, but if a lock is held on the file, the current process blocks (including all threads) until the lock is released.

#### file-test-lock

`(file-test-lock PORT [START [LEN]])` procedure

  Tests whether the file associated with `PORT` is locked for reading or writing (according to whether `PORT` is an input- or output-port) and returns either `#f` or the process-id of the locking process.

#### file-unlock

`(file-unlock LOCK)` procedure

  Unlocks the previously locked portion of a file given in `LOCK`.

### Signal handling

#### set-alarm!

`(set-alarm! SECONDS)` procedure

  Sets an internal timer to raise the `signal/alrm` after `SECONDS` are elapsed. You can use the `set-signal-handler!` procedure to write a handler for this signal.

#### set-signal-handler!

#### signal-handler

`(signal-handler SIGNUM)` procedure

  Returns the signal handler for the code `SIGNUM` or `#f`.

`(set-signal-handler! SIGNUM PROC)` procedure

  Establishes the procedure of one argument `PROC` as the handler for the signal with the code `SIGNUM`. `PROC` is called with the signal number as its sole argument. If the argument `PROC` is `#f` then any signal handler will be removed, and the corresponding signal set to `SIG_IGN`.

  Notes

  - it is unspecified in which thread of execution the signal handler will be invoked.
  - when signals arrive in quick succession (specifically, before the handler for a signal has been started), then signals will be queued (up to a certain limit); the order in which the queued signals will be handled is not specified
  - `(set! (signal-handler SIG) PROC)` can be used as an alternative to `(set-signal-handler! SIG PROC)`
  - Any signal handlers for the signals `signal/segv`, `signal/bus`, `signal/fpe` and `signal/ill` will be ignored and these signals will always trigger an exception, unless the executable was started with the `-:S` runtime option. This feature is only available on platforms that support the `sigprocmask(3)` POSIX API function.

#### set-signal-mask!

`(set-signal-mask! SIGLIST)` procedure

  Sets the signal mask of the current process to block all signals given in the list `SIGLIST`. Signals masked in that way will not be delivered to the current process.

#### signal-mask

`(signal-mask)` procedure

  Returns the signal mask of the current process.

#### signal-masked?

`(signal-masked? SIGNUM)` procedure

  Returns whether the signal for the code `SIGNUM` is currently masked.

#### signal-mask!

`(signal-mask! SIGNUM)` procedure

  Masks (blocks) the signal for the code `SIGNUM`.

#### signal-unmask!

`(signal-unmask! SIGNUM)` procedure

  Unmasks (unblocks) the signal for the code `SIGNUM`.

#### Signal codes

`signal/term` constant
`signal/kill` constant
`signal/int` constant
`signal/hup` constant
`signal/fpe` constant
`signal/ill` constant
`signal/segv` constant
`signal/abrt` constant
`signal/trap` constant
`signal/quit` constant
`signal/alrm` constant
`signal/vtalrm` constant
`signal/prof` constant
`signal/io` constant
`signal/urg` constant
`signal/chld` constant
`signal/cont` constant
`signal/stop` constant
`signal/tstp` constant
`signal/pipe` constant
`signal/xcpu` constant
`signal/xfsz` constant
`signal/usr1` constant
`signal/usr2` constant
`signal/bus` constant
`signal/winch` constant
`signal/break` constant

  These variables contain signal codes for use with `process-signal`, `set-signal-handler!`, `signal-handler`, `signal-masked?`, `signal-mask!`, or `signal-unmask!`.

### Environment access

#### get-environment-variables

`(get-environment-variables)` procedure

  Returns a association list of the environment variables and their current values (see also SRFI-98).

#### setenv

`(setenv VARIABLE VALUE)` procedure

  Sets the environment variable named `VARIABLE` to `VALUE`. Both arguments should be strings. If the variable is not defined in the environment, a new definition is created.

#### unsetenv

`(unsetenv VARIABLE)` procedure

  Removes the definition of the environment variable `VARIABLE` from the environment of the current process. If the variable is not defined, nothing happens.

### Memory mapped I/O

Memory mapped I/O takes the contents of a file descriptor and places them in memory.

#### memory-mapped-file?

`(memory-mapped-file? X)` procedure

  Returns `#t`, if `X` is an object representing a memory mapped file, or `#f` otherwise.

#### map-file-to-memory

`(map-file-to-memory ADDRESS LEN PROTECTION FLAG FILENO [OFFSET])` procedure

  Maps a section of a file to memory using the C function `mmap()`. `ADDRESS` should be a foreign pointer object or `#f`; `LEN` specifies the size of the section to be mapped; `PROTECTION` should be one or more of the flags `prot/read, prot/write, prot/exec` or `prot/none` bitwise-iored together; `FLAG` should be one or more of the flags `map/fixed, map/shared, map/private, map/anonymous` or `map/file`; `FILENO` should be the file-descriptor of the mapped file. The optional argument `OFFSET` gives the offset of the section of the file to be mapped and defaults to 0. This procedure returns an object representing the mapped file section. The procedure `move-memory!` can be used to access the mapped memory.

#### memory-mapped-file-pointer

`(memory-mapped-file-pointer MMAP)` procedure

  Returns a machine pointer to the start of the memory region to which the file is mapped.

#### unmap-file-from-memory

`(unmap-file-from-memory MMAP [LEN])` procedure

  Unmaps the section of a file mapped to memory using the C function `munmap()`. `MMAP` should be a mapped file as returned by the procedure `map-file-to-memory`. The optional argument `LEN` specifies the length of the section to be unmapped and defaults to the complete length given when the file was mapped.

#### Memory Mapped I/O Example

    ;; example-mmap.scm
    ;;
    ;; basic example of memory mapped I/O
    ;;
    ;; This example does no error checking or cleanup, and serves
    ;; only to demonstrate how the mmap functions work together.
    ;;
    (use posix)
    (use lolevel)

           ; open a file using the posix module, so we have the file descriptor.
    (let* ((fd   (file-open "example-mmap.scm" (+ open/rdonly open/nonblock)))
           ; fstat(2) the file descriptor fd to determine its size
           (size (file-size fd))
           ; mmap(2) the file for reading.
           (mmap (map-file-to-memory #f
                                     size
                                     prot/read
                                     (+ map/file map/shared)
                                     fd))
           ; return a pointer object to the beginning of the memory map.
           (buf  (memory-mapped-file-pointer mmap))
           ; allocate a string the same size as the file.
           (str  (make-string size)))
      ; copy the mapped memory into a string
      (move-memory! buf str size)
      (display str)
      ; alternately, print the string byte-by-byte without copying.
      (let loop ((p buf)
                 (i 0))
        (unless (= i size)
          (display (integer->char (pointer-s8-ref p)))
          (loop (pointer+ p 1) (+ i 1)))))

### Date and time routines

#### seconds->local-time

`(seconds->local-time [SECONDS])` procedure

  Breaks down the time value represented in `SECONDS` into a 10 element vector of the form `#(seconds minutes hours mday month year wday yday dstflag timezone)`, in the following format:

  seconds (0)
    the number of seconds after the minute (0 - 59)
  minutes (1)
    the number of minutes after the hour (0 - 59)
  hours (2)
    the number of hours past midnight (0 - 23)
  mday (3)
    the day of the month (1 - 31)
  month (4)
    the number of months since january (0 - 11)
  year (5)
    the number of years since 1900
  wday (6)
    the number of days since Sunday (0 - 6)
  yday (7)
    the number of days since January 1 (0 - 365)
  dstflag (8)
    a flag that is true if Daylight Saving Time is in effect at the time described.
  timezone (9)
    the difference between UTC and the latest local standard time, in seconds west of UTC.

  `SECONDS` defaults to the value of `(current-seconds)`.

#### local-time->seconds

`(local-time->seconds VECTOR)` procedure

  Converts the ten-element vector `VECTOR` representing the time value relative to the current timezone into the number of seconds since the first of January, 1970 UTC.

#### local-timezone-abbreviation

`(local-timezone-abbreviation)` procedure

  Returns the abbreviation for the local timezone as a string.

#### seconds->string

`(seconds->string [SECONDS])` procedure

  Converts the time represented in `SECONDS` into a local-time string of the form `"Tue May 21 13:46:22 1991"`. `SECONDS` defaults to the value of `(current-seconds)`.

#### seconds->utc-time

`(seconds->utc-time [SECONDS])` procedure

  Similar to `seconds->local-time`, but interpretes `SECONDS` as UTC time. `SECONDS` defaults to the value of `(current-seconds)`.

#### utc-time->seconds

`(utc-time->seconds VECTOR)` procedure

  Converts the ten-element vector `VECTOR` representing the UTC time value into the number of seconds since the first of January, 1970 UTC.

#### time->string

`(time->string VECTOR [FORMAT])` procedure

  Converts the broken down time represented in the 10 element vector `VECTOR` into a string of the form represented by the `FORMAT` string. The default time form produces something like `"Tue May 21 13:46:22 1991"`.

  The `FORMAT` string follows the rules for the C library procedure `strftime`. The default `FORMAT` string is "%a %b %e %H:%M:%S %Z %Y".

#### string->time

`(string->time TIME [FORMAT])` procedure

  Converts a string of the form represented by the `FORMAT` string into the broken down time represented in a 10 element vector. The default time form understands something like `"Tue May 21 13:46:22 1991"`.

  The `FORMAT` string follows the rules for the C library procedure `strptime`. The default `FORMAT` string is "%a %b %e %H:%M:%S %Z %Y".

### Raw exit

#### _exit

`(_exit [CODE])` procedure

  Exits the current process without flushing any buffered output (using the C function `_exit`). Note that the `exit-handler` is not called when this procedure is invoked. The optional return-code `CODE` defaults to `0`.

### ERRNO values

`errno/perm` constant
`errno/noent` constant
`errno/srch` constant
`errno/intr` constant
`errno/io` constant
`errno/noexec` constant
`errno/badf` constant
`errno/child` constant
`errno/nomem` constant
`errno/acces` constant
`errno/fault` constant
`errno/busy` constant
`errno/notdir` constant
`errno/isdir` constant
`errno/inval` constant
`errno/mfile` constant
`errno/nospc` constant
`errno/spipe` constant
`errno/pipe` constant
`errno/again` constant
`errno/rofs` constant
`errno/exist` constant
`errno/wouldblock` constant

  These variables contain error codes as returned by `errno`.

### Finding files

#### find-files

`(find-files DIRECTORY #!key test action seed limit dotfiles follow-symlinks)` procedure

  Recursively traverses the contents of `DIRECTORY` (which should be a string) and invokes the procedure `action` for all files in which the procedure `test` is true. `test` may be a procedure of one argument or an irregex object, regex string or SRE expression that will be matched with a full pathname using `irregex-match`. `action` should be a procedure of two arguments: the currently encountered file and the result of the previous invocation of `action`, or, if this is the first invocation, the value of `seed`. `test` defaults to `(constantly #t)`, `action` defaults to `cons`, `seed` defaults to `()`. `limit` should be a procedure of one argument that is called for each nested directory and which should return true, if that directory is to be traversed recursively. `limit` may also be an exact integer that gives the maximum recursion depth. For example, a depth of `0` means that only files in the top-level, specified directory are to be traversed. In this case, all nested directories are ignored. `limit` may also be `#f` (the default), which is equivalent to `(constantly #t)`.

  If `dotfiles` is given and true, then files starting with a "`.`" character will not be ignored (but note that "`.`" and "`..`" are always ignored). if `follow-symlinks` is given and true, then the traversal of a symbolic link that points to a directory will recursively traverse the latter. By default, symbolic links are not followed.

  Note that `action` is called with the full pathname of each file, including the directory prefix.

  This procedure's signature was changed in CHICKEN 4.6. In older versions, `find-files` has a different signature:

       (find-files DIRECTORY [TEST [ACTION [SEED [LIMIT]]]])

  The old signature was supported until CHICKEN 4.7.3 for compatibility reasons, at which point it became invalid. The optional arguments are ignored and use their default values, and no warning is issued. One symptom is that your `TEST` does not work, returning every file.

### Getting the hostname and system information

#### get-host-name

`(get-host-name)` procedure

  Returns the hostname of the machine that this process is running on.

#### system-information

`(system-information)` procedure

  Invokes the UNIX system call `uname()` and returns a list of 5 values: system-name, node-name, OS release, OS version and machine.

### Setting the file buffering mode

#### set-buffering-mode!

`(set-buffering-mode! PORT MODE [BUFSIZE])` procedure

  Sets the buffering-mode for the file associated with `PORT` to `MODE`, which should be one of the keywords `#:full`, `#:line` or `#:none`. If `BUFSIZE` is specified it determines the size of the buffer to be used (if any).

### Terminal ports

#### terminal-name

`(terminal-name PORT)` procedure

  Returns the name of the terminal that is connected to `PORT`.

#### terminal-port?

`(terminal-port? PORT)` procedure

  Returns `#t` if `PORT` is connected to a terminal and `#f` otherwise.

#### terminal-size

`(terminal-size PORT)` procedure

  Returns two values, the number of columns and rows of the terminal that is connected to `PORT` or `0`, `0` if the terminal size can not be obtained. On Windows, this procedure always returns `0`, `0`.

### How Scheme procedures relate to UNIX C functions

`change-directory`
  `chdir`
`change-directory*`
  `fchdir`
`change-file-mode`
  `chmod`
`change-file-owner`
  `chown`
`create-directory`
  `mkdir`
`create-fifo`
  `mkfifo`
`create-pipe`
  `pipe`
`create-session`
  `setsid`
`create-symbolic-link`
  `link`
`current-directory`
  `curdir`
`current-effective-group-id`
  `getegid`
`current-effective-user-id`
  `geteuid`
`current-group-id`
  `getgid`
`current-parent-id`
  `getppid`
`current-process-id`
  `getpid`
`current-user-id`
  `getuid`
`delete-directory`
  `rmdir`
`duplicate-fileno`
  `dup/dup2`
`_exit`
  `_exit`
`file-close`
  `close`
`file-access-time`
  `stat`
`file-change-time`
  `stat`
`file-creation-mode`
  `umask`
`file-modification-time`
  `stat`
`file-execute-access?`
  `access`
`file-open`
  `open`
`file-lock`
  `fcntl`
`file-position`
  `ftell/lseek`
`file-read`
  `read`
`file-read-access?`
  `access`
`file-select`
  `select`
`file-control`
  `fcntl`
`file-stat`
  `stat`
`file-test-lock`
  `fcntl`
`file-truncate`
  `truncate/ftruncate`
`file-unlock`
  `fcntl`
`file-write`
  `write`
`file-write-access?`
  `access`
`get-groups`
  `getgroups`
`get-host-name`
  `gethostname`
`initialize-groups`
  `initgroups`
`local-time->seconds`
  `mktime`
`local-timezone-abbreviation`
  `localtime`
`map-file-to-memory`
  `mmap`
`open-input-file*`
  `fdopen`
`open-output-file*`
  `fdopen`
`open-input-pipe`
  `popen`
`open-output-pipe`
  `popen`
`port->fileno`
  `fileno`
`process-execute`
  `execvp`
`process-fork`
  `fork`
`process-group-id`
  `getpgid`
`process-signal`
  `kill`
`process-wait`
  `waitpid`
`close-input-pipe`
  `pclose`
`close-output-pipe`
  `pclose`
`read-symbolic-link`
  `readlink`
`seconds->local-time`
  `localtime`
`seconds->string`
  `ctime`
`seconds->utc-time`
  `gmtime`
`set-alarm!`
  `alarm`
`set-buffering-mode!`
  `setvbuf`
`set-file-position!`
  `fseek/seek`
`set-groups!`
  `setgroups`
`set-signal-mask!`
  `sigprocmask`
`set-group-id!`
  `setgid`
`set-process-group-id!`
  `setpgid`
`set-user-id!`
  `setuid`
`set-root-directory!`
  `chroot`
`setenv`
  `setenv/putenv`
`sleep`
  `sleep`
`system-information`
  `uname`
`terminal-name`
  `ttyname`
`terminal-port?`
  `isatty`
`time->string`
  `asctime`
`unsetenv`
  `putenv`
`unmap-file-from-memory`
  `munmap`
`user-information`
  `getpwnam/getpwuid`
`utc-time->seconds`
  `timegm`

### Windows specific notes

Use of UTF8 encoded strings is for pathnames is not supported. Windows uses a 16-bit UNICODE encoding with special system calls for wide-character support. Only single-byte string encoding can be used.

#### Procedure Changes

Exceptions to the above procedure definitions.

`(create-pipe [MODE])` procedure

  The optional parameter `MODE`, default `open/binary | open/noinherit`. This can be `open/binary` or `open/text`, optionally or'ed with `open/noinherit`.

`(process-wait [PID [NOHANG]])` procedure

  `process-wait` always returns `#t` for a terminated process and only the exit status is available. (Windows does not provide signals as an interprocess communication method.)

`(process-execute PATHNAME [ARGUMENT-LIST [ENVIRONMENT-LIST [EXACT-FLAG]]])` procedure
`(process COMMAND ARGUMENT-LIST [ENVIRONMENT-LIST [EXACT-FLAG]])` procedure
`(process* COMMAND ARGUMENT-LIST [ENVIRONMENT-LIST [EXACT-FLAG]])` procedure

  The optional parameter `EXACT-FLAG`, default `#f`. When `#f` any argument string with embedded whitespace will be wrapped in quotes. When `#t` no such wrapping occurs.

#### Unsupported Definitions

The following definitions are not supported for native Windows builds (compiled with the Microsoft tools or with MinGW):

    open/noctty  open/nonblock  open/fsync  open/sync
    perm/isvtx  perm/isuid  perm/isgid
    file-select file-control
    signal/... (except signal/term, signal/int, signal/fpe, signal/ill, signal/segv, signal/abrt, signal/break)
    set-signal-mask!  signal-mask  signal-masked?  signal-mask!  signal-unmask!
    user-information  group-information  get-groups  set-groups!  initialize-groups
    errno/wouldblock
    change-directory*
    change-file-owner
    current-user-id  current-group-id  current-effective-user-id  current-effective-group-id
    set-user-id!  set-group-id!
    create-session
    process-group-id  set-process-group-id!
    create-symbolic-link  read-symbolic-link
    file-truncate
    file-lock  file-lock/blocking  file-unlock  file-test-lock
    create-fifo  fifo?
    set-alarm!
    terminal-port?  terminal-name
    process-fork  process-signal
    parent-process-id
    set-root-directory!
    utc-time->seconds

#### Additional Definitions

Only available for Windows

- open/noinherit

This variable is a mode value for `create-pipe`. Useful when spawning a child process.

- spawn/overlay
- spawn/wait
- spawn/nowait
- spawn/nowaito
- spawn/detach

These variables contains special flags that specify the exact semantics of `process-spawn`: `spawn/overlay` replaces the current process with the new one. `spawn/wait` suspends execution of the current process until the spawned process returns. `spawn/nowait` does the opposite (`spawn/nowaito` is identical, according to the Microsoft documentation) and runs the process asynchronously. `spawn/detach` runs the new process in the background, without being attached to a console.

#### process-spawn

`(process-spawn MODE COMMAND [ARGUMENT-LIST [ENVIRONMENT-LIST [EXACT-FLAG]]])` procedure

  Creates and runs a new process with the given `COMMAND` filename and the optional `ARGUMENT-LIST` and `ENVIRONMENT-LIST`. `MODE` specifies how exactly the process should be executed and must be one or more of the `spawn/...` flags defined above.

  The `EXACT-FLAG`, default `#f`, controls quote-wrapping of argument strings. When `#t` quote-wrapping is not performed.

  Returns:

  - the exit status when synchronous
  - the PID when asynchronous
  - -1 when failure

Previous: Unit srfi-69

Next: Unit utils