#
Chapter 10
Miscellaneous routines

## 10.1 Integer bitwise ops

`(arithmetic-shift i j)` ---> integer (procedure)
`(bitwise-and i j)` ---> integer (procedure)
`(bitwise-ior i j)` ---> integer (procedure)
`(bitwise-not i)` ---> integer (procedure)
`(bitwise-xor i j)` ---> integer (procedure)

> These operations operate on integers representing semi-infinite bit strings, using a 2's-complement encoding.

> `arithmetic-shift` shifts i by j bits. A left shift is j > 0; a right shift is j < 0.

## 10.2 Password encryption

`(crypt key salt)` ---> encrypted value (procedure)

Decrypts key by directly calling the `crypt` function using salt to perturb the hashing algorithm. Salt must be a two-character string consisting of digits, alphabetic characters, ``.'' or ```\`''. The length of key may be at most eight.

## 10.3 Dot-Locking

Section 3.2.8 already points out that POSIX's file locks are almost useless in practice. To bypass this restriction other advisory locking mechanisms, based only on standard file operations, where invented. One of them is the so-called dot-locking scheme where the lock of file-name is represented by the file file-name`.lock`. Care is taken that only one process may generate the lock for a given file.

Here is scsh's interface to dot-locking:

`(obtain-dot-lock file-name [interval retry-number stale-time])` ---> boolean (procedure)

> Tries to obtain the lock for file-name. If the file is already locked, the thread sleeps for interval seconds (default is 1) before it retries. If the lock cannot be obtained after retry-number attempts, the procedure returns `#f`, otherwise `#t`. The default value of retry-number is `#f` which corresponds to an infinite number of retires.

> If stale-time is non-`#f`, it specifies the minimum age a lock may have (in seconds) before it is considered stale. `Obtain-dot-lock` attempts to delete stale locks. If it was succcessful obtaining a lock after breaking it, `obtain-dot-lock` returns `broken`. If stale-time is `#f`, `obtain-dot-lock` never considers a lock stale. The default for stale-time is 300.

> Note that it is possible that `obtain-dot-lock` breaks a lock but nevertheless fails to obtain it otherwise. If it is necessary to handle this case specially, use `break-dot-lock` directly (see below) rather than specifying a non-`#f` stale-time

`(break-dot-lock file-name)` ---> undefined (procedure)

> Breaks the lock for file-name if one exists. Note that breaking a lock does not imply a subsequent `obtain-dot-lock` will succeed, as another party may have acquired the lock between `break-dot-lock` and `obtain-dot-lock`.

`(release-dot-lock file-name)` ---> boolean (procedure)

> Releases the lock for file-name. On success, `release-dot-lock` returns `#t`, otherwise `#f`. Note that this procedure can also be used to break the lock for file-name.

`(with-dot-lock* file-name thunk)` ---> value(s) of thunk (procedure)
`(with-dot-lock file-name body `...`)` ---> value(s) of body (syntax)

> The procedure `with-dot-lock*` obtains the requested lock, and then calls `(thunk)`. When thunk returns, the lock is released. A non-local exit (e.g., throwing to a saved continuation or raising an exception) also causes the lock to be released.

> After a normal return from thunk, its return values are returned by `with-dot-lock*`. The `with-dot-lock` special form is equivalent syntactic sugar.

## 10.4 Syslog facility

(Note: the functionality presented in this section is still somewhat experimental and thus subject to interface changes.)

The procedures in this section provide access to the 4.2BSD syslog facility present in most POSIX systems. The functionality is in a structure called `syslog`. There's an additional structure `syslog-channels` documented below. The scsh interface to the syslog facility differs significantly from that of the Unix library functionality in order to support multiple simultaneous connections to the syslog facility.

Log messages carry a variety of parameters beside the text of the message itself, namely a set of options controlling the output format and destination, the facility identifying the class of programs the message is coming from, an identifier specifying the conrete program, and the level identifying the importance of the message. Moreover, a log mask can prevent messages at certain levels to be actually sent to the syslog daemon.

### Log options

A log option specifies details of the I/O behavior of the syslog facility. A syslog option is an element of a finite type (see the Scheme 48 manual) constructed by the `syslog-option` macro. The syslog facility works with sets of options which are represented as enum sets (see the Scheme 48 manual).

