| uipc | Message-based IPC (unsigned messages) |
| wmutex | Weak (owner-less) locks |
+Modules are described in detail in the [module reference](docs/reference.md)
+
## Installation
--- /dev/null
+# The array module
+
+The array module implements functions for sorting, searching,
+printing, and comparing arrays.
+
+### Dependencies
+
+The array module does not depend on other modules.
+
+### Function index
+
+| Function | Purpose |
+|---------------------------------------|-----------------------------------------------|
+| [array_contains()](#array_contains) | Check if an element is in an array |
+| [array_identical()](#array_identical) | Check if two arrays are identical |
+| [array_same()](#array_same) | Check if two arrays contain the same elements |
+| [array_sort()](#array_sort) | Sort an array |
+| [array_to_lines()](#array_to_lines) | Print an array, one element per line |
+
+
+## array_contains()
+
+Check whether an element is contained in an array.
+
+### Synopsis
+
+ array_contains "$element" "${array[@]}"
+
+### Description
+
+The `array_contains()` function checks whether `element` is contained in `array`.
+It does so by iterating over the array, comparing each element in the array with
+`element`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|----------------------------------------|
+| 0 | The element is contained in the array |
+| 1 | The element was not found in the array |
+
+### Standard input
+
+`array_contains()` does not read from standard input.
+
+### Standard output
+
+`array_contains()` does not write to standard output.
+
+### Standard error
+
+`array_contains()` does not write to standard error.
+
+
+## array_identical()
+
+Checks if two arrays are identical.
+
+### Synopsis
+
+ array_identical left right
+
+### Description
+
+The `array_identical()` function checks whether the elements in the arrays
+referenced by `left` and `right` are identical. That means, it checks if the
+two arrays contain the same elements in the same order.
+The parameters `left` and `right` are name references to the arrays to be
+compared.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------|
+| 0 | The arrays are identical |
+| 1 | The arrays are not identical |
+
+### Standard input
+
+`array_identical()` does not read from standard input.
+
+### Standard output
+
+`array_identical()` does not write to standard output.
+
+### Standard error
+
+`array_identical()` does not write to standard error.
+
+
+## array_same()
+
+Check if two arrays contain the same elements.
+
+### Synopsis
+
+ array_same left right
+
+### Description
+
+The `array_same()` function checks whether the arrays referenced by `left`
+and `right` contain the same elements. That means, it checks if the arrays
+are permutations.
+The parameters `left` and `right` are name references to the arrays to be
+compared.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------------------|
+| 0 | The arrays contain the same elements |
+| 1 | The arrays do not contain the same elements |
+
+### Standard input
+
+`array_same()` does not read from standard input.
+
+### Standard output
+
+`array_same()` does not write to standard output.
+
+### Standard error
+
+`array_same()` does not write to standard error.
+
+
+## array_sort()
+
+Sort an array.
+
+### Synopsis
+
+ array_sort "${array[@]}"
+
+### Description
+
+The `array_sort()` function sorts the elements of `array` and outputs the
+result to standard output. The elements are sorted using a natural number
+sort, similar to the `sort -V` command from GNU Coreutils.
+If the array is empty, nothing will be written to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+`array_sort()` does not read from standard input.
+
+### Standard output
+
+The sorted array is written to standard output, one element per line.
+
+### Standard error
+
+`array_sort()` does not write to standard error.
+
+
+## array_to_lines()
+
+Print an array, one element per line.
+
+### Synopsis
+
+ array_to_lines "${array[@]}"
+
+### Description
+
+The `array_to_lines()` function outputs `array` to standard output, writing
+each element in the array to a separate line. The elements of the array are
+output as-is, meaning that an empty string in the array will cause an empty
+line to be written. The elements will be written in their order in the array.
+If the array is empty, nothing will be written to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+`array_to_lines()` does not read from standard input.
+
+### Standard output
+
+`array_to_lines()` writes one line per array element to standard output. If
+the array is empty, nothing will be written.
+
+### Standard error
+
+`array_to_lines()` does not write to standard error.
--- /dev/null
+# The conf module
+
+The conf module implements primitive configuration handling. This module
+allows the caller to load and store configuration values without having
+to worry about configuration files and other implementation details.
+
+Settings are stored per-script, meaning that one script will not be able
+to load and store settings from another script. Settings are further kept
+in *configuration domains*, which are namespaces, allowing a script to
+have different configuration profiles.
+
+### Dependencies
+
+ * [log](log.md)
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------------|-------------------------------|
+| [conf_get()](#conf_get) | Get the value of a setting |
+| [conf_get_domains()](#conf_get_domains) | List all setting domains |
+| [conf_get_names()](#conf_get_names) | List all settings in a domain |
+| [conf_set()](#conf_set) | Set the value of a setting |
+| [conf_unset()](#conf_unset) | Remove a setting |
+
+
+## conf_get()
+
+Get the value of a setting.
+
+### Synopsis
+
+ conf_get "$name" "$domain"
+
+### Description
+
+The `conf_get()` function retrieves the configuration setting identified by
+the name `$name` from the domain `$domain`. If `$domain` is omitted, the
+value from the domain `default` is retrieved.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------------|
+| 0 | The value of the setting was successfully read |
+| 1 | The setting was not found |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+On success, the value of the setting is written to standard output. No data
+will be written if the setting was not found.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## conf_get_domains()
+
+List all setting domains.
+
+### Synopsis
+
+ conf_get_domains
+
+### Description
+
+The `conf_get_domains()` function returns the names of all configuration
+domains for the script. If the script does not have any settings, no names
+will be returned.
+If configuration domains for the script have been defined, their names will
+be written to standard output, one domain per line.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+If configuration domains have been defined for the caller, the names of
+the domains will be written to standard output, one domain per line.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## conf_get_names()
+
+List all settings in a domain.
+
+### Synopsis
+
+ conf_get_names "$domain"
+
+### Description
+
+The `conf_get_names()` function writes the names of all settings that
+have been stored in the configuration domain identified by `$domain`
+to standard output. If no settings have been defined in the domain, no
+data will be written. If `$domain` was omitted, this function will
+output the names of the settings in the default domain.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------|
+| 0 | The domain contains settings |
+| 1 | The domain does not contain any settings |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, this function will write the names of settings to
+standard output, one name per line. Otherwise, no data will be
+written.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## conf_set()
+
+Set the value of a setting.
+
+### Synopsis
+
+ conf_set "$name" "$value" "$domain"
+
+### Description
+
+The `conf_set()` function sets the value of the setting `$name`
+in the domain `$domain` to `$value`. If `$domain` was omitted,
+the setting in the `default` domain will be set.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------------------|
+| 0 | The setting was written successfully |
+| 1 | The setting could not be written to storage |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## conf_unset()
+
+Remove a setting.
+
+### Synopsis
+
+ conf_unset "$name" "$domain"
+
+### Description
+
+The `conf_unset()` function removes the setting with name `$name` from
+the domain `$domain`. If `$domain` was omitted, the setting will be
+removed from the `default` domain.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------|
+| 0 | The setting was removed |
+| 1 | The setting could not be found |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# The git module
+
+The git module implements functions for interacting with git
+repositories in the local file system.
+
+### Dependencies
+
+ * [log](log.md)
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------------------------|---------------------------------------|
+| [git_clone()](#git_clone) | Clone a git repository |
+| [git_commit()](#git_commit) | Commit a change to the current branch |
+| [git_branch_new()](#git_branch_new) | Create a new branch |
+| [git_branch_get_current()](#git_branch_get_current) | Get the name of the current branch |
+| [git_branch_checkout()](#git_branch_checkout) | Change the current branch |
+| [git_merge()](#git_merge) | Merge one branch into another one |
+| [git_push()](#git_push) | Push a branch to a remote |
+| [git_remote_get()](#git_remote_get) | Get the URL of a remote |
+
+
+## git_clone()
+
+Clone a git repository
+
+### Synopsis
+
+ git_clone "$source" "$destination"
+
+### Description
+
+The `git_clone()` function clones the repository specified by `$source` into the path specified
+by `$destination`. The source repository may be reachable via any protocol that is understood by
+git. The path specified in `$destination` must be on a local file system. It is not necessary
+that the destination path exists, however the executing user must have sufficient permissions to
+create the path, if it does not exist.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|----------------------------------------|
+| 0 | The repository was successfully cloned |
+| 1 | The repository could not be cloned |
+
+### Standard input
+
+`git_clone()` does not read from standard input.
+
+### Standard output
+
+`git_clone()` does not write to standard output.
+
+### Standard error
+
+If an error occurs, `git_clone()` will write an error message to standard error. The message
+that is written includes the standard output and standard error from the git command that was
+invoked by `git_clone()`.
+
+
+## git_commit()
+
+Commit a change to the current branch
+
+### Synopsis
+
+ git_commit "$repository" "$message"
+
+### Description
+
+The `git_commit()` function commits the changes that are staged in the repository specified by
+`$repository` to the repository's current branch. The commit message will be set to the value
+passed in `$message`.
+
+### Return value
+
+| Return value | |
+|--------------|------------------------------------------------|
+| 0 | The staged changes were successfully committed |
+| 1 | The changes could not be committed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, `git_commit()` will write an error message to standard error. The message
+that is written includes the standard output and standard error from the git command that was
+invoked by `git_commit()`.
+
+## git_branch_new()
+
+Create a new branch
+
+### Synopsis
+
+ git_branch_new "$repository" "$branch"
+
+### Description
+
+The `git_branch_new()` function creates a new branch with name `$branch` in the repository
+specified by `$repository`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------------|
+| 0 | The branch was created successfully |
+| 1 | The branch could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, `git_branch_new()` will write an error message to standard error. The message
+that is written includes the standard output and standard error from the git command that was
+invoked by `git_branch_new()`.
+
+
+## git_branch_get_current()
+
+Get the name of the current branch
+
+### Synopsis
+
+ git_branch_get_current "$repository"
+
+### Description
+
+The `git_branch_get_current()` function writes the name of the working branch of the repository
+specified by `$repository` to standard output. The repository must be located in the local file
+system and must not be a bare repository.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------------|
+| 0 | The branch name was written to standard output |
+| 1 | The branch name could not be determined |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+On success, the name of the repository's working branch is written to standard output. Otherwise,
+no data is written to standard output.
+
+### Standard error
+
+In case of an error, `git_branch_get_current()` will write an error message to standard error.
+
+
+## git_branch_checkout()
+
+Change the current branch
+
+### Synopsis
+
+ git_branch_checkout "$repository" "$branch"
+
+### Description
+
+The `git_branch_checkout()` function changes the working branch of the repository specified by
+`$repository` to the branch specified by `$branch`. The repository must be located in the local
+file system. If `$branch` was omitted, the `master` branch will be checked out.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------------------|
+| 0 | The working branch was successfully changed |
+| 1 | The working branch could not be changed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, `git_branch_checkout()` will write an error message to standard error. The message
+that is written includes the standard output and standard error from the git command that was invoked
+by `git_branch_checkout()`.
+
+
+## git_merge()
+
+Merge one branch into another one
+
+### Synopsis
+
+ git_merge "$repository" "$source" "$destination"
+
+### Description
+
+The `git_merge()` function merges the branch `$source` of the repository `$repository` into the branch
+`$destination` of the same repository. If `$destination` was omitted, `$source` will be merged into the
+working branch of the repository.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The merge operation was successful |
+| 1 | The merge could not be performed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, `git_merge()` will write an error message to standard error. The message
+that is written includes the standard output and standard error from the git command that was
+invoked by `git_merge()`.
+
+
+## git_push()
+
+Push a branch to a remote
+
+### Synopsis
+
+ git_push "$repository" "$branch" "$remote"
+
+### Description
+
+The `git_push()` function pushes the branch `$branch` of the repository `$repository` to the
+remote `$remote`. If `$remote` was omitted, the branch will be pushed to the remote `origin`.
+If `$branch` was omitted, the working branch will be pushed.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The branch was pushed successfully |
+| 1 | The branch could not be pushed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, `git_push()` will write an error message to standard error. The message that
+is written will include the standard output and standard error of the git command that was invoked
+by `git_push()`.
+
+
+## git_remote_get()
+
+Get the URL of a remote
+
+### Synopsis
+
+ git_remote_get "$repository" "$remote"
+
+### Description
+
+The `git_remote_get()` function determines the URL of the remote `$remote` of the repository
+`$repository` and writes it to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------------------|
+| 0 | The URL of the remote was written to standard output |
+| 1 | The URL of the remote could not be determined |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+On success, the URL of the remote is written to standard output. Otherwise, no data is written to
+standard output.
+
+### Standard error
+
+In case of an error, `git_remote_get()` will write an error message to standard error.
--- /dev/null
+# The inst module
+
+The inst module implements functions for writing daemons.
+
+### Dependencies
+
+ * [log](log.md)
+ * [opt](opt.md)
+ * [sem](sem.md)
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------------------------------|-----------------------------------------------|
+| [inst_count()](#inst_count) | Count the running instances of a script |
+| [inst_get_status()](#inst_get_status) | Get the status of an instance |
+| [inst_get_status_message()](#inst_get_status_message) | Get the status message of an instance |
+| [inst_get_status_timestamp()](#inst_get_status_timestamp) | Get the timestamp of an instance's status |
+| [inst_list()](#inst_list) | List running instances of a script |
+| [inst_running()](#inst_running) | Return the state of the current instance |
+| [inst_set_status()](#inst_set_status) | Set the status of the current instance |
+| [inst_singleton()](#inst_singleton) | Start a unique instance of the current script |
+| [inst_start()](#inst_start) | Start an instance of the current script |
+| [inst_stop()](#inst_stop) | Stop an instance of a script |
+
+## inst_count()
+
+Count the running instances of a script
+
+### Synopsis
+
+ inst_count "$instname"
+
+### Description
+
+The `inst_count()` function counts the running instances of the script determined by `$instname` and writes
+the count to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------------|
+| 0 | The number of instances was successfully written |
+| 1 | The number of instances could not be determined |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, an integer value representing the number of running instances is written to standard output.
+Otherwise, no data is written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## inst_get_status()
+
+Get the status of an instance
+
+### Synopsis
+
+ inst_get_status "$pid" "$instname"
+
+### Description
+
+The `inst_get_status()` function retrieves the status of the instance with pid `$pid` of the script
+`$instname` and writes it to standard output. If `$instname` is omitted, the status for the instance
+of the current script will be retrieved.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------------------|
+| 0 | The status was successfully written to standard output |
+| 1 | The status for the instance could not be retrieved |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the instance status is written to standard output. Otherwise, no data is written to standard
+output.
+
+### Standard error
+
+In case of an error, a message will be written to standard error.
+
+
+## inst_get_status_message()
+
+Get the status message of an instance
+
+### Synopsis
+
+ inst_get_status_message "$pid" "$instname"
+
+### Description
+
+The `inst_get_status_message()` function retrieves the status message of the instance with pid `$pid` of the
+script `$instname` and writes it to standard output. If `$instname` was omitted, the status for an instance
+of the executing script will be retrieved.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------------------|
+| 0 | The status was successfully written to standard output |
+| 1 | The status for the instance could not be retrieved |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the status message of the instance is written to standard output. Otherwise, no data is written
+to standard output.
+
+### Standard error
+
+In case of an error, a message will be written to standard error.
+
+
+## inst_get_status_timestamp()
+
+Get the timestamp of an instance's status
+
+### Synopsis
+
+ inst_get_status_timestamp "$pid" "$instname"
+
+### Description
+
+The `inst_get_status_timestamp()` retrieves the timestamp of the status of the instance with pid `$pid` of the
+script `$instname` and writes it to standard output. If `$instname` was omitted, the status for an instance of
+the executing script will be retrieved.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------------------------|
+| 0 | The timestamp was successfully written to standard output |
+| 1 | The timestamp could not be retrieved |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, an integer value representing the timestamp in UNIX-time is written to standard output.
+Otherwise, no data is written to standard output.
+
+### Standard error
+
+In case of an error, a message is written to standard output.
+
+
+## inst_list()
+
+List running instances of a script
+
+### Synopsis
+
+ inst_list "$instname"
+
+### Description
+
+The `inst_list()` function retrieves a list of running instances of the script `$instname` and writes it to
+standard output. If `$instname` was omitted, instances of the executing script will be returned.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+If running instances of the script were found, details about each of them will be written to standard output,
+one per line. The following is the format of each line.
+
+ OWNER STATE [STATUS_TIMESTAMP:STATUS_TEXT] INSTANCE_NAME ARGV0 ...
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## inst_running()
+
+Return the state of the current instance
+
+### Synopsis
+
+ inst_running
+
+### Description
+
+The `inst_running()` function determines the state of the executing script. Instances should use this function
+to determine whether they should stop execution. If this function returns a non-zero value, the calling
+instance has been requested to stop either by `inst_stop()` or a signal.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------|
+| 0 | The instance is running |
+| 1 | The instance has been requested to stop |
+
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, this function writes a message to standard error.
+
+
+## inst_set_status()
+
+Set the status of the current instance
+
+### Synopsis
+
+ inst_set_status "$status"
+
+### Description
+
+The `inst_set_status()` function sets the status of the executing instance to `$status`. The
+`inst_get_status_message()` and `inst_get_status_timestamp()` functions may be used to retrieve the status
+and the timestamp of the status, respectively.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------|
+| 0 | The status was successfully set |
+| 1 | The status could not be set |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, this function writes a message to standard error.
+
+
+
+## inst_singleton()
+
+Start a unique instance of the current script
+
+### Synopsis
+
+ inst_singleton "${args[@]}"
+
+### Description
+
+The `inst_singleton()` function starts a unique instance of the executing script using the array passed in
+`$args` as the main function of the new instance. If another instance of the executing script is already
+running, no instance will be started.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------------------------------------|
+| 0 | The instance was started |
+| 1 | Another instance of the executing script is already running |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, this function writes a message to standard error.
+
+
+## inst_start()
+
+Start an instance of the current script
+
+### Synopsis
+
+ inst_start "${args[@]}"
+
+### Description
+
+The `inst_start()` function starts an instance of the executing script using the array passed in
+`$args` as the main function of the new instance.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## inst_stop()
+
+Stop an instance of a script
+
+### Synopsis
+
+ inst_stop "$pid" "$instname"
+
+### Description
+
+The `inst_stop()` function requests the instance with pid `$pid` of the script `$instname` to stop. If
+`$instname` was omitted, an instance of the executing script will be requested to stop. Note that the
+instance that was requested to stop is highly unlikely to be stopped by the time this function returns.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------------------------|
+| 0 | The instance was successfully requested to stop |
+| 1 | The instance could not be requested to stop |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+A message will be written to standard error if the instance does not exist.
--- /dev/null
+# The is module
+
+The is module implements functions for checking the contents of strings.
+
+### Dependencies
+
+The is module does not depend on other modules.
+
+| Function | Purpose |
+|---------------------------|---------------------------------------------------------|
+| [is_alnum()](#is_alnum) | Check if a string contains only alphanumeric characters |
+| [is_alpha()](#is_alpha) | Check if a string contains only alphabet characters |
+| [is_base64()](#is_base64) | Check if a string contains a base64-encoded value |
+| [is_digits()](#is_digits) | Check if a string contains only digits |
+| [is_hex()](#is_hex) | Check if a string contains a hexadecimal value |
+| [is_int()](#is_int) | Check if a string contains an integer value |
+| [is_lower()](#is_lower) | Check if a string contains only lower-case letters |
+| [is_upper()](#is_upper) | Check if a string contains only upper-case letters |
+
+
+## is_alnum()
+
+Check if a string contains only alphanumeric characters
+
+### Synopsis
+
+ is_alnum "$str"
+
+### Description
+
+The `is_alnum()` function tests whether all characters in the string `$str` are alphanumeric.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------|
+| 0 | The input is alphanumeric |
+| 1 | The input is not alphanumeric |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_alpha()
+
+Check if a string contains only alphabet characters
+
+### Synopsis
+
+ is_alpha "$str"
+
+### Description
+
+The `is_alpha()` function tests whether all characters in the string `$str` are alphabet characters.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------|
+| 0 | The input is alphabetic |
+| 1 | The input is not alphabetic |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_base64()
+
+Check if a string contains a base64-encoded value
+
+### Synopsis
+
+ is_base64 "$str"
+
+### Description
+
+The `is_base64()` function tests whether the string `$str` contains a base64-encoded value. Aside of upper and
+lower-case alphabet letters and digits, `/` and `+` are considered part of the base64-alphabet. This function
+does not check if the length of the padding is correct.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------|
+| 0 | The input is base64 |
+| 1 | The input is not base64 |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_digits()
+
+Check if a string contains only digits
+
+### Synopsis
+
+ is_digits "$str"
+
+### Description
+
+The `is_digits()` function tests whether all characters in the string `$str` are digits.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------|
+| 0 | The input contains only digits |
+| 1 | The input contains non-digit characters |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_hex()
+
+Check if a string contains a hexadecimal value
+
+### Synopsis
+
+ is_hex "$str"
+
+### Description
+
+The `is_hex()` function tests whether the string `$str` contains a hexadecimal value. The value must neither
+be prefixed with `0x` or `0X`, nor suffixed with `h` or `H`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------|
+| 0 | The input is hexadecimal |
+| 1 | The input is not hexadecimal |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_int()
+
+Check if a string contains an integer value
+
+### Synopsis
+
+ is_int "$str"
+
+### Description
+
+The `is_int()` function tests whether the string `$str` contains an integer value. This function is similar to
+`is_digits()`, except that it allows the value to be prefixed with a sign (either `+` or `-`).
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------|
+| 0 | The input is an integer |
+| 1 | The input is not an integer |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_lower()
+
+Check if a string contains only lower-case letters
+
+### Synopsis
+
+ is_lower "$str"
+
+### Description
+
+The `is_lower()` function tests whether all characters in the string `$str` are lower-case alphabet letters.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------|
+| 0 | The input is lower-case |
+| 1 | The input is not lower-case |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## is_upper()
+
+Check if a string contains only upper-case letters
+
+### Synopsis
+
+ is_upper "$str"
+
+### Description
+
+The `is_upper()` function tests whether all characters in the string `$str` are upper-case alphabet letters.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------|
+| 0 | The input is upper-case |
+| 1 | The input is not upper-case |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# The json module
+
+The json module implements functions for creating and parsing JSON data.
+
+### Dependencies
+
+ * [array](array.md)
+ * [is](is.md)
+ * [log](log.md)
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------------------|--------------------------------------------------|
+| [json_array()](#json_array) | Create a JSON array |
+| [json_array_head()](#json_array_head) | Get the first element from a JSON array |
+| [json_array_tail()](#json_array_tail) | Remove the first element from a JSON array |
+| [json_array_to_lines()](#json_array_to_lines) | Get the elements from a JSON array, one per line |
+| [json_object()](#json_object) | Create a JSON object |
+| [json_object_get()](#json_object_get) | Extract a field from a JSON object |
+
+## json_array()
+
+Create a JSON array
+
+### Synopsis
+
+ json_array "${args[@]}"
+
+### Description
+
+The `json_array()` function creates a JSON array that is equivalent to the Bash array `$args` and writes
+it to standard output. This function attempts to parse values in `$args`, meaning that inputs that look
+like integer, floating-point, or other values will be converted to the corresponding types. If this is
+not desired, the caller must prefix values with type hints.
+
+| Prefix | Type |
+|--------|-------------|
+| `s:` | String |
+| `i:` | Integer |
+| `b:` | Bool |
+| `f:` | Float |
+| `o:` | JSON Object |
+| `a:` | JSON Array |
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The array was written successfully |
+| 1 | The array could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+On success, the JSON array is written to standard output. Otherwise, no data will be written to standard
+output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## json_array_head()
+
+Get the first element from a JSON array
+
+### Synopsis
+
+ json_array_head "$array"
+
+### Description
+
+The `json_array_head()` function extracts the first element from the JSON array `$array` and writes it to
+standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------------------------------|
+| 0 | The element was written successfully to standard output |
+| 1 | The element could not be retrieved from the array |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the first element of the array is written to standard output. Otherwise no data is written
+to standard output.
+
+### Standard error
+
+In case of an error, messages from an internal call to `jq` may be written to standard error.
+
+
+## json_array_tail()
+
+Remove the first element from a JSON array
+
+### Synopsis
+
+ json_array_tail "$array"
+
+### Description
+
+The `json_array_tail()` function creates a new JSON array with all but the first element of `$array`, and writes
+the new JSON array to standard output. The order of elements in the array is preserved.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------------------------|
+| 0 | The new array was successfully written to standard output |
+| 1 | The new array could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the new JSON array is written to standard output. Otherwise no data is written to standard output.
+
+### Standard error
+
+In case of an error, messages from an internal call to `jq` may be written to standard error.
+
+
+## json_array_to_lines()
+
+Get the elements from a JSON array, one per line
+
+### Synopsis
+
+ json_array_to_lines "$array"
+
+### Description
+
+The `json_array_to_lines()` function retrieves the elements from the JSON array passed in `$array` and writes them
+to standard output, one element per line.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------|
+| 0 | The array was output successfully |
+| 1 | The array could not be parsed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the elements from the array are written to standard output, one element per line. Otherwise, no data
+is written to standard output.
+
+### Standard error
+
+In case of an error, messages from an internal call to `jq` may be written to standard error.
+
+
+## json_object()
+
+Create a JSON object
+
+### Synopsis
+
+ json_object "$name0" "$value0" ...
+
+### Description
+
+The `json_object()` function creates a new JSON object using pairs of arguments as the names and values of fields in
+the object. If either the name or the value in a pair of arguments is the empty string, the pair will be skipped. The
+same rules as for the [json_array()](#json_array) function apply to this function. In particular, this means that
+values may need to be prefixed with type hints.
+An even number of arguments must be passed to this function.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------------------------|
+| 0 | The new object was successfully written to standard output |
+| 1 | The object could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the new JSON object is written to standard output. Otherwise no data is written to standard output.
+
+### Standard error
+
+In case of an error, this function may write a message to standard error.
+
+
+## json_object_get()
+
+Extract a field from a JSON object
+
+### Synopsis
+
+ json_object_get "$object" "$field"
+
+### Description
+
+The `json_object_get()` function extracts the field `$field` from the JSON object passed in `$object` and writes its
+value to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------------|
+| 0 | The value was written successfully |
+| 1 | The field could not be parsed from the object |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the the value of the field is written to standard output. Otherwise no data is written to standard output.
+
+### Standard error
+
+In case of an error, messages from an internal call to `jq` may be written to standard error.
--- /dev/null
+# The log module
+
+The log module implements functions for logging and debugging with different log levels. A script that includes
+this module has a global log level that defaults to `__log_warning`, meaning that by default only warnings and
+errors will be logged. The log level may be adjusted to increase or decrease the amount of log messages.
+
+| Log level | Meaning |
+|-----------------|--------------------------------------------------|
+| `__log_debug` | Log everything |
+| `__log_info` | Log errors, warnings, and informational messages |
+| `__log_warning` | Log errors and warnings (default) |
+| `__log_error` | Log only errors |
+
+### Dependencies
+
+This module does not depend on other modules.
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------------------------|-----------------------------------------------------|
+| [log_debug()](#log_debug) | Log a debug message |
+| [log_decrease_verbosity()](#log_decrease_verbosity) | Decrease the log level |
+| [log_error()](#log_error) | Log an error |
+| [log_get_verbosity()](#log_get_verbosity) | Get the current log level |
+| [log_highlight()](#log_highlight) | Highlight a message and write it to standard output |
+| [log_increase_verbosity()](#log_increase_verbosity) | Increase the log level |
+| [log_info()](#log_info) | Log an informational message |
+| [log_set_verbosity()](#log_set_verbosity) | Change the current log level |
+| [log_stacktrace()](#log_stacktrace) | Write the call hierarchy to standard output |
+| [log_warn()](#log_warn) | Log a warning |
+
+
+## log_debug()
+
+Log a debug message
+
+### Synopsis
+
+ log_debug "${messages[@]}"
+ log_debug <<< "$messages"
+
+### Description
+
+The `log_debug()` function writes debug messages to standard error and the script's log file. If debug messages
+were passed as arguments, this function will treat each argument as a debug message. Otherwise, this function
+will read debug messages line-by-line from standard input.
+Each line of output is prefixed with a timestamp, log tag, as well as the name of the source file and the line
+number that the function was called from.
+
+Messages will only be logged if the current log level is `__log_debug` or above.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------|
+| 0 | The message was written successfully |
+| 1 | The message could not be logged |
+
+### Standard input
+
+If this function is invoked without arguments, messages will be read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function will write one message per line to standard error.
+
+
+## log_decrease_verbosity()
+
+Decrease the log level
+
+### Synopsis
+
+ log_decrease_verbosity
+
+### Description
+
+The `log_decrease_verbosity()` function lowers the log level of the executing script by one step. If the log level
+is at `__log_error`, it will remain unchanged.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## log_error()
+
+Log an error
+
+### Synopsis
+
+ log_error "${messages[@]}"
+ log_error <<< "$messages"
+
+### Description
+
+The `log_error()` function writes error messages to standard error and the script's log file. If error messages
+were passed as arguments, this function will treat each argument as an error message. Otherwise, this function
+will read error messages line-by-line from standard input. Each line of output is prefixed with a timestamp and
+log tag.
+
+Error messages are always logged, regardless of the log level.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------|
+| 0 | The message was written successfully |
+| 1 | The message could not be logged |
+
+### Standard input
+
+If this function is invoked without arguments, messages will be read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function will write one message per line to standard error.
+
+
+## log_get_verbosity()
+
+Get the current log level
+
+### Synopsis
+
+ log_get_verbosity
+
+### Description
+
+The `log_get_verbosity()` function writes the current log level to standard output.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+An integer value indicating the current log level is written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## log_highlight()
+
+Highlight a message and write it to standard output
+
+### Synopsis
+
+ log_highlight "$tag" "${lines[@]}"
+ log_highlight "$tag" <<< "$lines"
+
+### Description
+
+The `log_highlight()` function adds markers with a tag `$tag` around the lines passed in `$lines` and writes them
+to standard output, making the lines easier to find in a large amount of log output.
+If no lines were passed as arguments, this function reads the data to be highlighted from standard input.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+If this function is invoked without arguments, data to be highlighted will be read from standard input.
+
+### Standard output
+
+Highlighted data will be written to standard output.
+
+### Standard error
+
+This function may write a message to standard error if standard input is not readable.
+
+
+## log_increase_verbosity()
+
+Increase the log level
+
+### Synopsis
+
+ log_increase_verbosity
+
+### Description
+
+The `log_increase_verbosity()` function raises the log level of the executing script by one step. If the log level
+is at `__log_debug`, it will remain unchanged.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## log_info()
+
+Log an informational message
+
+### Synopsis
+
+ log_info "${messages[@]}"
+ log_info <<< "$messages"
+
+### Description
+
+The `log_info()` function writes informational messages to standard error and the script's log file. If messages
+were passed as arguments, this function will treat each argument as a message. Otherwise, this function will read
+messages line-by-line from standard input. Each line of output is prefixed with a timestamp and log tag.
+
+Messages will only be logged if the log level is `__log_info` or above.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------|
+| 0 | The message was written successfully |
+| 1 | The message could not be logged |
+
+### Standard input
+
+If this function is invoked without arguments, messages will be read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function will write one message per line to standard error.
+
+
+## log_set_verbosity()
+
+Change the current log level
+
+### Synopsis
+
+ log_set_verbosity "$verbosity"
+
+### Description
+
+The `log_set_verbosity()` function sets the log level of the executing script to `$verbosity`. If the value passed in
+`$verbosity` is not a valid log level, the function will set it to the nearest valid log level.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## log_stacktrace()
+
+Write the call hierarchy to standard output
+
+### Synopsis
+
+ log_stacktrace
+
+### Description
+
+The `log_stacktrace()` function writes the call hierarchy of the calling function to standard output, allowing
+the user to determine where a particular function was called from. The output written to standard output includes
+file names, function names, and the line numbers that functions were called from. Indentation is used to visually
+highlight the nesting of function calls.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------|
+| 0 | Success (always returned) |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+The stacktrace of the calling function is written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## log_warn()
+
+Log a warning
+
+### Synopsis
+
+ log_warn "${messages[@]}"
+ log_warn <<< "$messages"
+
+### Description
+
+The `log_warn()` function writes warning messages to standard error and the script's log file. If messages were
+passed as arguments, this function will treat each argument as a message. Otherwise, this function will read
+messages line-by-line from standard input. Each line of output is prefixed with a timestamp and log tag.
+
+Messages will only be logged if the log level is `__log_warning` or above.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------|
+| 0 | The message was written successfully |
+| 1 | The message could not be logged |
+
+### Standard input
+
+If this function is invoked without arguments, messages will be read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function will write one message per line to standard error.
--- /dev/null
+# The mutex module
+
+The mutex module implements a simple mechanism to enforce serial execution.
+The path from a mutex lock operation to its corresponding unlock operation is
+called a critical section, and is guaranteed to be executed serially.
+
+Critical sections limit the performance of parallel processes and should thus
+be as short as possible. Further, long and nested critical sections are prone
+to cause deadlocks and should be avoided.
+As a best practice, a critical section should not span multiple functions and
+there should be only one codepath that leads out of the critical section.
+
+### Dependencies
+
+The mutex module has no dependencies.
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------|--------------------------------------|
+| [mutex_trylock()](#mutex_trylock) | Try to lock a mutex, without waiting |
+| [mutex_lock()](#mutex_lock) | Lock a mutex, waiting if necessary |
+| [mutex_unlock()](#mutex_unlock) | Unlock a mutex |
+
+
+## mutex_trylock()
+
+Try to lock a mutex, without waiting.
+
+### Synopsis
+
+ mutex_trylock "$mutex"
+
+### Description
+
+The `mutex_trylock()` function attempts to lock the mutex with the path
+`$mutex`. This function returns immediately, regardless of the outcome of
+the lock operation.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------|
+| 0 | The mutex was successfully locked |
+| 1 | The mutex could not be locked |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## mutex_lock()
+
+Lock a mutex, waiting if necessary.
+
+### Synopsis
+
+ mutex_lock "$mutex" "$timeout"
+
+### Description
+
+The `mutex_lock()` function locks the mutex with the path `$mutex`. If the mutex
+is already locked by another process, this function will wait either until it was
+able to lock the mutex, or until the timeout has expired. If `$timeout` is -1 or
+was omitted, the function will wait indefinitely. Otherwise, it will wait for
+`$timeout` seconds. The actual time that this function waits depends on the
+process scheduler and may be more than `$timeout` seconds.
+If a timeout of 0 is passed, this function is equivalent with `mutex_trylock()`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------|
+| 0 | The mutex was successfully locked |
+| 1 | The mutex could not be locked |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## mutex_unlock()
+
+Unlock a mutex.
+
+### Synopsis
+
+ mutex_unlock "$mutex"
+
+### Description
+
+The `mutex_unlock()` function unlocks the mutex at the path `$mutex`. If
+`$mutex` is a valid mutex, this function checks whether the running process
+is the owner of the mutex (i.e. if the running process is the process that
+locked the mutex) and, if it is not the owner, refuses to unlock the mutex.
+
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------|
+| 0 | The mutex was successfully unlocked |
+| 1 | The mutex could not be read |
+| 2 | The running process does not own the mutex |
+| 3 | The mutex could not be removed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# The opt module
+
+The opt module implements a versatile command line parser. The parser can be used for
+options without values (flags) and options with one or multiple values. The parser can
+be instructed to validate values using regular expressions, and call user-defined
+functions when an option was parsed and validated.
+
+### Dependencies
+
+ * [array](array.md)
+ * [log](log.md)
+
+### Function index
+
+| Function | Purpose |
+|-------------------------------------|-----------------------------------------|
+| [opt_add_arg()](#opt_add_arg) | Declare an option |
+| [opt_get()](#opt_get) | Get the value of an option |
+| [opt_get_argv()](#opt_get_argv) | Get the executing script's command line |
+| [opt_parse()](#opt_parse) | Parse a command line |
+| [opt_print_help()](#opt_print_help) | Print a help text |
+
+
+## opt_add_arg()
+
+Declare an option
+
+### Synopsis
+
+ opt_add_arg "$short" "$long" "$flags" "$default" "$desc" "$regex" "$action"
+
+### Description
+
+The `opt_add_arg()` function declares a new option with the short and long names `$short` and `$long`. The
+behavior of the option is determined by the flags passed in `$flags`, which is a string containing one or more
+of the following attributes.
+
+| Attribute | Meaning |
+|-----------|--------------------------------------|
+| `a` | The option is an array (implies `v`) |
+| `r` | The option is required |
+| `v` | The option has a value |
+
+If the `a` flag was set, the `$default` parameter must contain the name of the array that the parsed values
+will be appended to. The parser will only append to the array; values that it contains before the parser is
+invoked will not be overwritten.
+If the `r` flag was set, the option must be passed on the command line, otherwise the parser will return an
+error.
+If the `v` or `a` flag was set, the option must be followed by a value. The value is validated against the
+regular expression passed in `$regex`.
+The `$action` parameter may be used to determine a callback that is executed when an option was successfully
+parsed, i.e. it has no value or the value matches `$regex`. The callback `$action` will be passed the long
+name of the option in the first, and the value of the option in the second argument.
+
+The value passed in `$desc` will be displayed as the description in the script's help text.
+
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------|
+| 0 | The option was successfully declared |
+| 1 | The option could not be declared |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, a message is written to standard error.
+
+
+## opt_get()
+
+Get the value of an option
+
+### Synopsis
+
+ opt_get "$long"
+
+### Description
+
+The `opt_get()` function returns the value of the option with the long name `$long`. If the option does not
+have a value (i.e. it was declared without the `a` or `v` flags), the number of times it was encountered on
+the command line is returned.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------------------|
+| 0 | The value of the option was written to standard output |
+| 1 | The option was not set |
+| 2 | The option name is invalid |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the value of the option is written to standard output. If the option's value was not passed on
+the command line, its default value will be written. Otherwise, no data will be written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## opt_get_argv()
+
+Get the executing script's command line
+
+### Synopsis
+
+ opt_get_argv
+
+### Description
+
+The `opt_get_argv()` function returns options that were passed to the executing script, one argument per line.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|----------------------------------|
+| 0 | Success |
+| 1 | The options could not be written |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the options that were passed to the executing script are written to standard output, each
+argument on a separate line. Otherwise no data will be written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## opt_parse()
+
+Parse a command line
+
+### Synopsis
+
+ opt_parse "${opts[@]}"
+
+### Description
+
+The `opt_parse()` function parses the command line passed in `$opts` according to the option definitions that
+were declared using `opt_add_arg()`. Options may appear on the command line either with their short name,
+prefixed by one dash, or with their long name, prefixed by two dashes. The parser operates as follows.
+ * If an option does not have a value, the parser will count the number of times the option was found on the command line.
+ * If an option has a value, but the value is missing or could not be validated against the option's regular expression, the parser will return an error.
+ * If the option is an array, and its value could be validated, the value will be added to the array that stores the option's values.
+ * If the option does not have a value, or it has a value that could be validated against the option's regular expression, the parser will call the option's callback. If the option's callback returns a non-zero value, the parser will stop parsing and return the value that the callback returned.
+ * If `-h` or `--help` were encountered in `$opts`, the help text will be written to standard output.
+ * If `-v` or `--verbose` were encountered in `$opts`, the verbosity of the script is increased one level.
+ * If `-q` or `--quiet` were encountered in `$opts`, the verbosity of the script is decreased one level.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------|
+| 0 | The command line was successfully parsed |
+| 1 | The command line could not be parsed |
+| * | A callback failed with this return value |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+If `-h` or `--help` were found in `$opts`, the help text will be written to standard output.
+
+### Standard error
+
+In case of an error, a message will be written to standard error.
+
+
+## opt_print_help()
+
+Print a help text
+
+### Synopsis
+
+ opt_print_help
+
+### Description
+
+The `opt_print_help()` function writes a help text to standard output. The content of the help text depends
+on the options that were declared using `opt_add_arg()`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------|
+| 2 | Always returned |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+The help text of the script is written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# The queue module
+
+The queue implements a "thread"-safe mechanism for exchanging messages
+between multiple processes. Messages exchanged via queues will be received
+in the same order that they were sent.
+
+### Dependencies
+
+ * [log](log.md)
+ * [mutex](mutex.md)
+ * [sem](sem.md)
+
+### Function index
+
+| Function | Purpose |
+|-----------------------------------|------------------------------------------------|
+| [queue_destroy()](#queue_destroy) | Remove a queue |
+| [queue_foreach()](#queue_foreach) | Execute a callback for each message in a queue |
+| [queue_get()](#queue_get) | Get a message from a queue |
+| [queue_init()](#queue_init) | Create a new queue |
+| [queue_put()](#queue_put) | Insert a message into a queue |
+
+## queue_destroy()
+
+Remove a queue
+
+### Synopsis
+
+ queue_destroy "$queue"
+
+### Description
+
+The `queue_destory()` function removes the queue referenced by `$queue`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The queue was successfully removed |
+| 1 | The queue could not be removed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## queue_foreach()
+
+Execute a callback for each message in a queue
+
+### Synopsis
+
+ queue_foreach "$queue" "$func" "${args[@]}"
+
+### Description
+
+The `queue_foreach()` function executes the callback `$func` once for each message contained in the queue
+referenced by `$queue`. The callback will be passed the message in the first parameter, followed by the
+elements in `$args`.
+If the callback returns a non-zero value, `queue_foreach()` will not visit the remaining messages in the
+queue.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------------------------------|
+| 0 | The callback successfully processed all messages |
+| 1 | The queue could not be locked, or the callback failed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## queue_get()
+
+Get a message from a queue
+
+### Synopsis
+
+ queue_get "$queue" "$timeout"
+
+### Description
+
+The `queue_get()` function will return the message from the head of the queue `$queue`. If the queue is empty,
+the function will wait for at least `$timeout` seconds for the arrival of a message. If `$timeout` was
+omitted, the function will wait indefinitely; if `$timeout` is zero, the function will return immediately.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------------------------|
+| 0 | A message was successfully retrieved from the queue |
+| 1 | Could not retrieve a message from the queue |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+Upon success, the message retrieved from the queue is written to standard output. Otherwise, no data is
+written to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## queue_init()
+
+Create a new queue
+
+### Synopsis
+
+ queue_init "$queue"
+
+### Description
+
+The `queue_init()` function initializes a new queue with path `$queue`. If `$queue` is a relative path, the
+queue will be created in the home directory of the executing user.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The queue was successfully created |
+| 1 | The queue could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## queue_put()
+
+Insert a message into a queue
+
+### Synopsis
+
+ queue_put "$queue" "$item"
+
+### Description
+
+The `queue_put()` function places the item `$item` in the queue referenced by `$queue`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------|
+| 0 | The item was successfully inserted |
+| 1 | The item could not be inserted |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# Toolbox module reference
+
+The following modules are part of toolbox.
+
+| Module | Purpose |
+|---------------------|------------------------------------------|
+| [array](array.md) | Comparing, searching, and sorting arrays |
+| [conf](conf.md) | Configuration handling |
+| [git](git.md) | Interacting with git repositories |
+| [inst](inst.md) | Writing daemons |
+| ipc | Message-based IPC (GPG-signed) |
+| [is](is.md) | Checking the value of variables |
+| [json](json.md) | Handling JSON data |
+| [log](log.md) | Logging and debugging |
+| [mutex](mutex.md) | Locks for protecting shared resources |
+| [opt](opt.md) | Command line parsing |
+| [queue](queue.md) | "Thread"-safe FIFOs |
+| [sem](sem.md) | Process synchronization |
+| uipc | Message-based IPC (unsigned) |
+| [wmutex](wmutex.md) | Weak (owner-less) locks |
--- /dev/null
+# The sem module
+
+The sem module implements a semaphore datatype for synchronizing access
+to shared resources such as queues.
+
+### Dependencies
+
+ * [is](is.md)
+ * [log](log.md)
+ * [mutex](mutex.md)
+ * [wmutex](wmutex.md)
+
+### Function index
+
+| Function | Purpose |
+|-------------------------------|-----------------------------------------------------|
+| [sem_destroy()](#sem_destroy) | Clean up a semaphore |
+| [sem_init()](#sem_init) | Initialize a new semaphore |
+| [sem_post()](#sem_post) | Increase a semaphore |
+| [sem_peek()](#sem_peek) | Get the counter of a semaphore without modifying it |
+| [sem_trywait()](#sem_trywait) | Try to decrease a semaphore without waiting |
+| [sem_wait()](#sem_wait) | Decrease a semaphore, waiting if necessary |
+
+## sem_destroy()
+
+Clean up a semaphore
+
+### Synopsis
+
+ sem_destroy "$name"
+
+### Description
+
+The `sem_destroy()` function removes the semaphore referenced by `$name` and frees all resources
+occupied by it. Before removing the semaphore, this function checks if the calling process is the
+owner of the semaphore. If the caller is not the owner of the semaphore, an error will be returned.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|----------------------------------------|
+| 0 | The semaphore was removed successfully |
+| 1 | The semaphore could not be removed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, this function writes a message to standard error.
+
+
+## sem_init()
+
+Initialize a new semaphore
+
+### Synopsis
+
+ sem_init "$name" "$value"
+
+### Description
+
+The `sem_init()` function creates a new semaphore with the name `$name` and initializes its counter
+to the value `$value`. If `$name` is a relative path, the semaphore will be created in the calling
+user's home directory, otherwise `$name` is assumed to be the absolute path of a semaphore.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------------------|
+| 0 | The semaphore was created and initialized successfully |
+| 1 | The semaphore could not be created |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+In case of an error, this function writes a message to standard error.
+
+
+## sem_post()
+
+Increase a semaphore
+
+### Synopsis
+
+ sem_post "$name"
+
+### Description
+
+The `sem_post()` function increases the counter of a semaphore. This is a synchronous operation, and
+may cause the caller to block indefinitely.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------|
+| 0 | The semaphore was increased successfully |
+| 1 | The semaphore could not be increased |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## sem_peek()
+
+Get the counter of a semaphore without modifying it
+
+### Synopsis
+
+ sem_peek "$name"
+
+### Description
+
+The `sem_peek()` function reads the counter of the semaphore referenced by `$name` and writes it to
+standard output. This is a synchronous operation, and may cause the caller to block indefinitely.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|---------------------------------------------------------|
+| 0 | The counter was successfully written to standard output |
+| 1 | The counter could not be read |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+On success, the counter of the semaphore is written to standard output. Otherwise, no data is written
+to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## sem_trywait()
+
+Try to decrease a semaphore without waiting
+
+### Synopsis
+
+ sem_trywait "$name"
+
+### Description
+
+The `sem_trywait()` function attempts to decrease the counter of the semaphore referenced by `$name`
+and returns immediately. If the counter cannot be decreased without waiting on the semaphore, the
+counter is not decreased, and an error is returned.
+This function is equivalent to `sem_wait()` with a timeout of `0`, and may be implemented as a call
+to `sem_wait()`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|------------------------------------------------------|
+| 0 | The semaphore was decreased successfully |
+| 1 | The semaphore could not be decreased without waiting |
+
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## sem_wait()
+
+Decrease a semaphore, waiting if necessary
+
+### Synopsis
+
+ sem_wait "$name" "$timeout"
+
+### Description
+
+The `sem_wait()` function decreases the counter of the semaphore referenced by `$name`, waiting on the
+semaphore if necessary. The function will wait at most `$timeout` seconds, however the exact time waited
+depends on the process scheduler and may exceed `$timeout` seconds. If the timeout is negative or has been
+omitted, the function may wait indefinitely. If the timeout is `0`, the function will attempt to decrease
+the counter without waiting. The latter is equivalent to a call to `sem_trywait()`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-------------------------------------------------------------------|
+| 0 | The semaphore has been decreased successfully |
+| 1 | The semaphore could not be decreased within the specified timeout |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
--- /dev/null
+# The wmutex (weak mutex) module
+
+The wmutex module implements a simple mechanism to enforce serial execution.
+The path from a wmutex lock operation to its corresponding unlock operation is
+called a critical section, and is guaranteed to be executed serially.
+
+Weak mutexes work the same way as regular mutexes, except that weak mutexes do
+not perform ownership checks. Thus, weak mutexes may be used in situations where
+the process that unlocks a mutex is not the same as the one that locked it (for
+example, in semaphores).
+
+Critical sections limit the performance of parallel processes and should thus
+be as short as possible. Further, long and nested critical sections are prone
+to cause deadlocks and should be avoided.
+As a best practice, a critical section should not span multiple functions and
+there should be only one codepath that leads out of the critical section.
+
+### Dependencies
+
+The wmutex module has no dependencies.
+
+### Function index
+
+| Function | Purpose |
+|-------------------------------------|--------------------------------------|
+| [wmutex_trylock()](#wmutex_trylock) | Try to lock a mutex, without waiting |
+| [wmutex_lock()](#wmutex_lock) | Lock a mutex, waiting if necessary |
+| [wmutex_unlock()](#wmutex_unlock) | Unlock a mutex |
+
+
+## wmutex_trylock()
+
+Try to lock a mutex, without waiting.
+
+### Synopsis
+
+ wmutex_trylock "$mutex"
+
+### Description
+
+The `wmutex_trylock()` function attempts to lock the mutex with the path
+`$mutex`. This function returns immediately, regardless of the outcome of
+the lock operation.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------|
+| 0 | The mutex was successfully locked |
+| 1 | The mutex could not be locked |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## wmutex_lock()
+
+Lock a mutex, waiting if necessary.
+
+### Synopsis
+
+ wmutex_lock "$mutex" "$timeout"
+
+### Description
+
+The `wmutex_lock()` function locks the mutex with the path `$mutex`. If the mutex
+is already locked by another process, this function will wait either until it was
+able to lock the mutex, or until the timeout has expired. If `$timeout` is -1 or
+was omitted, the function will wait indefinitely. Otherwise, it will wait for
+`$timeout` seconds. The actual time that this function waits depends on the
+process scheduler and may be more than `$timeout` seconds.
+If a timeout of 0 is passed, this function is equivalent with `wmutex_trylock()`.
+
+### Return value
+
+| Return value | Meaning |
+|--------------|-----------------------------------|
+| 0 | The mutex was successfully locked |
+| 1 | The mutex could not be locked |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.
+
+
+## wmutex_unlock()
+
+Unlock a mutex.
+
+### Synopsis
+
+ wmutex_unlock "$mutex"
+
+### Description
+
+The `wmutex_unlock()` function unlocks the mutex at the path `$mutex`. If
+`$mutex` is a valid mutex, this function checks whether the running process
+is the owner of the mutex (i.e. if the running process is the process that
+locked the mutex) and, if it is not the owner, refuses to unlock the mutex.
+
+
+### Return value
+
+| Return value | Meaning |
+|--------------|--------------------------------------------|
+| 0 | The mutex was successfully unlocked |
+| 1 | The mutex could not be read |
+| 2 | The running process does not own the mutex |
+| 3 | The mutex could not be removed |
+
+### Standard input
+
+This function does not read from standard input.
+
+### Standard output
+
+This function does not write to standard output.
+
+### Standard error
+
+This function does not write to standard error.