`(syslog-option option-name)` ---> option (syntax)

`(syslog-option? x)` ---> boolean (procedure)

`(make-syslog-options list)` ---> options (procedure)

`(syslog-options option-name `...`)` ---> options (syntax)

`(syslog-options? x)` ---> boolean (procedure)

> `Syslog-option` constructs a log option from the name of an option. (The possible names are listed below.) `Syslog-option?` is a predicate for log options. Options are comparable using `eq?`. `Make-syslog-options` constructs a set of options from a list of options. `Syslog-options` is a macro which expands into an expression returning a set of options from names. `Syslog-options?` is a predicate for sets of options.

Here is a list of possible names of syslog options:

`console`
  If syslog cannot pass the message to syslogd it will attempt to write the message to the console.

`delay`
  Delay opening the connection to syslogd immediately until the first message is logged.

`no-delay`
  Open the connection to syslogd immediately. Normally the open is delayed until the first message is logged. Useful for programs that need to manage the order in which file descriptors are allocated.

  NOTA BENE: The `delay` and `no-delay` options are included for completeness, but do not have the expected effect in the present Scheme interface: Because the Scheme interface has to multiplex multiple simultaneous connections to the syslog facility over a single one, open and close operations on that facility happen at unpredictable times.

`log-pid`
  Log the process id with each message: useful for identifying instantiations of daemons.

### Log facilities

A log facility identifies the originator of a log message from a finite set known to the system. Each originator is identified by a name:

`(syslog-facility facility-name)` ---> facility (syntax)

`(syslog-facility? x)` ---> boolean (procedure)

> `Syslog-facility` is macro that expands into an expression returning a facility for a given name. `Syslog-facility?` is a predicate for facilities. Facilities are comparable via `eq?`.

Here is a list of possible names of syslog facilities:

`authorization`
  The authorization system: login, su, getty, etc.

`cron`
  The cron daemon.

`daemon`
  System daemons, such as routed, that are not provided for explicitly by other facilities.

`kernel`
  Messages generated by the kernel.

`lpr`
  The line printer spooling system: lpr, lpc, lpd, etc.

`mail`
  The mail system.

`news`
  The network news system.

`user`
  Messages generated by random user processes.

`uucp`
  The uucp system.

`local0` `local1` `local2` `local3` `local4` `local5` `local6` `local7`
  Reserved for local use.

### Log levels

A log level identifies the importance of a message from a fixed set of possible levels.

`(syslog-level level-name)` ---> level (syntax)

`(syslog-level? x)` ---> boolean (procedure)

> `Syslog-level` is macro that expands into an expression returning a facility for a given name. `Syslog-level?` is a predicate for facilities. Levels are comparable via `eq?`.

Here is a list of possible names of syslog levels:

`emergency`
  A panic condition. This is normally broadcast to all users.

`alert`
  A condition that should be corrected immediately, such as a corrupted system database.

`critical`
  Critical conditions, e.g., hard device errors.

`error`
  Errors.

`warning`
  Warning messages.

`notice`
  Conditions that are not error conditions, but should possibly be handled specially.

`info`
  Informational messages.

`debug`
  Messages that contain information normally of use only when debugging a program.

### Log masks

A log masks can mask out log messages at a set of levels. A log mask is an enum set of log levels.

`(make-syslog-mask list)` ---> mask (procedure)

`(syslog-mask level-name `...`)` ---> mask (syntax)

`syslog-mask-all` mask

`(syslog-mask-upto level)` ---> mask (procedure)

`(syslog-mask? x)` ---> boolean (procedure)

> `Make-syslog-mask` constructs a mask from a list of levels. `Syslog-mask` is a macro which constructs a mask from names of levels. `Syslog-mask-all` is a predefined log mask containing all levels. `Syslog-mask-upto` returns a mask consisting of all levels up to and including a certain level, starting with `emergency`.

### Logging

Scheme 48 dynamically maintains implicit connections to the syslog facility specifying a current identifier, current options, a current facility and a current log mask. This implicit connection is held in a thread fluid (see Section 9.5). Hence, every thread maintains it own implicit connection to syslog. Note that the connection is not implicitly preserved across a `spawn`, but it is preserved across a `fork-thread`:

`(with-syslog-destination string options facility mask thunk)` ---> value (procedure)

`(set-syslog-destination! string options facility mask)` ---> undefined (procedure)

> `With-syslog-destination` dynamically binds parameters of the implicit connection to the syslog facility and runs thunk within those parameter bindings, returning what thunk returns. Each of the parameters may be `#f` in which case the previous values will be used. `Set-syslog-destination!` sets the parameters of the implicit connection of the current thread.

`(syslog level message)` ---> undefined (procedure)

`(syslog level message [string options syslog-facility])` ---> undefined (procedure)

> `Syslog` actually logs a message. Each of the parameters of the implicit connection (except for the log mask) can be explicitly specified as well for the current call to `syslog`, overriding the parameters of the channel. The parameters revert to their original values after the call.

### Syslog channels

The `syslog-channels` structure allows direct manipulation of syslog channels, the objects that represent connections to the syslog facility. Note that it is not necessary to explicitly open a syslog channel to do logging.

`(open-syslog-channel string options facility mask)` ---> channel (procedure)

`(close-syslog-channel channel)` ---> undefined (procedure)

`(syslog level message channel)` ---> undefined (procedure)

> `Open-syslog-channel` and `close-syslog-channel` create and destroy a connection to the syslog facility, respectively. The specified form of calling `syslog` logs to the specified channel.

## 10.5 MD5 interface

Scsh provides a direct interface to the MD5 functions to compute the ``fingerprint'' or ``message digest'' of a file or string. It uses the C library written by Colin Plum.

`(md5-digest-for-string string)` ---> md5-digest (procedure)

> Calculates the MD5 digest for the given string.

`(md5-digest-for-port port [buffer-size])` ---> md5-digest (procedure)

> Reads the contents of the port and calculates the MD5 digest for it. The optional argument buffer-size determines the size of the port's input buffer in bytes. It defaults to 1024 bytes.

`(md5-digest? thing)` ---> boolean (procedure)

> The type predicate for MD5 digests: `md5-digest?` returns true if and only if thing is a MD5 digest.

`(md5-digest->number md5-digest)` ---> number (procedure)

> Returns the number corresponding to the MD5 digest.

`(number->md5-digest number)` ---> md5-digest (procedure)

> Creates a MD5 digest from a number.

`(make-md5-context)` ---> md5-context (procedure)
`(md5-context? thing)` ---> boolean (procedure)
`(update-md5-context! md5-context string)` ---> undefined (procedure)
`(md5-context->md5-digest md5-context)` ---> md5-digest (procedure)

> These procedures provide a low-level interface to the library. A md5-context stores the state of a MD5 computation, it is created by `make-md5-context`, its type predicate is `md5-context?`. The procedure `update-md5-context!` extends the md5-context by the given string. Finally, `md5-context->md5-digest` returns the md5-digest for the md5-context. With these procedures it is possible to incrementally add strings to a md5-context before computing the digest.

## 10.6 Configuration variables

This section describes procedures to access the configuration parameters used to compile scsh and flags needed to build C extensions for scsh.

`(host)` ---> string (procedure)
`(machine)` ---> string (procedure)
`(vendor)` ---> string (procedure)
`(os)` ---> string (procedure)

> These procedures return the description of the host, scsh was built on, as determined by the script `config.guess`.

`(prefix)` ---> string (procedure)
`(exec-prefix)` ---> string (procedure)
`(bin-dir)` ---> string (procedure)
`(lib-dir)` ---> string (procedure)
`(include-dir)` ---> string (procedure)
`(man-dir)` ---> string (procedure)

> These procedures return the various directories of the scsh installation.

`(lib-dirs-list)` ---> symbol list (procedure)

> Returns the default list of library directories. See Section 11.1.5 for more information about the library search facility.

`(libs)` ---> string (procedure)
`(defs)` ---> string (procedure)
`(cflags)` ---> string (procedure)
`(cppflags)` ---> string (procedure)
`(ldflags)` ---> string (procedure)

> The values returned by these procedures correspond to the values `make` used to compile scsh's C files.

`(compiler-flags)` ---> string (procedure)

> The procedure compiler-flags returns flags suitable for running the C compiler when compiling a C file that uses scsh's foreign function interface.

`(linker-flags)` ---> string (procedure)

> Scsh also comes as a library that can be linked into other programs. The procedure linker-flags returns the appropriate flags to link the scsh library to another program.