View Source alcove (alcove v1.0.0)

Summary

Functions

Get seccomp system architecture

Convert capsicum constants to integer

Convert capsicum constants to integer

cap_enter(2): place process into capability mode

cap_enter(2): place process into capability mode

cap_fcntls_get(2): get allowed fcntl commands in capability mode

cap_fcntls_get(2): get allowed fcntl commands in capability mode

cap_fcntls_limit(2): manage fcntl commands in capability mode

cap_fcntls_limit(2): manage fcntl commands in capability mode

cap_getmode(2): check if capability mode is enabled

cap_getmode(2): check if capability mode is enabled

cap_ioctls_limit(2): manage allowed ioctl commands

cap_ioctls_limit(2): manage allowed ioctl commands

cap_rights_limit(2): manage process capabilities

cap_rights_limit(2): manage process capabilities

chdir(2): change process current working directory

chdir(2): change process current working directory

chmod(2): change file permissions

chmod(2): change file permissions

chown(2): change file ownership

chown(2): change file ownership

chroot(2): change root directory

chroot(2): change root directory

clearenv(3): zero process environment

clearenv(3): zero process environment

clone(2): create a new process

clone(2): create a new process

Map clone(2) symbols to integer constants

Map clone(2) symbols to integer constants

close(2): close a file descriptor

close(2): close a file descriptor

connect(2): initiate a connection on a socket

connect(2): initiate a connection on a socket

Returns the list of child PIDs for this process

Returns the list of child PIDs for this process

Convert constant to integer

environ(7): return the process environment variables

environ(7): return the process environment variables

Close stdin of the process

Close stdin, stdout or stderr of the process

Convert errno integer to atom

Convert errno integer to atom

Get events generated by alcove port process

Get events generated by alcove port process

execve(2): replace process image with environment

execve(2): replace process image with environment

execvp(2): replace the current process image using the search path

execvp(2): replace the current process image using the search path

exit(3): cause an alcove control process to exit

exit(3): cause an alcove control process to exit

fcntl(2): perform operations on a file descriptor

fcntl(2): perform operations on a file descriptor

Convert fnctl(2) constant to integer

Convert fnctl(2) constant to integer

fexecve(2): replace the process image

fexecve(2): replace the process image

Constants for open(2)

Create a call filter list

Restrict calls available to an alcove control process

Restrict available calls for control and subprocess

Restrict available calls for control and subprocess

fork(2): create a new process

fork(2): create a new process

Get control process attributes

getcwd(3): return the current working directory

getcwd(3): return the current working directory

getenv(3): retrieve an environment variable

getenv(3): retrieve an environment variable

getgid(2): retrieve the process group ID

getgid(2): retrieve the process group ID

getgroups(2): retrieve the list of supplementary groups

getgroups(2): retrieve the list of supplementary groups

gethostname(2): retrieve the system hostname

gethostname(2): retrieve the system hostname

Retrieve port options for event loop

Retrieve port options for event loop

getpgrp(2): retrieve the process group

getpgrp(2): retrieve the process group

getpid(2): retrieve the system PID of the process

getpid(2): retrieve the system PID of the process

getpriority(2): retrieve scheduling priority of process, process group or user

getpriority(2): retrieve scheduling priority of process, process group or user

getresgid(2): get real, effective and saved group ID

getresgid(2): get real, effective and saved group ID

getresuid(2): get real, effective and saved user ID

getresuid(2): get real, effective and saved user ID

getrlimit(2): retrieve the resource limits for a process

getrlimit(2): retrieve the resource limits for a process

getsid(2): retrieve the session ID

getsid(2): retrieve the session ID

getuid(2): returns the process user ID

getuid(2): returns the process user ID

ioctl(2): control device

Convert ioctl constant to integer

Convert ioctl constant to integer

jail(2): restrict the current process in a system jail

jail(2): restrict the current process in a system jail

jail_attach(2): join a jailed process

jail_attach(2): join a jailed process

jail_remove(2): destroy a jailed process

jail_remove(2): destroy a jailed process

kill(2): terminate a process

kill(2): terminate a process

link(2) : create a hard link

link(2) : create a hard link

lseek(2): set file offset for read/write

lseek(2): set file offset for read/write

mkdir(2): create a directory

mkdir(2): create a directory

mkfifo(3): make named pipe file

mkfifo(3): make named pipe file

mount(2): mount a filesystem, Linux style

Convert flag names to integers

Convert flag names to integers

open(2): returns a file descriptor associated with a file

open(2): returns a file descriptor associated with a file

pivot_root(2): change the root mount

pivot_root(2): change the root mount

pledge(2): restrict system operations

pledge(2): restrict system operations

prctl(2): operations on a process

Convert prctl option names to integers

Convert prctl option names to integers

procctl(2): control processes

Convert ptrace constant to integer

Convert ptrace constant to integer

read(2): read bytes from a file descriptor

read(2): read bytes from a file descriptor

readdir(3): retrieve list of objects in a directory

readdir(3): retrieve list of objects in a directory

Convert an RLIMIT_* flag to an integer

Convert an RLIMIT_* flag to an integer

rmdir(2): delete a directory

rmdir(2): delete a directory

seccomp(2): restrict system operations

seccomp(2): restrict system operations

Convert seccomp option name to integer

Convert seccomp option name to integer

select(2): poll a list of file descriptor for events

select(2): poll a list of file descriptor for events

Set options for child process of alcove control process

Set options for child process of alcove control process

setenv(3): set an environment variable

setenv(3): set an environment variable

setgid(2): set the GID of the process

setgid(2): set the GID of the process

setgroups(2): set the supplementary groups of the process

setgroups(2): set the supplementary groups of the process

sethostname(2): set the system hostname

sethostname(2): set the system hostname

setns(2): attach to a namespace

setns(2): attach to a namespace

Set port options

setpgid(2): set process group

setpgid(2): set process group

setpriority(2): set scheduling priority of process, process group or user

setpriority(2): set scheduling priority of process, process group or user

setproctitle(3): set the process title

setproctitle(3): set the process title

setresgid(2): set real, effective and saved group ID

setresgid(2): set real, effective and saved group ID

setresuid(2): set real, effective and saved user ID

setresuid(2): set real, effective and saved user ID

setrlimit(2): set a resource limit

setrlimit(2): set a resource limit

setsid(2): create a new session

setsid(2): create a new session

setuid(2): change UID

setuid(2): change UID

sigaction(2): set process behaviour for signals

sigaction(2): set process behaviour for signals

Convert signal names to integers

Convert signal names to integers

socket(2): returns a file descriptor for a communication endpoint

socket(2): returns a file descriptor for a communication endpoint

Read stderr from the process

Send data to stdin of the process

Read stdout from the process

symlink(2): create a symbolic link

symlink(2): create a symbolic link

Convert syscall name to integer

Convert syscall name to integer

umount2(2): unmount filesystem with flags

umount2(2): unmount filesystem with flags

umount(2): unmount a filesystem

umount(2): unmount a filesystem

unlink(2): delete a name from the filesystem

unlink(2): delete a name from the filesystem

unsetenv(3): remove an environment variable

unsetenv(3): remove an environment variable

unshare(2): create a new namespace in the current process

unshare(2): create a new namespace in the current process

unveil(2): restrict filesystem view

unveil(2): restrict filesystem view

Retrieve the alcove version

Retrieve the alcove version

waitpid(2): wait for process to change state

waitpid(2): wait for process to change state

write(2): write to a file descriptor

write(2): write to a file descriptor

Types

alcove_pid/0

-type alcove_pid() ::
          #alcove_pid{pid :: alcove:pid_t(),
                      flowcontrol :: alcove:int32_t(),
                      signaloneof :: alcove:int32_t(),
                      fdctl :: alcove:fd(),
                      stdin :: alcove:fd(),
                      stdout :: alcove:fd(),
                      stderr :: alcove:fd()}.

alcove_pid_field/0

-type alcove_pid_field() :: pid | flowcontrol | signaloneof | fdctl | stdin | stdout | stderr.

alcove_rlimit/0

-type alcove_rlimit() :: #alcove_rlimit{cur :: alcove:uint64_t(), max :: alcove:uint64_t()}.

alcove_timeval/0

-type alcove_timeval() :: #alcove_timeval{sec :: non_neg_integer(), usec :: non_neg_integer()}.

constant/0

-type constant() :: atom() | integer().

cstruct/0

-type cstruct() :: [binary() | {ptr, binary() | non_neg_integer()}, ...].

fd/0

-type fd() :: int32_t().

fd_set/0

-type fd_set() :: [fd()].

filter/0

-type filter() ::
          alcove_proto:calls() |
          [] |
          {deny, alcove_proto:calls() | []} |
          {allow, alcove_proto:calls() | []}.

gid_t/0

-type gid_t() :: uint32_t().

int8_t/0

-type int8_t() :: -127..127.

int16_t/0

-type int16_t() :: -32767..32767.

int32_t/0

-type int32_t() :: -2147483647..2147483647.

int64_t/0

-type int64_t() :: -9223372036854775807..9223372036854775807.

mode_t/0

-type mode_t() :: uint32_t().

off_t/0

-type off_t() :: uint64_t().

pid_t/0

-type pid_t() :: int32_t().

posix/0

-type posix() ::
          e2big | eacces | eaddrinuse | eaddrnotavail | eadv | eafnosupport | eagain | ealign |
          ealready | ebade | ebadf | ebadfd | ebadmsg | ebadr | ebadrpc | ebadrqc | ebadslt | ebfont |
          ebusy | ecapmode | echild | echrng | ecomm | econnaborted | econnrefused | econnreset |
          edeadlk | edeadlock | edestaddrreq | edirty | edom | edotdot | edquot | eduppkg | eexist |
          efault | efbig | ehostdown | ehostunreach | eidrm | einit | einprogress | eintr | einval |
          eio | eisconn | eisdir | eisnam | el2hlt | el2nsync | el3hlt | el3rst | elbin | elibacc |
          elibbad | elibexec | elibmax | elibscn | elnrng | eloop | emfile | emlink | emsgsize |
          emultihop | enametoolong | enavail | enet | enetdown | enetreset | enetunreach | enfile |
          enoano | enobufs | enocsi | enodata | enodev | enoent | enoexec | enolck | enolink | enomem |
          enomsg | enonet | enopkg | enoprotoopt | enospc | enosr | enostr | enosym | enosys | enotblk |
          enotcapable | enotconn | enotdir | enotempty | enotnam | enotrecoverable | enotsock |
          enotsup | enotty | enotuniq | enxio | eopnotsupp | eoverflow | eownerdead | eperm |
          epfnosupport | epipe | eproclim | eprocunavail | eprogmismatch | eprogunavail | eproto |
          eprotonosupport | eprototype | erange | erefused | eremchg | eremdev | eremote | eremoteio |
          eremoterelease | erofs | erpcmismatch | erremote | eshutdown | esocktnosupport | espipe |
          esrch | esrmnt | estale | esuccess | etime | etimedout | etoomanyrefs | etxtbsy | euclean |
          eunatch | eusers | eversion | ewouldblock | exdev | exfull.

ptr_arg/0

-type ptr_arg() :: binary() | constant() | cstruct().

ptr_val/0

-type ptr_val() :: binary() | integer() | cstruct().

size_t/0

-type size_t() :: uint64_t().

ssize_t/0

-type ssize_t() :: int64_t().

uid_t/0

-type uid_t() :: uint32_t().

uint8_t/0

-type uint8_t() :: 0..255.

uint16_t/0

-type uint16_t() :: 0..65535.

uint32_t/0

-type uint32_t() :: 0..4294967295.

uint64_t/0

-type uint64_t() :: 0..18446744073709551615.

waitstatus/0

-type waitstatus() :: {exit_status, int32_t()} | {termsig, atom()} | {stopsig, atom()} | continued.

Functions

audit_arch()

-spec audit_arch() -> atom().

Get seccomp system architecture

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:audit_arch().
 audit_arch_x86_64
 3> alcove:define(Drv, [], alcove:audit_arch()).
 3221225534

cap_constant(Drv, Pids, Symbol)

-spec cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.

Convert capsicum constants to integer

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
 16

cap_constant(Drv, Pids, Symbol, Timeout)

-spec cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.

Convert capsicum constants to integer

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
 16

cap_enter(Drv, Pids)

-spec cap_enter(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.

cap_enter(2): place process into capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> {ok, Pid1} = alcove:fork(Drv, []).
 {ok,75331}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,75332}
 4> ok = alcove:cap_enter(Drv, [Pid1]).
 ok
 5> alcove:kill(Drv, [Pid1], 0, 0).
 {error,ecapmode}
 6> alcove:kill(Drv, [Pid2], 0, 0).
 ok
 7> alcove:kill(Drv, [], 0, 0).
 ok

cap_enter(Drv, Pids, Timeout)

-spec cap_enter(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.

cap_enter(2): place process into capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> {ok, Pid1} = alcove:fork(Drv, []).
 {ok,75331}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,75332}
 4> ok = alcove:cap_enter(Drv, [Pid1]).
 ok
 5> alcove:kill(Drv, [Pid1], 0, 0).
 {error,ecapmode}
 6> alcove:kill(Drv, [Pid2], 0, 0).
 ok
 7> alcove:kill(Drv, [], 0, 0).
 ok

cap_fcntls_get(Drv, Pids, FD)

-spec cap_fcntls_get(alcove_drv:ref(), [pid_t()], FD :: fd()) -> {ok, integer()} | {error, posix()}.

cap_fcntls_get(2): get allowed fcntl commands in capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,77853}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,120}

cap_fcntls_get(Drv, Pids, FD, Timeout)

-spec cap_fcntls_get(alcove_drv:ref(), [pid_t()], FD :: fd(), timeout()) ->
                        {ok, integer()} | {error, posix()}.

cap_fcntls_get(2): get allowed fcntl commands in capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,77853}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,120}

cap_fcntls_limit(Drv, Pids, FD, Rights)

-spec cap_fcntls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) ->
                          ok | {error, posix()}.

cap_fcntls_limit(2): manage fcntl commands in capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,77853}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,120}
 6> ok = alcove:cap_fcntls_limit(Drv, [Pid], FD, [cap_fcntl_setfl]).
 ok
 7> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,16}

cap_fcntls_limit(Drv, Pids, FD, Rights, Timeout)

-spec cap_fcntls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) ->
                          ok | {error, posix()}.

cap_fcntls_limit(2): manage fcntl commands in capability mode

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,77853}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,120}
 6> ok = alcove:cap_fcntls_limit(Drv, [Pid], FD, [cap_fcntl_setfl]).
 ok
 7> alcove:cap_fcntls_get(Drv, [Pid], FD).
 {ok,16}

cap_getmode(Drv, Pids)

-spec cap_getmode(alcove_drv:ref(), [pid_t()]) -> {ok, 0 | 1} | {error, posix()}.

cap_getmode(2): check if capability mode is enabled

* 0 : false

* 1 : true

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 4> alcove:cap_getmode(Drv, [Pid]).
 {ok,1}
 5> alcove:cap_getmode(Drv, []).
 {ok,0}

cap_getmode(Drv, Pids, Timeout)

-spec cap_getmode(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, 0 | 1} | {error, posix()}.

cap_getmode(2): check if capability mode is enabled

* 0 : false

* 1 : true

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> ok = alcove:cap_enter(Drv, [Pid]).
 ok
 4> alcove:cap_getmode(Drv, [Pid]).
 {ok,1}
 5> alcove:cap_getmode(Drv, []).
 {ok,0}

cap_ioctls_limit(Drv, Pids, FD, Rights)

-spec cap_ioctls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) ->
                          ok | {error, posix()}.

cap_ioctls_limit(2): manage allowed ioctl commands

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/pts/1", [o_rdwr, o_nonblock], 0).
 {ok,6}
 4> alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_ioctls_limit(Drv, [Pid], FD, [tiocmget, tiocgwinsz]).
 ok
 6> alcove:ioctl(Drv, [Pid], FD, tiocmset, <<>>).
 {error,enotcapable}
 7> alcove:ioctl(Drv, [Pid], FD, tiocmget, <<>>).
 {ok,0,<<>>}

cap_ioctls_limit(Drv, Pids, FD, Rights, Timeout)

-spec cap_ioctls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) ->
                          ok | {error, posix()}.

cap_ioctls_limit(2): manage allowed ioctl commands

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/pts/1", [o_rdwr, o_nonblock], 0).
 {ok,6}
 4> alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_ioctls_limit(Drv, [Pid], FD, [tiocmget, tiocgwinsz]).
 ok
 6> alcove:ioctl(Drv, [Pid], FD, tiocmset, <<>>).
 {error,enotcapable}
 7> alcove:ioctl(Drv, [Pid], FD, tiocmget, <<>>).
 {ok,0,<<>>}

cap_rights_limit(Drv, Pids, FD, Rights)

-spec cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) ->
                          ok | {error, posix()}.

cap_rights_limit(2): manage process capabilities

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_rights_limit(Drv, [Pid], FD, [cap_read]).
 ok
 6> alcove:read(Drv, [Pid], FD, 64).
 {ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
 7> alcove:lseek(Drv, [Pid], FD, 0, 0).
 {error,enotcapable}
 8> alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {error,ecapmode}

cap_rights_limit(Drv, Pids, FD, Rights, Timeout)

-spec cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) ->
                          ok | {error, posix()}.

cap_rights_limit(2): manage process capabilities

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:cap_enter(Drv, [Pid]).
 ok
 5> alcove:cap_rights_limit(Drv, [Pid], FD, [cap_read]).
 ok
 6> alcove:read(Drv, [Pid], FD, 64).
 {ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
 7> alcove:lseek(Drv, [Pid], FD, 0, 0).
 {error,enotcapable}
 8> alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {error,ecapmode}

chdir(Drv, Pids, Path)

-spec chdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.

chdir(2): change process current working directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18617}
 3> alcove:chdir(Drv, [Pid], "/tmp").
 ok
 4> alcove:chdir(Drv, [], "/").
 ok
 5> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/tmp">>}
 6> alcove:getcwd(Drv, []).
 {ok,<<"/">>}

chdir(Drv, Pids, Path, Timeout)

-spec chdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.

chdir(2): change process current working directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18617}
 3> alcove:chdir(Drv, [Pid], "/tmp").
 ok
 4> alcove:chdir(Drv, [], "/").
 ok
 5> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/tmp">>}
 6> alcove:getcwd(Drv, []).
 {ok,<<"/">>}

chmod(Drv, Pids, Path, Mode)

-spec chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.

chmod(2): change file permissions

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:chmod(Drv, [Pid], "/tmp/foo123.txt", 8#400).
 ok

chmod(Drv, Pids, Path, Mode, Timeout)

-spec chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) ->
               ok | {error, posix()}.

chmod(2): change file permissions

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:chmod(Drv, [Pid], "/tmp/foo123.txt", 8#400).
 ok

chown(Drv, Pids, Path, Owner, Group)

-spec chown(alcove_drv:ref(), [pid_t()], Path :: iodata(), Owner :: uid_t(), Group :: gid_t()) ->
               ok | {error, posix()}.

chown(2): change file ownership

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 6> alcove:chown(Drv, [Pid], "/tmp/foo123.txt", 0, 0).
 ok

chown(Drv, Pids, Path, Owner, Group, Timeout)

-spec chown(alcove_drv:ref(),
            [pid_t()],
            Path :: iodata(),
            Owner :: uid_t(),
            Group :: gid_t(),
            timeout()) ->
               ok | {error, posix()}.

chown(2): change file ownership

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 6> alcove:chown(Drv, [Pid], "/tmp/foo123.txt", 0, 0).
 ok

chroot(Drv, Pids, Path)

-spec chroot(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.

chroot(2): change root directory

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:chroot(Drv, [Pid], "/tmp").
 ok
 4> alcove:chdir(Drv, [Pid], "/").
 ok
 5> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/">>}

chroot(Drv, Pids, Path, Timeout)

-spec chroot(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.

chroot(2): change root directory

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:chroot(Drv, [Pid], "/tmp").
 ok
 4> alcove:chdir(Drv, [Pid], "/").
 ok
 5> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/">>}

clearenv(Drv, Pids)

-spec clearenv(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.

clearenv(3): zero process environment

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:clearenv(Drv, [Pid]).
 ok
 4> alcove:environ(Drv, [Pid]).
 []

clearenv(Drv, Pids, Timeout)

-spec clearenv(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.

clearenv(3): zero process environment

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:clearenv(Drv, [Pid]).
 ok
 4> alcove:environ(Drv, [Pid]).
 []

clone(Drv, Pids, Flags)

-spec clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()]) ->
               {ok, pid_t()} | {error, posix()}.

clone(2): create a new process

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns, clone_newpid, clone_newipc, clone_newuts, clone_newnet]).
 {ok,19127}
 3> alcove:getpid(Drv, [Pid]).
 1

clone(Drv, Pids, Flags, Timeout)

-spec clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()], timeout()) ->
               {ok, pid_t()} | {error, posix()}.

clone(2): create a new process

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns, clone_newpid, clone_newipc, clone_newuts, clone_newnet]).
 {ok,19127}
 3> alcove:getpid(Drv, [Pid]).
 1

clone_constant(Drv, Pids, Symbol)

-spec clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | int32_t().

Map clone(2) symbols to integer constants

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:clone_constant(Drv, [19127], clone_newuts).
 67108864

clone_constant(Drv, Pids, Symbol, Timeout)

-spec clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | int32_t().

Map clone(2) symbols to integer constants

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:clone_constant(Drv, [19127], clone_newuts).
 67108864

close(Drv, Pids, FD)

-spec close(alcove_drv:ref(), [pid_t()], FD :: fd()) -> ok | {error, posix()}.

close(2): close a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:close(Drv, [Pid], FD).
 ok

close(Drv, Pids, FD, Timeout)

-spec close(alcove_drv:ref(), [pid_t()], FD :: fd(), timeout()) -> ok | {error, posix()}.

close(2): close a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:close(Drv, [Pid], FD).
 ok

connect(Drv, Pids, FD, Sockaddr)

-spec connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct()) ->
                 ok | {error, posix()}.

connect(2): initiate a connection on a socket

Examples

 -module(unix_socket).

 -export([connect]).

 connect(Data) when is_binary(Data) ->
     {ok, Drv} = alcove:start(),
     {ok, NC} = alcove:fork(Drv, []),
     {ok, Process} = alcove:fork(Drv, []),

     Sockname = <<"/tmp/test.", (integer_to_binary(alcove:getpid(Drv, [])))/binary>>,
     ok = alcove:execvp(Drv, [NC], "nc", ["nc", "-l", "-U", Sockname]),

     ok = waitfor(Sockname),

     {ok, Socket} = alcove:socket(Drv, [Process], af_unix, sock_stream, 0),

     % #define UNIX_PATH_MAX   108
     % struct sockaddr_un {
     % 	__kernel_sa_family_t sun_family; /* AF_UNIX */
     % 	char sun_path[UNIX_PATH_MAX];   /* pathname */
     % };
     AF_UNIX = 1,
     SocknameLen = byte_size(Sockname),
     Len = (unix_path_max() - SocknameLen) * 8,
     ok = alcove:connect(Drv, [Process], Socket, [
         sockaddr_common(AF_UNIX, SocknameLen),
         Sockname,
         <<0:Len>>
     ]),

     % alcove process -> nc
     {ok, N} = alcove:write(Drv, [Process], Socket, Data),
     receive
         {alcove_stdout, Drv, [NC], Stdout} ->
             Stdout
     end.

 % UNIX_PATH_MAX
 unix_path_max() ->
     case erlang:system_info(os_type) of
         {unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
             104;
         {unix, _} ->
             108
     end.

 % struct sockaddr
 sockaddr_common(Family, Length) ->
     case erlang:system_info(os_type) of
         {unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
             <<Length:8, Family:8>>;
         {unix, _} ->
             <<Family:16/native>>
     end.

 waitfor(Sockname) ->
     case file:read_file_info(Sockname) of
         {ok, _} ->
             ok;
         {error, enoent} ->
             timer:sleep(1),
             waitfor(Sockname);
         {error, eperm} ->
             ok;
         Error ->
             Error
     end.

connect(Drv, Pids, FD, Sockaddr, Timeout)

-spec connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct(), timeout()) ->
                 ok | {error, posix()}.

connect(2): initiate a connection on a socket

Examples

 -module(unix_socket).

 -export([connect]).

 connect(Data) when is_binary(Data) ->
     {ok, Drv} = alcove:start(),
     {ok, NC} = alcove:fork(Drv, []),
     {ok, Process} = alcove:fork(Drv, []),

     Sockname = <<"/tmp/test.", (integer_to_binary(alcove:getpid(Drv, [])))/binary>>,
     ok = alcove:execvp(Drv, [NC], "nc", ["nc", "-l", "-U", Sockname]),

     ok = waitfor(Sockname),

     {ok, Socket} = alcove:socket(Drv, [Process], af_unix, sock_stream, 0),

     % #define UNIX_PATH_MAX   108
     % struct sockaddr_un {
     % 	__kernel_sa_family_t sun_family; /* AF_UNIX */
     % 	char sun_path[UNIX_PATH_MAX];   /* pathname */
     % };
     AF_UNIX = 1,
     SocknameLen = byte_size(Sockname),
     Len = (unix_path_max() - SocknameLen) * 8,
     ok = alcove:connect(Drv, [Process], Socket, [
         sockaddr_common(AF_UNIX, SocknameLen),
         Sockname,
         <<0:Len>>
     ]),

     % alcove process -> nc
     {ok, N} = alcove:write(Drv, [Process], Socket, Data),
     receive
         {alcove_stdout, Drv, [NC], Stdout} ->
             Stdout
     end.

 % UNIX_PATH_MAX
 unix_path_max() ->
     case erlang:system_info(os_type) of
         {unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
             104;
         {unix, _} ->
             108
     end.

 % struct sockaddr
 sockaddr_common(Family, Length) ->
     case erlang:system_info(os_type) of
         {unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
             <<Length:8, Family:8>>;
         {unix, _} ->
             <<Family:16/native>>
     end.

 waitfor(Sockname) ->
     case file:read_file_info(Sockname) of
         {ok, _} ->
             ok;
         {error, enoent} ->
             timer:sleep(1),
             waitfor(Sockname);
         {error, eperm} ->
             ok;
         Error ->
             Error
     end.

cpid(Drv, Pids)

-spec cpid(alcove_drv:ref(), [pid_t()]) -> [alcove_pid()].

Returns the list of child PIDs for this process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid1} = alcove:fork(Drv, []).
 {ok,19048}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,19127}
 4> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 5> alcove:cpid(Drv, [Pid1]).
 []
 6> alcove:cpid(Drv, []).
 [#alcove_pid{pid = 19048,flowcontrol = -1,signaloneof = 15,
              fdctl = 7,stdin = 9,stdout = 10,stderr = 12},
  #alcove_pid{pid = 19127,flowcontrol = -1,signaloneof = 15,
              fdctl = 8,stdin = 13,stdout = 14,stderr = 16}]

cpid(Drv, Pids, Timeout)

-spec cpid(alcove_drv:ref(), [pid_t()], timeout()) -> [alcove_pid()].

Returns the list of child PIDs for this process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid1} = alcove:fork(Drv, []).
 {ok,19048}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,19127}
 4> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 5> alcove:cpid(Drv, [Pid1]).
 []
 6> alcove:cpid(Drv, []).
 [#alcove_pid{pid = 19048,flowcontrol = -1,signaloneof = 15,
              fdctl = 7,stdin = 9,stdout = 10,stderr = 12},
  #alcove_pid{pid = 19127,flowcontrol = -1,signaloneof = 15,
              fdctl = 8,stdin = 13,stdout = 14,stderr = 16}]

define(Drv, Pipeline, Constant)

-spec define(alcove_drv:ref(), [pid_t()], atom() | [atom()]) -> integer().

Convert constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:define(Drv, [], clone_newns).
 131072

environ(Drv, Pids)

-spec environ(alcove_drv:ref(), [pid_t()]) -> [binary()].

environ(7): return the process environment variables

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:environ(Drv, []).
 [<<"LANG=C.UTF-8">>,
  <<"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin">>,
  <<"TERM=screen">>, <<"SHELL=/bin/bash">>]

environ(Drv, Pids, Timeout)

-spec environ(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].

environ(7): return the process environment variables

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:environ(Drv, []).
 [<<"LANG=C.UTF-8">>,
  <<"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin">>,
  <<"TERM=screen">>, <<"SHELL=/bin/bash">>]

eof(Drv, Pids)

-spec eof(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.

Close stdin of the process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:eof(Drv, [Pid]).
 ok
 5> alcove:event(Drv, [Pid]).
 {exit_status,0}

eof(Drv, Pids, Stdio)

-spec eof(alcove_drv:ref(), [pid_t()], stdin | stdout | stderr) -> ok | {error, posix()}.

Close stdin, stdout or stderr of the process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:eof(Drv, [Pid], stdin).
 ok
 5> alcove:event(Drv, [Pid]).
 {exit_status,0}

errno_id(Drv, Pids, Errno)

-spec errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t()) -> posix().

Convert errno integer to atom

Examples

 1> alcove:errno_id(Drv, [], 1).
 eperm

errno_id(Drv, Pids, Errno, Timeout)

-spec errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t(), timeout()) -> posix().

Convert errno integer to atom

Examples

 1> alcove:errno_id(Drv, [], 1).
 eperm

event(Drv, Pids)

-spec event(alcove_drv:ref(), [pid_t()]) -> term().

Get events generated by alcove port process

event/1,2 is used to retrieve async messages returned from the port, such as caught signals, the exit status or the termination signal.

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:kill(Drv, [], Pid, 15).
 ok
 4> alcove:event(Drv, [Pid]).
 {signal,sigterm,
         <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,74,0,0,0,0,0,0,0,
                   0,...>>}

event(Drv, Pids, Timeout)

-spec event(alcove_drv:ref(), [pid_t()], timeout()) -> term().

Get events generated by alcove port process

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,19048}
 3> alcove:kill(Drv, [], Pid, 15).
 ok
 4> alcove:event(Drv, [Pid], 5000).
 {signal,sigterm,
         <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,74,0,0,0,0,0,0,0,
                   0,...>>}
 5> alcove:event(Drv, [Pid], 5000).
 false

execve(Drv, Pids, Arg0, Argv, Env)

-spec execve(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()], Env :: [iodata()]) ->
                ok | {error, posix()}.

execve(2): replace process image with environment

Replace the process image, specifying the environment for the new process image.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,29037}
 3> alcove:execve(Drv, [Pid], "/usr/bin/env", ["env"], ["FOO=123"]).
 ok

 % Shell got {alcove_stdout,<0.176.0>,[29037],<<"FOO=123\n">>}
 % Shell got {alcove_event,<0.176.0>,[29037],{exit_status,0}}

 4> alcove:stdout(Drv, [Pid]).
 [<<"FOO=123\n">>]
 5> alcove:event(Drv, [Pid], 5000).
 {exit_status,0}
 ok

execve(Drv, Pids, Arg0, Argv, Env, Timeout)

-spec execve(alcove_drv:ref(),
             [pid_t()],
             Arg0 :: iodata(),
             Argv :: [iodata()],
             Env :: [iodata()],
             timeout()) ->
                ok | {error, posix()}.

execve(2): replace process image with environment

Replace the process image, specifying the environment for the new process image.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,29037}
 3> alcove:execve(Drv, [Pid], "/usr/bin/env", ["env"], ["FOO=123"]).
 ok

 % Shell got {alcove_stdout,<0.176.0>,[29037],<<"FOO=123\n">>}
 % Shell got {alcove_event,<0.176.0>,[29037],{exit_status,0}}

 4> alcove:stdout(Drv, [Pid]).
 [<<"FOO=123\n">>]
 5> alcove:event(Drv, [Pid], 5000).
 {exit_status,0}
 ok

execvp(Drv, Pids, Arg0, Argv)

-spec execvp(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()]) -> ok | {error, posix()}.

execvp(2): replace the current process image using the search path

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,29087}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:stdin(Drv, [Pid], "test\n").
 ok
 5> alcove:stdout(Drv, [Pid]).
 [<<"test\n">>]
 6> alcove:stdin(Drv, [Pid], "123\n").
 ok
 7> flush().
 Shell got {alcove_stdout,<0.176.0>,[29087],<<"123\n">>}
 ok

execvp(Drv, Pids, Arg0, Argv, Timeout)

-spec execvp(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()], timeout()) ->
                ok | {error, posix()}.

execvp(2): replace the current process image using the search path

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,29087}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:stdin(Drv, [Pid], "test\n").
 ok
 5> alcove:stdout(Drv, [Pid]).
 [<<"test\n">>]
 6> alcove:stdin(Drv, [Pid], "123\n").
 ok
 7> flush().
 Shell got {alcove_stdout,<0.176.0>,[29087],<<"123\n">>}
 ok

exit(Drv, Pids, Status)

-spec exit(alcove_drv:ref(), [pid_t()], Status :: int32_t()) -> ok.

exit(3): cause an alcove control process to exit

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,30973}
 3> alcove:exit(Drv, [Pid], 111).
 ok
 4> flush().
 Shell got {alcove_event,<0.176.0>,[30973],{exit_status,111}}
 ok

exit(Drv, Pids, Status, Timeout)

-spec exit(alcove_drv:ref(), [pid_t()], Status :: int32_t(), timeout()) -> ok.

exit(3): cause an alcove control process to exit

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,30973}
 3> alcove:exit(Drv, [Pid], 111).
 ok
 4> flush().
 Shell got {alcove_event,<0.176.0>,[30973],{exit_status,111}}
 ok

fcntl(Drv, Pids, FD, Cmd, Arg)

-spec fcntl(alcove_drv:ref(), [pid_t()], FD :: fd(), Cmd :: constant(), Arg :: int64_t()) ->
               {ok, int64_t()} | {error, posix()}.

fcntl(2): perform operations on a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,31012}

 % stdin = 0
 3> alcove:fcntl(Drv, [Pid], 0, f_getfd, 0).
 {ok,0}

fcntl(Drv, Pids, FD, Cmd, Arg, Timeout)

-spec fcntl(alcove_drv:ref(), [pid_t()], FD :: fd(), Cmd :: constant(), Arg :: int64_t(), timeout()) ->
               {ok, int64_t()} | {error, posix()}.

fcntl(2): perform operations on a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.176.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,31012}

 % stdin = 0
 3> alcove:fcntl(Drv, [Pid], 0, f_getfd, 0).
 {ok,0}

fcntl_constant(Drv, Pids, Symbol)

-spec fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.

Convert fnctl(2) constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:fcntl_constant(Drv, [], fd_cloexec).
 1

fcntl_constant(Drv, Pids, Symbol, Timeout)

-spec fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.

Convert fnctl(2) constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.176.0>}
 2> alcove:fcntl_constant(Drv, [], fd_cloexec).
 1

fexecve(Drv, Pids, FD, Argv, Env)

-spec fexecve(alcove_drv:ref(), [pid_t()], FD :: fd(), Argv :: [iodata()], Env :: [iodata()]) ->
                 ok | {error, posix()}.

fexecve(2): replace the process image

Replace the process image, specifying the environment for the new process image, using a previously opened file descriptor. The file descriptor can be set to close after exec() by passing the O_CLOEXEC flag to open:

 {ok, Pid} = alcove:fork(Drv, []),
 {ok, FD} = alcove:open(Drv, [Pid], "/bin/ls", [o_rdonly,o_cloexec], 0),
 ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], ["FOO=123"]).

Linux requires an environment to be set unlike with execve(2). The environment can be empty:

 % Environment required on Linux
 ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], [""]).

Support

* Linux

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,31491}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/usr/bin/env", [o_rdonly,o_cloexec], 0).
 {ok,6}
 4> alcove:fexecve(Drv, [Pid], FD, ["env", "-0"], ["FOO=123"]).
 ok
 5> flush().
 Shell got {alcove_stdout,<0.177.0>,[31491],<<70,79,79,61,49,50,51,0>>}
 Shell got {alcove_event,<0.177.0>,[31491],{exit_status,0}}
 ok

fexecve(Drv, Pids, FD, Argv, Env, Timeout)

-spec fexecve(alcove_drv:ref(), [pid_t()], FD :: fd(), Argv :: [iodata()], Env :: [iodata()], timeout()) ->
                 ok | {error, posix()}.

fexecve(2): replace the process image

Replace the process image, specifying the environment for the new process image, using a previously opened file descriptor. The file descriptor can be set to close after exec() by passing the O_CLOEXEC flag to open:

 {ok, Pid} = alcove:fork(Drv, []),
 {ok, FD} = alcove:open(Drv, [Pid], "/bin/ls", [o_rdonly,o_cloexec], 0),
 ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], ["FOO=123"]).

Linux requires an environment to be set unlike with execve(2). The environment can be empty:

 % Environment required on Linux
 ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], [""]).

Support

* Linux

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,31491}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/usr/bin/env", [o_rdonly,o_cloexec], 0).
 {ok,6}
 4> alcove:fexecve(Drv, [Pid], FD, ["env", "-0"], ["FOO=123"]).
 ok
 5> flush().
 Shell got {alcove_stdout,<0.177.0>,[31491],<<70,79,79,61,49,50,51,0>>}
 Shell got {alcove_event,<0.177.0>,[31491],{exit_status,0}}
 ok

file_constant(Drv, Pids, Symbol)

-spec file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> non_neg_integer() | unknown.

Constants for open(2)

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:file_constant(Drv, [], o_rdonly).
 0

file_constant(Drv, Pids, Symbol, Timeout)

-spec file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                       non_neg_integer() | unknown.

Constants for open(2)

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:file_constant(Drv, [], o_rdonly).
 0

filter(Calls)

-spec filter(filter()) -> binary().

Create a call filter list

Generate a list of calls to filter for filter/3,4. By default, calls are blocked. To restrict the alcove control process to a subset of calls, use the allow tuple:

 # alcove process restricted to fork, clone, getpid
 alcove:filter({allow, [fork, clone, getpid]})

Examples

 1> alcove:filter({allow, [fork, clone, getpid]}).
 <<255,223,255,239,239,255,255,255,255,255,255,255,15>>
 2> alcove:filter([fork, clone, getpid]).
 <<0,32,0,16,16>>
 3> alcove:filter({deny, [fork, clone, getpid]}).
 <<0,32,0,16,16>>

filter(Drv, Pids, Calls)

-spec filter(alcove_drv:ref(), [pid_t()], binary()) -> ok | {error, einval}.

Restrict calls available to an alcove control process

filter/3 restrict calls available to an alcove control process. Restricted control processes continue to proxy data and monitor and reap subprocesses.

Invoking a filtered call will crash the process with 'undef'.

If the filter call is filtered, subsequent calls to filter/3,4 will fail.

Once added, the call cannot be removed from the filter set. Passing an empty binary (<<>>) will not modify the current filter set.

Filters are inherited by the child process from the parent. filter/3 specifies the subprocess should use the same filter as the parent:

 1> catch_exception(true).
 false
 2> {ok, Drv} = alcove_drv:start().
 {ok,<0.179.0>}
 3> {ok, Pid} = alcove:fork(Drv, []).
 {ok,16464}
 4> Filter = alcove:filter([fork]).
 <<0,0,0,16>>
 % equivalent to: alcove:filter(Drv, [], Filter, Filter)
 5> alcove:filter(Drv, [], Filter).
 ok
 6> alcove:fork(Drv, [Pid]).
 * exception error: undefined function alcove:fork/2

filter(Drv, Pids, Calls, Calls)

-spec filter(alcove_drv:ref(), [pid_t()], Calls :: binary(), Calls :: binary()) -> ok | {error, einval}.

Restrict available calls for control and subprocess

filter/4 allows setting different filters for the control and subprocesses:

Examples

 1> catch_exception(true).
 false
 2> {ok, Drv} = alcove_drv:start().
 {ok,<0.189.0>}
 3> F1 = alcove:filter({allow, [fork,filter,getcwd]}).
 <<255,255,255,231,239,255,255,255,255,255,255,255,15>>
 4> F2 = alcove:filter({allow, [getpid,gethostname]}).
 <<255,255,255,223,237,255,255,255,255,255,255,255,15>>
 % Control process: restricted to: fork, filter, getcwd
 % Any forked control subprocess: restricted to: getpid, gethostname
 5> alcove:filter(Drv, [], F1, F2).
 ok
 6> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18721}
 7> alcove:getpid(Drv, [Pid]).
 18721
 8> alcove:getpid(Drv, []).
 * exception error: undefined function alcove:getpid/2
 9> alcove:getcwd(Drv, [Pid]).
 * exception error: undefined function alcove:getcwd/2
 10> alcove:getcwd(Drv, []).
 {ok, <<"/">>}

filter(Drv, Pids, Calls, Calls, Timeout)

-spec filter(alcove_drv:ref(), [pid_t()], Calls :: binary(), Calls :: binary(), timeout()) ->
                ok | {error, einval}.

Restrict available calls for control and subprocess

filter/4 allows setting different filters for the control and subprocesses:

Examples

 1> catch_exception(true).
 false
 2> {ok, Drv} = alcove_drv:start().
 {ok,<0.189.0>}
 3> F1 = alcove:filter({allow, [fork,filter,getcwd]}).
 <<255,255,255,231,239,255,255,255,255,255,255,255,15>>
 4> F2 = alcove:filter({allow, [getpid,gethostname]}).
 <<255,255,255,223,237,255,255,255,255,255,255,255,15>>
 % Control process: restricted to: fork, filter, getcwd
 % Any forked control subprocess: restricted to: getpid, gethostname
 5> alcove:filter(Drv, [], F1, F2).
 ok
 6> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18721}
 7> alcove:getpid(Drv, [Pid]).
 18721
 8> alcove:getpid(Drv, []).
 * exception error: undefined function alcove:getpid/2
 9> alcove:getcwd(Drv, [Pid]).
 * exception error: undefined function alcove:getcwd/2
 10> alcove:getcwd(Drv, []).
 {ok, <<"/">>}

fork(Drv, Pids)

-spec fork(alcove_drv:ref(), [pid_t()]) -> {ok, pid_t()} | {error, posix()}.

fork(2): create a new process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.189.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18721}
 3> alcove:getpid(Drv, [Pid]).
 18721

fork(Drv, Pids, Timeout)

-spec fork(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, pid_t()} | {error, posix()}.

fork(2): create a new process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.189.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18721}
 3> alcove:getpid(Drv, [Pid]).
 18721

getcpid(Drv, Pids, Pid, Key)

-spec getcpid(alcove_drv:ref(), [pid_t()], pid_t(), alcove_pid_field()) -> false | int32_t().

Get control process attributes

Retrieves attributes set by the alcove control process for a child process.

• flowcontrol

Number of messages allowed from process:

-1 : flowcontrol disabled

0 : stdout/stderr for process is not read

1+ : read this many messages from the process

• signaloneof

Signal sent to child process on shutdown.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,3925}
 3> alcove:getcpid(Drv, [], Pid, flowcontrol).
 -1

getcwd(Drv, Pids)

-spec getcwd(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.

getcwd(3): return the current working directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,3925}
 3> alcove:chdir(Drv, [Pid], "/").
 ok
 4> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/">>}

getcwd(Drv, Pids, Timeout)

-spec getcwd(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.

getcwd(3): return the current working directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,3925}
 3> alcove:chdir(Drv, [Pid], "/").
 ok
 4> alcove:getcwd(Drv, [Pid]).
 {ok,<<"/">>}

getenv(Drv, Pids, Name)

-spec getenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> binary() | false.

getenv(3): retrieve an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getenv(Drv, [], "TERM").
 <<"screen">>

getenv(Drv, Pids, Name, Timeout)

-spec getenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> binary() | false.

getenv(3): retrieve an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getenv(Drv, [], "TERM").
 <<"screen">>

getgid(Drv, Pids)

-spec getgid(alcove_drv:ref(), [pid_t()]) -> gid_t().

getgid(2): retrieve the process group ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getgid(Drv, []).
 1000

getgid(Drv, Pids, Timeout)

-spec getgid(alcove_drv:ref(), [pid_t()], timeout()) -> gid_t().

getgid(2): retrieve the process group ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getgid(Drv, []).
 1000

getgroups(Drv, Pids)

-spec getgroups(alcove_drv:ref(), [pid_t()]) -> {ok, [gid_t()]} | {error, posix()}.

getgroups(2): retrieve the list of supplementary groups

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getgroups(Drv, []).
 {ok,[24,20,1000]}

getgroups(Drv, Pids, Timeout)

-spec getgroups(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, [gid_t()]} | {error, posix()}.

getgroups(2): retrieve the list of supplementary groups

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getgroups(Drv, []).
 {ok,[24,20,1000]}

gethostname(Drv, Pids)

-spec gethostname(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.

gethostname(2): retrieve the system hostname

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}

gethostname(Drv, Pids, Timeout)

-spec gethostname(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.

gethostname(2): retrieve the system hostname

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}

getopt(Drv, Pids, Opt)

-spec getopt(alcove_drv:ref(), [pid_t()], Opt :: atom()) -> false | int32_t().

Retrieve port options for event loop

Options are configurable per process, with the default settings inherited from the parent.

The initial values for these options are set for the port by alcove_drv:start/1.

* maxchild : non_neg_integer() : 64

Number of child processes allowed for this control process. The value can be modified using setopt/4,5. Additionally, reducing RLIMIT_NOFILE for the process may result in a reduced maxchild value.

* exit_status : 1 | 0 : 1

Controls whether the controlling Erlang process is informed of a process exit value.

* maxforkdepth : non_neg_integer() : 16

Sets the maximum length of the alcove process pipeline.

* termsig : 1 | 0 : 1

If a child process exits because of a signal, notify the controlling Erlang process.

* flowcontrol : int32_t() : -1 (disabled)

Sets the default flow control behaviour for a newly forked process. Flow control is applied after the child process calls exec().

See setcpid/5.

* signaloneof : 0-255 : 15

Send a signal to a child process on shutdown (stdin of the alcove control process is closed).

See setcpid/5.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getopt(Drv, [], maxforkdepth).
 16

getopt(Drv, Pids, Opt, Timeout)

-spec getopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), timeout()) -> false | int32_t().

Retrieve port options for event loop

Options are configurable per process, with the default settings inherited from the parent.

The initial values for these options are set for the port by alcove_drv:start/1.

* maxchild : non_neg_integer() : 64

Number of child processes allowed for this control process. The value can be modified using setopt/4,5. Additionally, reducing RLIMIT_NOFILE for the process may result in a reduced maxchild value.

* exit_status : 1 | 0 : 1

Controls whether the controlling Erlang process is informed of a process exit value.

* maxforkdepth : non_neg_integer() : 16

Sets the maximum length of the alcove process pipeline.

* termsig : 1 | 0 : 1

If a child process exits because of a signal, notify the controlling Erlang process.

* flowcontrol : int32_t() : -1 (disabled)

Sets the default flow control behaviour for a newly forked process. Flow control is applied after the child process calls exec().

See setcpid/5.

* signaloneof : 0-255 : 15

Send a signal to a child process on shutdown (stdin of the alcove control process is closed).

See setcpid/5.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getopt(Drv, [], maxforkdepth).
 16

getpgrp(Drv, Pids)

-spec getpgrp(alcove_drv:ref(), [pid_t()]) -> pid_t().

getpgrp(2): retrieve the process group

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpgrp(Drv, []).
 3924

getpgrp(Drv, Pids, Timeout)

-spec getpgrp(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().

getpgrp(2): retrieve the process group

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpgrp(Drv, []).
 3924

getpid(Drv, Pids)

-spec getpid(alcove_drv:ref(), [pid_t()]) -> pid_t().

getpid(2): retrieve the system PID of the process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpid(Drv, []).
 3924

getpid(Drv, Pids, Timeout)

-spec getpid(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().

getpid(2): retrieve the system PID of the process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpid(Drv, []).
 3924

getpriority(Drv, Pids, Which, Who)

-spec getpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t()) ->
                     {ok, int32_t()} | {error, posix()}.

getpriority(2): retrieve scheduling priority of process, process group or user

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpriority(Drv, [], prio_process, 0).
 {ok,0}

getpriority(Drv, Pids, Which, Who, Timeout)

-spec getpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t(), timeout()) ->
                     {ok, int32_t()} | {error, posix()}.

getpriority(2): retrieve scheduling priority of process, process group or user

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getpriority(Drv, [], prio_process, 0).
 {ok,0}

getresgid(Drv, Pids)

-spec getresgid(alcove_drv:ref(), [pid_t()]) ->
                   {ok, Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()} | {error, posix()}.

getresgid(2): get real, effective and saved group ID

Support

* Linux

* OpenBSD

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getresgid(Drv, []).
 {ok,1000,1000,1000}

getresgid(Drv, Pids, Timeout)

-spec getresgid(alcove_drv:ref(), [pid_t()], timeout()) ->
                   {ok, Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()} | {error, posix()}.

getresgid(2): get real, effective and saved group ID

Support

* Linux

* OpenBSD

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getresgid(Drv, []).
 {ok,1000,1000,1000}

getresuid(Drv, Pids)

-spec getresuid(alcove_drv:ref(), [pid_t()]) ->
                   {ok, Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()} | {error, posix()}.

getresuid(2): get real, effective and saved user ID

Support

* Linux

* OpenBSD

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getresuid(Drv, []).
 {ok,1000,1000,1000}

getresuid(Drv, Pids, Timeout)

-spec getresuid(alcove_drv:ref(), [pid_t()], timeout()) ->
                   {ok, Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()} | {error, posix()}.

getresuid(2): get real, effective and saved user ID

Support

* Linux

* OpenBSD

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getresuid(Drv, []).
 {ok,1000,1000,1000}

getrlimit(Drv, Pids, Resource)

-spec getrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant()) ->
                   {ok, alcove_rlimit()} | {error, posix()}.

getrlimit(2): retrieve the resource limits for a process

Returns a record:

 -include_lib("alcove/include/alcove.hrl").

 #alcove_rlimit{
     cur = integer(),
     max = integer()
     }

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> alcove:getrlimit(Drv, [], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 1024,max = 1048576}}

getrlimit(Drv, Pids, Resource, Timeout)

-spec getrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), timeout()) ->
                   {ok, alcove_rlimit()} | {error, posix()}.

getrlimit(2): retrieve the resource limits for a process

Returns a record:

 -include_lib("alcove/include/alcove.hrl").

 #alcove_rlimit{
     cur = integer(),
     max = integer()
     }

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> alcove:getrlimit(Drv, [], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 1024,max = 1048576}}

getsid(Drv, Pids, OSPid)

-spec getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t()) -> {ok, pid_t()} | {error, posix()}.

getsid(2): retrieve the session ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getsid(Drv, [], 0).
 {ok,3924}

getsid(Drv, Pids, OSPid, Timeout)

-spec getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), timeout()) ->
                {ok, pid_t()} | {error, posix()}.

getsid(2): retrieve the session ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getsid(Drv, [], 0).
 {ok,3924}

getuid(Drv, Pids)

-spec getuid(alcove_drv:ref(), [pid_t()]) -> uid_t().

getuid(2): returns the process user ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getuid(Drv, []).
 1000

getuid(Drv, Pids, Timeout)

-spec getuid(alcove_drv:ref(), [pid_t()], timeout()) -> uid_t().

getuid(2): returns the process user ID

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:getuid(Drv, []).
 1000

ioctl(Drv, Pids, FD, Request, Argp)

-spec ioctl(alcove_drv:ref(), [pid_t()], FD :: fd(), Request :: constant(), Argp :: cstruct()) ->
               {ok, integer(), iodata()} | {error, posix()}.

ioctl(2): control device

Controls a device using a file descriptor previously obtained using open/5.

Argp can be either a binary or a list representation of a C struct. See prctl/7 below for a description of the list elements.

On success, ioctl/5 returns a 3-tuple:

* Result: an integer equal to the return value of the ioctl

Usually 0 but some ioctls may use the return value as the output parameter.

* Bin: the value depends on the type of the input parameter Argp

* cstruct: contains the contents of the memory pointed to by Argp

* integer/binary: an empty binary

Examples

An example of creating a tap device in a net namespace on Linux:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newnet]).
 {ok,8288}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/net/tun", [o_rdwr], 0).
 {ok,6}
 4> {ok, 0, <<"tap", _/binary>>} = alcove:ioctl(Drv, [Pid], FD, tunsetiff, <<
 4>                 % generate a tuntap device name
 4>                 0:(16 * 8),
 4>                 % IFF_TAP, IFF_NO_PI
 4>                 (16#0002 bor 16#1000):2/native-unsigned-integer-unit:8,
 4>                 0:(14 * 8)
 4>             >>).
 {ok,0,
     <<116,97,112,48,0,0,0,0,0,0,0,0,0,0,0,0,2,16,0,0,0,0,0,0,
       0,0,...>>}

ioctl(Drv, Pids, FD, Request, Argp, Timeout)

-spec ioctl(alcove_drv:ref(),
            [pid_t()],
            FD :: fd(),
            Request :: constant(),
            Argp :: cstruct(),
            timeout()) ->
               {ok, integer(), iodata()} | {error, posix()}.

ioctl(2): control device

Controls a device using a file descriptor previously obtained using open/5.

Argp can be either a binary or a list representation of a C struct. See prctl/7 below for a description of the list elements.

On success, ioctl/5 returns a 3-tuple:

* Result: an integer equal to the return value of the ioctl

Usually 0 but some ioctls may use the return value as the output parameter.

* Bin: the value depends on the type of the input parameter Argp

* cstruct: contains the contents of the memory pointed to by Argp

* integer/binary: an empty binary

Examples

An example of creating a tap device in a net namespace on Linux:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newnet]).
 {ok,8288}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/net/tun", [o_rdwr], 0).
 {ok,6}
 4> {ok, 0, <<"tap", _/binary>>} = alcove:ioctl(Drv, [Pid], FD, tunsetiff, <<
 4>                 % generate a tuntap device name
 4>                 0:(16 * 8),
 4>                 % IFF_TAP, IFF_NO_PI
 4>                 (16#0002 bor 16#1000):2/native-unsigned-integer-unit:8,
 4>                 0:(14 * 8)
 4>             >>).
 {ok,0,
     <<116,97,112,48,0,0,0,0,0,0,0,0,0,0,0,0,2,16,0,0,0,0,0,0,
       0,0,...>>}

ioctl_constant(Drv, Pids, Symbol)

-spec ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.

Convert ioctl constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:ioctl_constant(Drv, [], siocgifaddr).
 35093

ioctl_constant(Drv, Pids, Symbol, Timeout)

-spec ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.

Convert ioctl constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:ioctl_constant(Drv, [], siocgifaddr).
 35093

jail(Drv, Pids, Jail)

-spec jail(alcove_drv:ref(), [pid_t()], Jail :: cstruct()) -> {ok, int32_t()} | {error, posix()}.

jail(2): restrict the current process in a system jail

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> alcove:gethostname(Drv, [Pid]).
 {ok,<<"test0">>}

jail(Drv, Pids, Jail, Timeout)

-spec jail(alcove_drv:ref(), [pid_t()], Jail :: cstruct(), timeout()) ->
              {ok, int32_t()} | {error, posix()}.

jail(2): restrict the current process in a system jail

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> alcove:gethostname(Drv, [Pid]).
 {ok,<<"test0">>}

jail_attach(Drv, Pids, JID)

-spec jail_attach(alcove_drv:ref(), [pid_t()], JID :: int32_t()) -> ok | {error, posix()}.

jail_attach(2): join a jailed process

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> {ok, Pid0} = alcove:fork(Drv, []).
 {ok,44379}
 7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
 ok
 8> alcove:gethostname(Drv, [Pid0]).
 {ok,<<"test0">>}
 9> ok = alcove:jail_remove(Drv, [], JID0).
 ok

jail_attach(Drv, Pids, JID, Timeout)

-spec jail_attach(alcove_drv:ref(), [pid_t()], JID :: int32_t(), timeout()) -> ok | {error, posix()}.

jail_attach(2): join a jailed process

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> {ok, Pid0} = alcove:fork(Drv, []).
 {ok,44379}
 7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
 ok
 8> alcove:gethostname(Drv, [Pid0]).
 {ok,<<"test0">>}
 9> ok = alcove:jail_remove(Drv, [], JID0).
 ok

jail_remove(Drv, Pids, JID)

-spec jail_remove(alcove_drv:ref(), [pid_t()], JID :: int32_t()) -> ok | {error, posix()}.

jail_remove(2): destroy a jailed process

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> {ok, Pid0} = alcove:fork(Drv, []).
 {ok,44379}
 7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
 ok
 8> alcove:gethostname(Drv, [Pid0]).
 {ok,<<"test0">>}
 9> ok = alcove:jail_remove(Drv, [], JID0).
 ok

jail_remove(Drv, Pids, JID, Timeout)

-spec jail_remove(alcove_drv:ref(), [pid_t()], JID :: int32_t(), timeout()) -> ok | {error, posix()}.

jail_remove(2): destroy a jailed process

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 3> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 4> Jail0 = alcove_cstruct:jail(#alcove_jail{
 4>         path = "/rescue",
 4>         hostname = "test0",
 4>         jailname = "jail0"
 4>     }).
 [<<2,0,0,0>>,
  <<0,0,0,0>>,
  {ptr,<<47,114,101,115,99,117,101,0>>},
  {ptr,<<116,101,115,116,48,0>>},
  {ptr,<<106,97,105,108,48,0>>},
  <<0,0,0,0,0,0,0,0>>,
  {ptr,<<>>},
  {ptr,<<>>}]
 5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
 {ok,21}
 6> {ok, Pid0} = alcove:fork(Drv, []).
 {ok,44379}
 7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
 ok
 8> alcove:gethostname(Drv, [Pid0]).
 {ok,<<"test0">>}
 9> ok = alcove:jail_remove(Drv, [], JID0).
 ok

kill(Drv, Pids, OSPid, Signal)

-spec kill(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Signal :: constant()) -> ok | {error, posix()}.

kill(2): terminate a process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:kill(Drv, [], 0, 0).
 ok
 3> alcove:kill(Drv, [], 12345, 0).
 {error,esrch}
 4> {ok, Pid} = alcove:fork(Drv, []).
 {ok,8288}
 5> alcove:kill(Drv, [], Pid, 0).
 ok
 6> alcove:kill(Drv, [], Pid, sigkill).
 ok
 7> alcove:kill(Drv, [], Pid, 0).
 {error,esrch}
 8> flush().
 Shell got {alcove_ctl,<0.177.0>,[8288],fdctl_closed}
 Shell got {alcove_event,<0.177.0>,[8288],{termsig,sigkill}}

kill(Drv, Pids, OSPID, Signal, Timeout)

-spec kill(alcove_drv:ref(), [pid_t()], OSPID :: pid_t(), Signal :: constant(), timeout()) ->
              ok | {error, posix()}.

kill(2): terminate a process

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:kill(Drv, [], 0, 0).
 ok
 3> alcove:kill(Drv, [], 12345, 0).
 {error,esrch}
 4> {ok, Pid} = alcove:fork(Drv, []).
 {ok,8288}
 5> alcove:kill(Drv, [], Pid, 0).
 ok
 6> alcove:kill(Drv, [], Pid, sigkill).
 ok
 7> alcove:kill(Drv, [], Pid, 0).
 {error,esrch}
 8> flush().
 Shell got {alcove_ctl,<0.177.0>,[8288],fdctl_closed}
 Shell got {alcove_event,<0.177.0>,[8288],{termsig,sigkill}}

link(Drv, Pids, OldPath, NewPath)

-spec link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) ->
              ok | {error, posix()}.

link(2) : create a hard link

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/alcove-link-test.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:link(Drv, [Pid], "/tmp/alcove-link-test.txt", "/tmp/alcove-link-test.link").
 ok

link(Drv, Pids, OldPath, NewPath, Timeout)

-spec link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) ->
              ok | {error, posix()}.

link(2) : create a hard link

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/alcove-link-test.txt", [o_wronly, o_creat], 8#644).
 {ok,6}
 4> alcove:link(Drv, [Pid], "/tmp/alcove-link-test.txt", "/tmp/alcove-link-test.link").
 ok

lseek(Drv, Pids, FD, Offset, Whence)

-spec lseek(alcove_drv:ref(), [pid_t()], FD :: fd(), Offset :: off_t(), Whence :: int32_t()) ->
               ok | {error, posix()}.

lseek(2): set file offset for read/write

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:lseek(Drv, [Pid], FD, 0, 0).
 ok

lseek(Drv, Pids, FD, Offset, Whence, Timeout)

-spec lseek(alcove_drv:ref(), [pid_t()], FD :: fd(), Offset :: off_t(), Whence :: int32_t(), timeout()) ->
               ok | {error, posix()}.

lseek(2): set file offset for read/write

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,18820}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:lseek(Drv, [Pid], FD, 0, 0).
 ok

mkdir(Drv, Pids, Path, Mode)

-spec mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.

mkdir(2): create a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
 ok

mkdir(Drv, Pids, Path, Mode, Timeout)

-spec mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) ->
               ok | {error, posix()}.

mkdir(2): create a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
 ok

mkfifo(Drv, Pids, Path, Mode)

-spec mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.

mkfifo(3): make named pipe file

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
 ok

mkfifo(Drv, Pids, Path, Mode, Timeout)

-spec mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) ->
                ok | {error, posix()}.

mkfifo(3): make named pipe file

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
 ok

mount(Drv, Pids, Source, Target, FSType, Flags, Data, Options)

-spec mount(alcove_drv:ref(),
            [pid_t()],
            Source :: iodata(),
            Target :: iodata(),
            FSType :: iodata(),
            Flags :: uint64_t() | [constant()],
            Data :: iodata(),
            Options :: iodata()) ->
               ok | {error, posix()}.

mount(2): mount a filesystem, Linux style

The arguments are:

* source

* target

* filesystem type

* flags

* data

An empty list may be used to specify NULL.

For example, filesystems mounted in a Linux mount namespace may be visible in the global mount namespace. To avoid this, first remount the root filesystem within a mount namespace using the MS_REC|MS_PRIVATE flags:

 {ok, Task} = alcove:clone(Drv, [], [clone_newns]),
 ok = alcove:mount(Drv, [Task], "none", "/", [], [ms_rec, ms_private], []).

On BSD systems, the Source argument is ignored and passed to the system mount call as:

 mount(FSType, Target, Flags, Data);

On Solaris, some mount options are passed in the Options argument as a string of comma separated values terminated by a NULL. Other platforms ignore the Options parameter.

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount(Drv, [Pid], "/mnt").
 ok

mount(Drv, Pids, Source, Target, FSType, Flags, Data, Options, Timeout)

-spec mount(alcove_drv:ref(),
            [pid_t()],
            Source :: iodata(),
            Target :: iodata(),
            FSType :: iodata(),
            Flags :: uint64_t() | [constant()],
            Data :: iodata(),
            Options :: iodata(),
            timeout()) ->
               ok | {error, posix()}.

mount(2): mount a filesystem, Linux style

The arguments are:

* source

* target

* filesystem type

* flags

* data

An empty list may be used to specify NULL.

For example, filesystems mounted in a Linux mount namespace may be visible in the global mount namespace. To avoid this, first remount the root filesystem within a mount namespace using the MS_REC|MS_PRIVATE flags:

 {ok, Task} = alcove:clone(Drv, [], [clone_newns]),
 ok = alcove:mount(Drv, [Task], "none", "/", [], [ms_rec, ms_private], []).

On BSD systems, the Source argument is ignored and passed to the system mount call as:

 mount(FSType, Target, Flags, Data);

On Solaris, some mount options are passed in the Options argument as a string of comma separated values terminated by a NULL. Other platforms ignore the Options parameter.

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount(Drv, [Pid], "/mnt").
 ok

mount_constant(Drv, Pids, Symbol)

-spec mount_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | uint64_t().

Convert flag names to integers

Names are derived from the C macro name with the underscore prefix removed. For example, rdonly is mapped to MS_RDONLY on Linux and MNT_RDONLY on FreeBSD.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mount_constant(Drv, [], rdonly).
 1

mount_constant(Drv, Pids, Symbol, Timeout)

-spec mount_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | uint64_t().

Convert flag names to integers

Names are derived from the C macro name with the underscore prefix removed. For example, rdonly is mapped to MS_RDONLY on Linux and MNT_RDONLY on FreeBSD.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mount_constant(Drv, [], rdonly).
 1

open(Drv, Pids, Path, Flags, Mode)

-spec open(alcove_drv:ref(),
           [pid_t()],
           Path :: iodata(),
           Flags :: int32_t() | [constant()],
           Mode :: mode_t()) ->
              {ok, fd()} | {error, posix()}.

open(2): returns a file descriptor associated with a file

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
 {ok,6}

open(Drv, Pids, Path, Flags, Mode, Timeout)

-spec open(alcove_drv:ref(),
           [pid_t()],
           Path :: iodata(),
           Flags :: int32_t() | [constant()],
           Mode :: mode_t(),
           timeout()) ->
              {ok, fd()} | {error, posix()}.

open(2): returns a file descriptor associated with a file

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
 {ok,6}

pivot_root(Drv, Pids, NewRoot, PutOld)

-spec pivot_root(alcove_drv:ref(), [pid_t()], NewRoot :: iodata(), PutOld :: iodata()) ->
                    ok | {error, posix()}.

pivot_root(2): change the root mount

Use pivot_root(2) in a Linux mount namespace to change the root filesystem.

Warning: using pivot_root(2) in the global namespace may have unexpected effects.

To use an arbitrary directory as a mount point:

* mark the mount namespace as private

* create a mount point by bind mounting the new root directory over itself

* change the current working directory to the new root directory

* call pivot_root(2) with new and old root set to the current working directory

* unmount the current working directory

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.198.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-root", 8#755).
 ok
 3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,29739}
 4> alcove:mount(Drv, [Pid], "none", "/", [], [ms_rec, ms_private], [], []).
 ok
 5> alcove:mount(Drv, [Pid], "/tmp/alcove-root", "/tmp/alcove-root", [], [ms_bind], [], []).
 ok
 6> alcove:chdir(Drv, [Pid], "/tmp/alcove-root").
 ok
 7> alcove:pivot_root(Drv, [Pid], ".", ".").
 ok
 8> alcove:umount2(Drv, [Pid], ".", [mnt_detach]).
 ok

pivot_root(Drv, Pids, NewRoot, PutOld, Timeout)

-spec pivot_root(alcove_drv:ref(), [pid_t()], NewRoot :: iodata(), PutOld :: iodata(), timeout()) ->
                    ok | {error, posix()}.

pivot_root(2): change the root mount

Use pivot_root(2) in a Linux mount namespace to change the root filesystem.

Warning: using pivot_root(2) in the global namespace may have unexpected effects.

To use an arbitrary directory as a mount point:

* mark the mount namespace as private

* create a mount point by bind mounting the new root directory over itself

* change the current working directory to the new root directory

* call pivot_root(2) with new and old root set to the current working directory

* unmount the current working directory

Support

* Linux

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.198.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-root", 8#755).
 ok
 3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,29739}
 4> alcove:mount(Drv, [Pid], "none", "/", [], [ms_rec, ms_private], [], []).
 ok
 5> alcove:mount(Drv, [Pid], "/tmp/alcove-root", "/tmp/alcove-root", [], [ms_bind], [], []).
 ok
 6> alcove:chdir(Drv, [Pid], "/tmp/alcove-root").
 ok
 7> alcove:pivot_root(Drv, [Pid], ".", ".").
 ok
 8> alcove:umount2(Drv, [Pid], ".", [mnt_detach]).
 ok

pledge(Drv, Pids, Promises, ExecPromises)

-spec pledge(alcove_drv:ref(), [pid_t()], Promises :: iodata(), ExecPromises :: iodata()) ->
                ok | {error, posix()}.

pledge(2): restrict system operations

An empty list ([]) specifies promises should not be changed. Warning: an empty string ("") is equivalent to an empty list.

To specify no capabilities, use an empty binary: <<>>> or <<"">>

Support

* OpenBSD

Examples

Fork a control process:

* restricted to stdio, proc and exec capabilities

* unrestricted after calling exec

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,10059}
 3> alcove:pledge(Drv, [Pid], <<"stdio proc exec">>, []).
 ok

pledge(Drv, Pids, Promises, ExecPromises, Timeout)

-spec pledge(alcove_drv:ref(), [pid_t()], Promises :: iodata(), ExecPromises :: iodata(), timeout()) ->
                ok | {error, posix()}.

pledge(2): restrict system operations

An empty list ([]) specifies promises should not be changed. Warning: an empty string ("") is equivalent to an empty list.

To specify no capabilities, use an empty binary: <<>>> or <<"">>

Support

* OpenBSD

Examples

Fork a control process:

* restricted to stdio, proc and exec capabilities

* unrestricted after calling exec

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,10059}
 3> alcove:pledge(Drv, [Pid], <<"stdio proc exec">>, []).
 ok

prctl(Drv, Pids, Arg1, Arg2, Arg3, Arg4, Arg5)

-spec prctl(alcove_drv:ref(), [pid_t()], constant(), ptr_arg(), ptr_arg(), ptr_arg(), ptr_arg()) ->
               {ok, integer(), ptr_val(), ptr_val(), ptr_val(), ptr_val()} | {error, posix()}.

prctl(2): operations on a process

This function can be used to set BPF syscall filters on processes (seccomp mode).

A list can be used for prctl operations requiring a C structure as an argument. List elements are used to contiguously populate a buffer (it is up to the caller to add padding):

* binary(): the element is copied directly into the buffer

On return, the contents of the binary is returned to the caller.

* {ptr, N}: N bytes of memory is allocated and zeroed. The pointer is placed in the buffer.

On return, the contents of the memory is returned to the caller.

* {ptr, binary()}

Memory equal to the size of the binary is allocated and initialized with the contents of the binary.

On return, the contents of the memory is returned to the caller.

Support

* Linux

Examples

To enforce a seccomp filter:

 -module(seccomp).

 -include_lib("alcove/include/alcove_seccomp.hrl").

 -export([run/2, run/3, filter/3]).

 -define(DENY_SYSCALL(Syscall), [
     ?BPF_JUMP(?BPF_JMP + ?BPF_JEQ + ?BPF_K, (Syscall), 0, 1),
     ?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_KILL)
 ]).

 filter(Drv, Pid, Syscall) ->
     Arch = alcove:define(Drv, Pid, alcove:audit_arch()),
     NR = alcove:syscall_constant(Drv, Pid, syscall_constant, Syscall),

     [
         ?VALIDATE_ARCHITECTURE(Arch),
         ?EXAMINE_SYSCALL,
         ?DENY_SYSCALL(NR),
         ?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_ALLOW)
     ].

 run(Drv, Pid) ->
     run(Drv, Pid, sys_getcwd).

 run(Drv, Pid, Syscall) ->
     Filter = filter(Drv, Pid, Syscall),

     {ok, _, _, _, _, _} = alcove:prctl(Drv, Pid, pr_set_no_new_privs, 1, 0, 0, 0),
     Pad = (erlang:system_info({wordsize, external}) - 2) * 8,

     Prog = [
         <<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
         <<0:Pad>>,
         {ptr, list_to_binary(Filter)}
     ],
     %% alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog)
     alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).

See also: seccomp/5.

prctl(Drv, Pids, Arg1, Arg2, Arg3, Arg4, Arg5, Timeout)

-spec prctl(alcove_drv:ref(),
            [pid_t()],
            constant(),
            ptr_arg(),
            ptr_arg(),
            ptr_arg(),
            ptr_arg(),
            timeout()) ->
               {ok, integer(), ptr_val(), ptr_val(), ptr_val(), ptr_val()} | {error, posix()}.

prctl(2): operations on a process

This function can be used to set BPF syscall filters on processes (seccomp mode).

A list can be used for prctl operations requiring a C structure as an argument. List elements are used to contiguously populate a buffer (it is up to the caller to add padding):

* binary(): the element is copied directly into the buffer

On return, the contents of the binary is returned to the caller.

* {ptr, N}: N bytes of memory is allocated and zeroed. The pointer is placed in the buffer.

On return, the contents of the memory is returned to the caller.

* {ptr, binary()}

Memory equal to the size of the binary is allocated and initialized with the contents of the binary.

On return, the contents of the memory is returned to the caller.

Support

* Linux

Examples

To enforce a seccomp filter:

 -module(seccomp).

 -include_lib("alcove/include/alcove_seccomp.hrl").

 -export([run/2, run/3, filter/3]).

 -define(DENY_SYSCALL(Syscall), [
     ?BPF_JUMP(?BPF_JMP + ?BPF_JEQ + ?BPF_K, (Syscall), 0, 1),
     ?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_KILL)
 ]).

 filter(Drv, Pid, Syscall) ->
     Arch = alcove:define(Drv, Pid, alcove:audit_arch()),
     NR = alcove:syscall_constant(Drv, Pid, syscall_constant, Syscall),

     [
         ?VALIDATE_ARCHITECTURE(Arch),
         ?EXAMINE_SYSCALL,
         ?DENY_SYSCALL(NR),
         ?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_ALLOW)
     ].

 run(Drv, Pid) ->
     run(Drv, Pid, sys_getcwd).

 run(Drv, Pid, Syscall) ->
     Filter = filter(Drv, Pid, Syscall),

     {ok, _, _, _, _, _} = alcove:prctl(Drv, Pid, pr_set_no_new_privs, 1, 0, 0, 0),
     Pad = (erlang:system_info({wordsize, external}) - 2) * 8,

     Prog = [
         <<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
         <<0:Pad>>,
         {ptr, list_to_binary(Filter)}
     ],
     %% alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog)
     alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).

See also: seccomp/5.

prctl_constant(Drv, Pids, Symbol)

-spec prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().

Convert prctl option names to integers

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:prctl_constant(Drv, [], pr_set_name).
 15

prctl_constant(Drv, Pids, Symbol, Timeout)

-spec prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                        unknown | non_neg_integer().

Convert prctl option names to integers

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:prctl_constant(Drv, [], pr_set_name).
 15

procctl(Drv, Pids, IDType, ID, Cmd, Data)

-spec procctl(alcove_drv:ref(),
              [pid_t()],
              IDType :: constant(),
              ID :: pid_t(),
              Cmd :: constant(),
              Data :: [] | cstruct()) ->
                 {ok, binary(), cstruct()} | {error, posix()}.

procctl(2): control processes

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Pid, []).
 {ok,44378}
 3> alcove:procctl(Drv, [Pid], 0, Pid, proc_reap_acquire, []).
 {ok,<<>>,[]}
 4> alcove:procctl(Drv, [Pid], p_pid, Pid, proc_reap_status, [
 4>      <<0,0,0,0>>, % rs_flags
 4>      <<0,0,0,0>>, % rs_children
 4>      <<0,0,0,0>>, % rs_descendants
 4>      <<0,0,0,0>>, % rs_reaper
 4>      <<0,0,0,0>>  % rs_pid
 4>    ]).
 {ok,<<1,0,0,0,0,0,0,0,0,0,0,0,118,173,0,0,255,255,255,255>>,
     [<<1,0,0,0>>,
      <<0,0,0,0>>,
      <<0,0,0,0>>,
      <<118,173,0,0>>,
      <<"\377\377\377\377">>]}

procctl(Drv, Pids, IDType, ID, Cmd, Data, Timeout)

-spec procctl(alcove_drv:ref(),
              [pid_t()],
              IDType :: constant(),
              ID :: pid_t(),
              Cmd :: constant(),
              Data :: [] | cstruct(),
              timeout()) ->
                 {ok, binary(), cstruct()} | {error, posix()}.

procctl(2): control processes

Support

* FreeBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Pid, []).
 {ok,44378}
 3> alcove:procctl(Drv, [Pid], 0, Pid, proc_reap_acquire, []).
 {ok,<<>>,[]}
 4> alcove:procctl(Drv, [Pid], p_pid, Pid, proc_reap_status, [
 4>      <<0,0,0,0>>, % rs_flags
 4>      <<0,0,0,0>>, % rs_children
 4>      <<0,0,0,0>>, % rs_descendants
 4>      <<0,0,0,0>>, % rs_reaper
 4>      <<0,0,0,0>>  % rs_pid
 4>    ]).
 {ok,<<1,0,0,0,0,0,0,0,0,0,0,0,118,173,0,0,255,255,255,255>>,
     [<<1,0,0,0>>,
      <<0,0,0,0>>,
      <<0,0,0,0>>,
      <<118,173,0,0>>,
      <<"\377\377\377\377">>]}

ptrace(Drv, Pids, Request, OSPid, Addr, Data)

-spec ptrace(alcove_drv:ref(),
             [pid_t()],
             Request :: constant(),
             OSPid :: pid_t(),
             Addr :: ptr_arg(),
             Data :: ptr_arg()) ->
                {ok, integer(), ptr_val(), ptr_val()} | {error, posix()}.

ptrace(2): process trace

Examples

 -module(ptrace).

 -export([run/0]).

 run() ->
     {ok, Drv} = alcove_drv:start_link(),
     {ok, Pid1} = alcove:fork(Drv, []),

     {ok, Pid2} = alcove:fork(Drv, [Pid1]),

     % disable the alcove event loop: child process must be managed by
     % the caller
     {ok, sig_dfl} = alcove:sigaction(Drv, [Pid1], sigchld, sig_info),

     % enable ptracing in the child process and exec() a command
     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1, Pid2],
         ptrace_traceme,
         0,
         0,
         0
     ),
     ok = alcove:execvp(Drv, [Pid1, Pid2], "cat", ["cat"]),

     % the parent is notified
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, Pid2, _, [{stopsig, sigtrap}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         [wnohang]
     ),

     % should be no other events
     {ok, 0, 0, []} = alcove:waitpid(Drv, [Pid1], -1, [wnohang]),

     % allow the process to continue
     {ok, 0, <<>>, <<>>} = alcove:ptrace(Drv, [Pid1], ptrace_cont, Pid2, 0, 0),

     ok = alcove:stdin(Drv, [Pid1, Pid2], "test\n"),

     ok =
         receive
             {alcove_stdout, Drv, [Pid1, Pid2], <<"test\n">>} ->
                 ok
         after 5000 -> timeout
         end,

     % Send a SIGTERM and re-write it to a harmless SIGWINCH
     ok = alcove:kill(Drv, [Pid1], Pid2, sigterm),
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, Pid2, _, [{stopsig, sigterm}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         [wnohang]
     ),

     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1],
         ptrace_cont,
         Pid2,
         0,
         28
     ),

     % Convert a SIGWINCH to SIGTERM
     ok = alcove:kill(Drv, [Pid1], Pid2, sigwinch),
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1],
         ptrace_cont,
         Pid2,
         0,
         15
     ),
     {ok, Pid2, _, [{termsig, sigterm}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         []
     ).

ptrace(Drv, Pids, Request, OSPid, Addr, Data, Timeout)

-spec ptrace(alcove_drv:ref(),
             [pid_t()],
             Request :: constant(),
             OSPid :: pid_t(),
             Addr :: ptr_arg(),
             Data :: ptr_arg(),
             timeout()) ->
                {ok, integer(), ptr_val(), ptr_val()} | {error, posix()}.

ptrace(2): process trace

Examples

 -module(ptrace).

 -export([run/0]).

 run() ->
     {ok, Drv} = alcove_drv:start_link(),
     {ok, Pid1} = alcove:fork(Drv, []),

     {ok, Pid2} = alcove:fork(Drv, [Pid1]),

     % disable the alcove event loop: child process must be managed by
     % the caller
     {ok, sig_dfl} = alcove:sigaction(Drv, [Pid1], sigchld, sig_info),

     % enable ptracing in the child process and exec() a command
     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1, Pid2],
         ptrace_traceme,
         0,
         0,
         0
     ),
     ok = alcove:execvp(Drv, [Pid1, Pid2], "cat", ["cat"]),

     % the parent is notified
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, Pid2, _, [{stopsig, sigtrap}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         [wnohang]
     ),

     % should be no other events
     {ok, 0, 0, []} = alcove:waitpid(Drv, [Pid1], -1, [wnohang]),

     % allow the process to continue
     {ok, 0, <<>>, <<>>} = alcove:ptrace(Drv, [Pid1], ptrace_cont, Pid2, 0, 0),

     ok = alcove:stdin(Drv, [Pid1, Pid2], "test\n"),

     ok =
         receive
             {alcove_stdout, Drv, [Pid1, Pid2], <<"test\n">>} ->
                 ok
         after 5000 -> timeout
         end,

     % Send a SIGTERM and re-write it to a harmless SIGWINCH
     ok = alcove:kill(Drv, [Pid1], Pid2, sigterm),
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, Pid2, _, [{stopsig, sigterm}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         [wnohang]
     ),

     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1],
         ptrace_cont,
         Pid2,
         0,
         28
     ),

     % Convert a SIGWINCH to SIGTERM
     ok = alcove:kill(Drv, [Pid1], Pid2, sigwinch),
     {signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
     {ok, 0, <<>>, <<>>} = alcove:ptrace(
         Drv,
         [Pid1],
         ptrace_cont,
         Pid2,
         0,
         15
     ),
     {ok, Pid2, _, [{termsig, sigterm}]} = alcove:waitpid(
         Drv,
         [Pid1],
         -1,
         []
     ).

ptrace_constant(Drv, Pids, Symbol)

-spec ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | integer().

Convert ptrace constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
 0

ptrace_constant(Drv, Pids, Symbol, Timeout)

-spec ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | integer().

Convert ptrace constant to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
 0

read(Drv, Pids, FD, Count)

-spec read(alcove_drv:ref(), [pid_t()], FD :: fd(), Count :: size_t()) ->
              {ok, binary()} | {error, posix()}.

read(2): read bytes from a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:read(Drv, [Pid], FD, 64).
 {ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}

read(Drv, Pids, FD, Count, Timeout)

-spec read(alcove_drv:ref(), [pid_t()], FD :: fd(), Count :: size_t(), timeout()) ->
              {ok, binary()} | {error, posix()}.

read(2): read bytes from a file descriptor

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,75710}
 3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
 {ok,6}
 4> alcove:read(Drv, [Pid], FD, 64).
 {ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}

readdir(Drv, Pids, Path)

-spec readdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> {ok, [binary()]} | {error, posix()}.

readdir(3): retrieve list of objects in a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> alcove:readdir(Drv, [], "/dev/pts").
 {ok,[<<".">>,<<"..">>,<<"50">>,<<"49">>,<<"45">>,<<"48">>,
      <<"47">>,<<"46">>,<<"44">>,<<"43">>,<<"42">>,<<"41">>,
      <<"40">>,<<"39">>,<<"38">>,<<"37">>,<<"36">>,<<"35">>,
      <<"34">>,<<"33">>,<<"32">>,<<"31">>,<<"30">>,<<"29">>,
      <<"28">>,<<"27">>,<<...>>|...]}

readdir(Drv, Pids, Path, Timeout)

-spec readdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) ->
                 {ok, [binary()]} | {error, posix()}.

readdir(3): retrieve list of objects in a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.209.0>}
 2> alcove:readdir(Drv, [], "/dev/pts").
 {ok,[<<".">>,<<"..">>,<<"50">>,<<"49">>,<<"45">>,<<"48">>,
      <<"47">>,<<"46">>,<<"44">>,<<"43">>,<<"42">>,<<"41">>,
      <<"40">>,<<"39">>,<<"38">>,<<"37">>,<<"36">>,<<"35">>,
      <<"34">>,<<"33">>,<<"32">>,<<"31">>,<<"30">>,<<"29">>,
      <<"28">>,<<"27">>,<<...>>|...]}

rlimit_constant(Drv, Pids, Symbol)

-spec rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().

Convert an RLIMIT_* flag to an integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
 7

rlimit_constant(Drv, Pids, Symbol, Timeout)

-spec rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                         unknown | non_neg_integer().

Convert an RLIMIT_* flag to an integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
 7

rmdir(Drv, Pids, Path)

-spec rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.

rmdir(2): delete a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-rmdir-test", 8#755).
 ok
 3> alcove:rmdir(Drv, [], "/tmp/alcove-rmdir-test").
 ok

rmdir(Drv, Pids, Path, Timeout)

-spec rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.

rmdir(2): delete a directory

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:mkdir(Drv, [], "/tmp/alcove-rmdir-test", 8#755).
 ok
 3> alcove:rmdir(Drv, [], "/tmp/alcove-rmdir-test").
 ok

seccomp(Drv, Pids, Operation, Flags, Prog)

-spec seccomp(alcove_drv:ref(),
              [pid_t()],
              Operation :: constant(),
              Flags :: constant(),
              Prog :: cstruct()) ->
                 ok | {error, posix()}.

seccomp(2): restrict system operations

Support

* Linux

Examples

''' %% Equivalent to: %% alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0) alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog) '''

See also: prctl/7.

seccomp(Drv, Pids, Operation, Flags, Prog, Timeout)

-spec seccomp(alcove_drv:ref(),
              [pid_t()],
              Operation :: constant(),
              Flags :: constant(),
              Prog :: cstruct(),
              timeout()) ->
                 ok | {error, posix()}.

seccomp(2): restrict system operations

Support

* Linux

Examples

''' %% Equivalent to: %% alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0) alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog) '''

See also: prctl/7.

seccomp_constant(Drv, Pids, Symbol)

-spec seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().

Convert seccomp option name to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:seccomp_constant(Drv, [], seccomp_set_mode_strict).
 0

seccomp_constant(Drv, Pids, Symbol, Timeout)

-spec seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                          unknown | non_neg_integer().

Convert seccomp option name to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:seccomp_constant(Drv, [], seccomp_set_mode_strict).
 0

select(Drv, Pids, Readfds, Writefds, Exceptfds, Timeval)

-spec select(alcove_drv:ref(),
             [pid_t()],
             Readfds :: fd_set(),
             Writefds :: fd_set(),
             Exceptfds :: fd_set(),
             Timeval :: [] | alcove_timeval()) ->
                {ok, Readset :: fd_set(), Writeset :: fd_set(), Exceptset :: fd_set()} |
                {error, posix()}.

select(2): poll a list of file descriptor for events

select/6 will block until an event occurs on a file descriptor, a timeout is reached or interrupted by a signal.

The Timeout value may be:

* an empty list ([]): causes select to block indefinitely (no timeout)

* an alcove_timeval record

An alcove_timeval record contains these fields:

* sec : number of seconds to wait

* usec : number of microseconds to wait

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, FD} = alcove:open(Drv, [], "/dev/null", [o_rdwr], 0).
 {ok,6}
 3> alcove:select(Drv, [], [FD], [FD], [FD], []).
 {ok,[6],[6],[]}
 4> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 5> alcove:select(Drv, [], [FD], [FD], [FD], #alcove_timeval{sec = 1, usec = 1}).
 {ok,[6],[6],[]}

select(Drv, Pids, Readfds, Writefds, Exceptfds, Timeval, Timeout)

-spec select(alcove_drv:ref(),
             [pid_t()],
             Readfds :: fd_set(),
             Writefds :: fd_set(),
             Exceptfds :: fd_set(),
             Timeval :: [] | alcove_timeval(),
             timeout()) ->
                {ok, Readset :: fd_set(), Writeset :: fd_set(), Exceptset :: fd_set()} |
                {error, posix()}.

select(2): poll a list of file descriptor for events

select/6 will block until an event occurs on a file descriptor, a timeout is reached or interrupted by a signal.

The Timeout value may be:

* an empty list ([]): causes select to block indefinitely (no timeout)

* an alcove_timeval record

An alcove_timeval record contains these fields:

* sec : number of seconds to wait

* usec : number of microseconds to wait

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, FD} = alcove:open(Drv, [], "/dev/null", [o_rdwr], 0).
 {ok,6}
 3> alcove:select(Drv, [], [FD], [FD], [FD], []).
 {ok,[6],[6],[]}
 4> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 5> alcove:select(Drv, [], [FD], [FD], [FD], #alcove_timeval{sec = 1, usec = 1}).
 {ok,[6],[6],[]}

setcpid(Drv, Pids, Child, Opt, Val)

-spec setcpid(alcove_drv:ref(),
              [pid_t()],
              Child :: pid_t(),
              Opt :: alcove_pid_field(),
              Val :: int32_t()) ->
                 boolean().

Set options for child process of alcove control process

flowcontrol enables rate limiting of the stdout and stderr of a child process. stdin is not rate limited (default: -1 (disabled))

* 0: stdout/stderr for process is not read

* 1-2147483646: read this many messages from the process

* -1: disable flow control

NOTE: the limit applies to stdout and stderr. If the limit is set to 1, it is possible to get:

* 1 message from stdout

* 1 message from stderr

* 1 message from stdout and stderr

signaloneof delivers a signal to any subprocesses when the alcove control process shuts down (default: 15 (SIGTERM))

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,24440}
 3> alcove:setcpid(Drv, [], Pid, flowcontrol, 0).
 true
 4> alcove:getcpid(Drv, [], Pid, flowcontrol).
 0

setcpid(Drv, Pids, Child, Opt, Val, Timeout)

-spec setcpid(alcove_drv:ref(),
              [pid_t()],
              Child :: pid_t(),
              Opt :: alcove_pid_field(),
              Val :: int32_t(),
              timeout()) ->
                 boolean().

Set options for child process of alcove control process

flowcontrol enables rate limiting of the stdout and stderr of a child process. stdin is not rate limited (default: -1 (disabled))

* 0: stdout/stderr for process is not read

* 1-2147483646: read this many messages from the process

* -1: disable flow control

NOTE: the limit applies to stdout and stderr. If the limit is set to 1, it is possible to get:

* 1 message from stdout

* 1 message from stderr

* 1 message from stdout and stderr

signaloneof delivers a signal to any subprocesses when the alcove control process shuts down (default: 15 (SIGTERM))

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,24440}
 3> alcove:setcpid(Drv, [], Pid, flowcontrol, 0).
 true
 4> alcove:getcpid(Drv, [], Pid, flowcontrol).
 0

setenv(Drv, Pids, Name, Value, Overwrite)

-spec setenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), Value :: iodata(), Overwrite :: int32_t()) ->
                ok | {error, posix()}.

setenv(3): set an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
 ok
 3> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 4> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 0).
 ok
 5> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 6> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 1).
 ok
 7> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"bar">>

setenv(Drv, Pids, Name, Value, Overwrite, Timeout)

-spec setenv(alcove_drv:ref(),
             [pid_t()],
             Name :: iodata(),
             Value :: iodata(),
             Overwrite :: int32_t(),
             timeout()) ->
                ok | {error, posix()}.

setenv(3): set an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
 ok
 3> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 4> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 0).
 ok
 5> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 6> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 1).
 ok
 7> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"bar">>

setgid(Drv, Pids, Gid)

-spec setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t()) -> ok | {error, posix()}.

setgid(2): set the GID of the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 72> alcove:setgid(Drv, [Pid], 123).
 ok
 73> alcove:getgid(Drv, [Pid]).
 123

setgid(Drv, Pids, Gid, Timeout)

-spec setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t(), timeout()) -> ok | {error, posix()}.

setgid(2): set the GID of the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 72> alcove:setgid(Drv, [Pid], 123).
 ok
 73> alcove:getgid(Drv, [Pid]).
 123

setgroups(Drv, Pids, Groups)

-spec setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()]) -> ok | {error, posix()}.

setgroups(2): set the supplementary groups of the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 75> alcove:setgroups(Drv, [Pid], []).
 ok
 76> alcove:getgroups(Drv, [Pid]).
 {ok,[]}

setgroups(Drv, Pids, Groups, Timeout)

-spec setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()], timeout()) -> ok | {error, posix()}.

setgroups(2): set the supplementary groups of the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 75> alcove:setgroups(Drv, [Pid], []).
 ok
 76> alcove:getgroups(Drv, [Pid]).
 {ok,[]}

sethostname(Drv, Pids, Hostname)

-spec sethostname(alcove_drv:ref(), [pid_t()], Hostname :: iodata()) -> ok | {error, posix()}.

sethostname(2): set the system hostname

This function is probably only useful if running in a uts namespace or a jail.

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newuts]).
 {ok,44378}
 3> alcove:sethostname(Drv, [Pid], "test").
 ok
 4> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}
 5> alcove:gethostname(Drv, [Pid]).
 {ok,<<"test">>}

sethostname(Drv, Pids, Hostname, Timeout)

-spec sethostname(alcove_drv:ref(), [pid_t()], Hostname :: iodata(), timeout()) -> ok | {error, posix()}.

sethostname(2): set the system hostname

This function is probably only useful if running in a uts namespace or a jail.

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newuts]).
 {ok,44378}
 3> alcove:sethostname(Drv, [Pid], "test").
 ok
 4> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}
 5> alcove:gethostname(Drv, [Pid]).
 {ok,<<"test">>}

setns(Drv, Pids, FD, NSType)

-spec setns(alcove_drv:ref(), [pid_t()], FD :: fd(), NSType :: constant()) -> ok | {error, posix()}.

setns(2): attach to a namespace

A process namespace is represented as a path in the /proc filesystem. The path is /proc/<pid>/ns/<ns>, where:

* pid: the system PID

* ns: a file representing the namespace

The available namespaces is dependent on the kernel version. You can see which are supported by running:

 ls -al /proc/$$/ns

Support

* Linux

Examples

Attach a process to an existing network namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid1} = alcove:clone(Drv, [], [clone_newnet]).
 {ok,27125}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,27126}
 % Move Pid2 into the Pid1 network namespace
 4> {ok, FD} = alcove:open(Drv, [Pid2], ["/proc/", integer_to_list(Pid1), "/ns/net"], [o_rdonly], 0).
 {ok,8}
 5> alcove:setns(Drv, [Pid2], FD, 0).
 ok
 6> alcove:close(Drv, [Pid2], FD).

setns(Drv, Pids, FD, NSType, Timeout)

-spec setns(alcove_drv:ref(), [pid_t()], FD :: fd(), NSType :: constant(), timeout()) ->
               ok | {error, posix()}.

setns(2): attach to a namespace

A process namespace is represented as a path in the /proc filesystem. The path is /proc/<pid>/ns/<ns>, where:

* pid: the system PID

* ns: a file representing the namespace

The available namespaces is dependent on the kernel version. You can see which are supported by running:

 ls -al /proc/$$/ns

Support

* Linux

Examples

Attach a process to an existing network namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid1} = alcove:clone(Drv, [], [clone_newnet]).
 {ok,27125}
 3> {ok, Pid2} = alcove:fork(Drv, []).
 {ok,27126}
 % Move Pid2 into the Pid1 network namespace
 4> {ok, FD} = alcove:open(Drv, [Pid2], ["/proc/", integer_to_list(Pid1), "/ns/net"], [o_rdonly], 0).
 {ok,8}
 5> alcove:setns(Drv, [Pid2], FD, 0).
 ok
 6> alcove:close(Drv, [Pid2], FD).

setopt(Drv, Pids, Opt, Val)

-spec setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t()) -> boolean().

Set port options

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setopt(Drv, [], maxforkdepth, 128).
 true

See also: getopt/3.

setopt(Drv, Pids, Opt, Val, Timeout)

-spec setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t(), timeout()) -> boolean().

Set port options

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setopt(Drv, [], maxforkdepth, 128).
 true

See also: getopt/3.

setpgid(Drv, Pids, OSPid, Pgid)

-spec setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t()) -> ok | {error, posix()}.

setpgid(2): set process group

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setpgid(Drv, [Pid], 0, 0).
 ok

setpgid(Drv, Pids, OSPid, Pgid, Timeout)

-spec setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t(), timeout()) ->
                 ok | {error, posix()}.

setpgid(2): set process group

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setpgid(Drv, [Pid], 0, 0).
 ok

setpriority(Drv, Pids, Which, Who, Prio)

-spec setpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t(), Prio :: int32_t()) ->
                     ok | {error, posix()}.

setpriority(2): set scheduling priority of process, process group or user

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setpriority(Drv, [Pid], prio_process, 0, 10).
 ok
 4> alcove:getpriority(Drv, [Pid], prio_process, 0).
 {ok,10}

setpriority(Drv, Pids, Which, Who, Prio, Timeout)

-spec setpriority(alcove_drv:ref(),
                  [pid_t()],
                  Which :: constant(),
                  Who :: int32_t(),
                  Prio :: int32_t(),
                  timeout()) ->
                     ok | {error, posix()}.

setpriority(2): set scheduling priority of process, process group or user

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setpriority(Drv, [Pid], prio_process, 0, 10).
 ok
 4> alcove:getpriority(Drv, [Pid], prio_process, 0).
 {ok,10}

setproctitle(Drv, Pids, Title)

-spec setproctitle(alcove_drv:ref(), [pid_t()], Title :: iodata()) -> ok.

setproctitle(3): set the process title

Overwrites arg0.

On Linux, prctl/6,7 can be used to set the command name:

 {ok,Fork} = alcove:fork(Drv, []),
 alcove:prctl(Drv, [Fork], pr_set_name, <<"pseudonym">>, 0,0,0).

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setproctitle(Drv, [Pid], "new process name").
 ok

setproctitle(Drv, Pids, Title, Timeout)

-spec setproctitle(alcove_drv:ref(), [pid_t()], Title :: iodata(), timeout()) -> ok.

setproctitle(3): set the process title

Overwrites arg0.

On Linux, prctl/6,7 can be used to set the command name:

 {ok,Fork} = alcove:fork(Drv, []),
 alcove:prctl(Drv, [Fork], pr_set_name, <<"pseudonym">>, 0,0,0).

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28210}
 3> alcove:setproctitle(Drv, [Pid], "new process name").
 ok

setresgid(Drv, Pids, Real, Effective, Saved)

-spec setresgid(alcove_drv:ref(), [pid_t()], Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()) ->
                   ok | {error, posix()}.

setresgid(2): set real, effective and saved group ID

Support

* Linux

* FreeBSD

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setresgid(Drv, [Pid], 123, 123, 123).
 ok

setresgid(Drv, Pids, Real, Effective, Saved, Timeout)

-spec setresgid(alcove_drv:ref(),
                [pid_t()],
                Real :: gid_t(),
                Effective :: gid_t(),
                Saved :: gid_t(),
                timeout()) ->
                   ok | {error, posix()}.

setresgid(2): set real, effective and saved group ID

Support

* Linux

* FreeBSD

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setresgid(Drv, [Pid], 123, 123, 123).
 ok

setresuid(Drv, Pids, Real, Effective, Saved)

-spec setresuid(alcove_drv:ref(), [pid_t()], Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()) ->
                   ok | {error, posix()}.

setresuid(2): set real, effective and saved user ID

Support

* Linux

* FreeBSD

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setresuid(Drv, [Pid], 123, 123, 123).
 ok

setresuid(Drv, Pids, Real, Effective, Saved, Timeout)

-spec setresuid(alcove_drv:ref(),
                [pid_t()],
                Real :: uid_t(),
                Effective :: uid_t(),
                Saved :: uid_t(),
                timeout()) ->
                   ok | {error, posix()}.

setresuid(2): set real, effective and saved user ID

Support

* Linux

* FreeBSD

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setresuid(Drv, [Pid], 123, 123, 123).
 ok

setrlimit(Drv, Pids, Resource, Limit)

-spec setrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), Limit :: alcove_rlimit()) ->
                   ok | {error, posix()}.

setrlimit(2): set a resource limit

Note on rlimit_nofile:

The control process requires a fixed number of file descriptors for each subprocess. Reducing the number of file descriptors will reduce the limit on child processes.

If the file descriptor limit is below the number of file descriptors currently used, setrlimit/4,5 will return {error, einval}.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 4> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 1024,max = 1048576}}
 5> alcove:setrlimit(Drv, [Pid], rlimit_nofile, #alcove_rlimit{cur = 64, max = 64}).
 ok
 6> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 64,max = 64}}

setrlimit(Drv, Pids, Resource, Limit, Timeout)

-spec setrlimit(alcove_drv:ref(),
                [pid_t()],
                Resource :: constant(),
                Limit :: alcove_rlimit(),
                timeout()) ->
                   ok | {error, posix()}.

setrlimit(2): set a resource limit

Note on rlimit_nofile:

The control process requires a fixed number of file descriptors for each subprocess. Reducing the number of file descriptors will reduce the limit on child processes.

If the file descriptor limit is below the number of file descriptors currently used, setrlimit/4,5 will return {error, einval}.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 4> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 1024,max = 1048576}}
 5> alcove:setrlimit(Drv, [Pid], rlimit_nofile, #alcove_rlimit{cur = 64, max = 64}).
 ok
 6> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
 {ok,#alcove_rlimit{cur = 64,max = 64}}

setsid(Drv, Pids)

-spec setsid(alcove_drv:ref(), [pid_t()]) -> {ok, OSPid :: pid_t()} | {error, posix()}.

setsid(2): create a new session

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setsid(Drv, [Pid]).
 {ok,28493}

setsid(Drv, Pids, Timeout)

-spec setsid(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, OSPid :: pid_t()} | {error, posix()}.

setsid(2): create a new session

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:setsid(Drv, [Pid]).
 {ok,28493}

setuid(Drv, Pids, User)

-spec setuid(alcove_drv:ref(), [pid_t()], User :: uid_t()) -> ok | {error, posix()}.

setuid(2): change UID

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 72> alcove:setuid(Drv, [Pid], 123).
 ok
 73> alcove:getuid(Drv, [Pid]).
 123

See also: setresuid/5.

setuid(Drv, Pids, User, Timeout)

-spec setuid(alcove_drv:ref(), [pid_t()], User :: uid_t(), timeout()) -> ok | {error, posix()}.

setuid(2): change UID

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.208.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,44378}
 72> alcove:setuid(Drv, [Pid], 123).
 ok
 73> alcove:getuid(Drv, [Pid]).
 123

See also: setresuid/5.

sigaction(Drv, Pids, Signum, Handler)

-spec sigaction(alcove_drv:ref(), [pid_t()], Signum :: constant(), Handler :: [] | atom()) ->
                   {ok, OldHandler :: atom()} | {error, posix()}.

sigaction(2): set process behaviour for signals

* sig_dfl

Uses the default behaviour for the signal

* sig_ign

Ignores the signal

* sig_info

Catches the signal and sends the controlling Erlang process an event:

 {signal, atom(), Info}

Info is a binary containing the siginfo_t structure. See sigaction(2) for details.

* []

Returns the current handler for the signal.

Multiple caught signals of the same type may be reported as one event.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 4> alcove:kill(Drv, [], Pid, sigterm).
 ok
 5> flush().
 Shell got {alcove_event,<0.177.0>,
                         [28493],
                         {signal,sigterm,
                                 <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0>>}}
 ok
 6> alcove:sigaction(Drv, [Pid], sigterm, sig_ign).
 {ok,sig_info}
 7> alcove:kill(Drv, [], Pid, sigterm).
 ok
 8> flush().
 ok
 9> alcove:sigaction(Drv, [Pid], sigterm, sig_info).
 {ok,sig_ign}
 10> alcove:kill(Drv, [], Pid, sigterm).
 ok
 11> flush().
 Shell got {alcove_event,<0.177.0>,
                         [28493],
                         {signal,sigterm,
                                 <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0>>}}
 ok

sigaction(Drv, Pids, Signum, Handler, Timeout)

-spec sigaction(alcove_drv:ref(), [pid_t()], Signum :: constant(), Handler :: [] | atom(), timeout()) ->
                   {ok, OldHandler :: atom()} | {error, posix()}.

sigaction(2): set process behaviour for signals

* sig_dfl

Uses the default behaviour for the signal

* sig_ign

Ignores the signal

* sig_info

Catches the signal and sends the controlling Erlang process an event:

 {signal, atom(), Info}

Info is a binary containing the siginfo_t structure. See sigaction(2) for details.

* []

Returns the current handler for the signal.

Multiple caught signals of the same type may be reported as one event.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> rr(alcove).
 [alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
 3> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 4> alcove:kill(Drv, [], Pid, sigterm).
 ok
 5> flush().
 Shell got {alcove_event,<0.177.0>,
                         [28493],
                         {signal,sigterm,
                                 <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0>>}}
 ok
 6> alcove:sigaction(Drv, [Pid], sigterm, sig_ign).
 {ok,sig_info}
 7> alcove:kill(Drv, [], Pid, sigterm).
 ok
 8> flush().
 ok
 9> alcove:sigaction(Drv, [Pid], sigterm, sig_info).
 {ok,sig_ign}
 10> alcove:kill(Drv, [], Pid, sigterm).
 ok
 11> flush().
 Shell got {alcove_event,<0.177.0>,
                         [28493],
                         {signal,sigterm,
                                 <<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                   0,0,0,0>>}}
 ok

signal_constant(Drv, Pids, Symbol)

-spec signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().

Convert signal names to integers

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:signal_constant(Drv, [], sighup).
 1

signal_constant(Drv, Pids, Symbol, Timeout)

-spec signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                         unknown | non_neg_integer().

Convert signal names to integers

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:signal_constant(Drv, [], sighup).
 1

socket(Drv, Pids, Domain, Type, Protocol)

-spec socket(alcove_drv:ref(),
             [pid_t()],
             Domain :: constant(),
             Type :: constant(),
             Protocol :: int32_t()) ->
                {ok, fd()} | {error, posix()}.

socket(2): returns a file descriptor for a communication endpoint

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Socket} = alcove:socket(Drv, [], af_inet, sock_stream, 0).
 {ok,6}
 3> alcove:close(Drv, [], Socket).
 ok

socket(Drv, Pids, Domain, Type, Protocol, Timeout)

-spec socket(alcove_drv:ref(),
             [pid_t()],
             Domain :: constant(),
             Type :: constant(),
             Protocol :: int32_t(),
             timeout()) ->
                {ok, fd()} | {error, posix()}.

socket(2): returns a file descriptor for a communication endpoint

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Socket} = alcove:socket(Drv, [], af_inet, sock_stream, 0).
 {ok,6}
 3> alcove:close(Drv, [], Socket).
 ok

stderr(Drv, Pids)

-spec stderr(alcove_drv:ref(), [pid_t()]) -> [binary()].

Read stderr from the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat", "/nonexistent"]).
 ok
 4> alcove:stderr(Drv, [Pid]).
 [<<"cat: /nonexistent: No such file or directoryn">>]

stderr(Drv, Pids, Timeout)

-spec stderr(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].

stdin(Drv, Pids, Data)

-spec stdin(alcove_drv:ref(), [pid_t()], iodata()) -> ok.

Send data to stdin of the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:stdin(Drv, [Pid], "testn").
 ok
 5> alcove:stdout(Drv, [Pid]).
 [<<"testn">>]

stdout(Drv, Pids)

-spec stdout(alcove_drv:ref(), [pid_t()]) -> [binary()].

Read stdout from the process

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
 ok
 4> alcove:stdin(Drv, [Pid], "testn").
 ok
 5> alcove:stdout(Drv, [Pid]).
 [<<"testn">>]

stdout(Drv, Pids, Timeout)

-spec stdout(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].

symlink(Drv, Pids, OldPath, NewPath)

-spec symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) ->
                 ok | {error, posix()}.

symlink(2): create a symbolic link

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
 ok

symlink(Drv, Pids, OldPath, NewPath, Timeout)

-spec symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) ->
                 ok | {error, posix()}.

symlink(2): create a symbolic link

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
 ok

syscall_constant(Drv, Pids, Symbol)

-spec syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().

Convert syscall name to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:syscall_constant(Drv, [], sys_exit).
 60

syscall_constant(Drv, Pids, Symbol, Timeout)

-spec syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) ->
                          unknown | non_neg_integer().

Convert syscall name to integer

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:syscall_constant(Drv, [], sys_exit).
 60

umount2(Drv, Pids, Path, Flags)

-spec umount2(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()]) ->
                 ok | {error, posix()}.

umount2(2): unmount filesystem with flags

Support

* Linux

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount2(Drv, [Pid], "/mnt", [mnt_detach]).
 ok

umount2(Drv, Pids, Path, Flags, Timeout)

-spec umount2(alcove_drv:ref(),
              [pid_t()],
              Path :: iodata(),
              Flags :: int32_t() | [constant()],
              timeout()) ->
                 ok | {error, posix()}.

umount2(2): unmount filesystem with flags

Support

* Linux

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount2(Drv, [Pid], "/mnt", [mnt_detach]).
 ok

umount(Drv, Pids, Path)

-spec umount(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.

umount(2): unmount a filesystem

On BSD systems, calls unmount(2).

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount(Drv, [Pid], "/mnt").
 ok

umount(Drv, Pids, Path, Timeout)

-spec umount(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.

umount(2): unmount a filesystem

On BSD systems, calls unmount(2).

Examples

An example of bind mounting a directory within a linux mount namespace:

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
 {ok,10059}
 3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
 ok
 4> alcove:umount(Drv, [Pid], "/mnt").
 ok

unlink(Drv, Pids, Path)

-spec unlink(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.

unlink(2): delete a name from the filesystem

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
 {ok,6}
 3> alcove:unlink(Drv, [], "/tmp/alcove-open-test").
 ok

unlink(Drv, Pids, Path, Timeout)

-spec unlink(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.

unlink(2): delete a name from the filesystem

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
 {ok,6}
 3> alcove:unlink(Drv, [], "/tmp/alcove-open-test").
 ok

unsetenv(Drv, Pids, Name)

-spec unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> ok | {error, posix()}.

unsetenv(3): remove an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
 ok
 3> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 4> alcove:unsetenv(Drv, [], "ALCOVE_TEST").
 ok
 5> alcove:getenv(Drv, [], "ALCOVE_TEST").
 false

unsetenv(Drv, Pids, Name, Timeout)

-spec unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> ok | {error, posix()}.

unsetenv(3): remove an environment variable

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
 ok
 3> alcove:getenv(Drv, [], "ALCOVE_TEST").
 <<"foo">>
 4> alcove:unsetenv(Drv, [], "ALCOVE_TEST").
 ok
 5> alcove:getenv(Drv, [], "ALCOVE_TEST").
 false

unshare(Drv, Pids, Flags)

-spec unshare(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()]) -> ok | {error, posix()}.

unshare(2): create a new namespace in the current process

Make a new namespace without calling clone(2):

 ok = alcove:unshare(Drv, [], [clone_newnet]).
 % The port is now running in a namespace without network access.

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:unshare(Drv, [Pid], [clone_newuts]).
 ok
 4> alcove:sethostname(Drv, [Pid], "unshare").
 ok
 5> alcove:gethostname(Drv, [Pid]).
 {ok,<<"unshare">>}
 6> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}

unshare(Drv, Pids, Flags, Timeout)

-spec unshare(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()], timeout()) ->
                 ok | {error, posix()}.

unshare(2): create a new namespace in the current process

Make a new namespace without calling clone(2):

 ok = alcove:unshare(Drv, [], [clone_newnet]).
 % The port is now running in a namespace without network access.

Examples

 1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28493}
 3> alcove:unshare(Drv, [Pid], [clone_newuts]).
 ok
 4> alcove:sethostname(Drv, [Pid], "unshare").
 ok
 5> alcove:gethostname(Drv, [Pid]).
 {ok,<<"unshare">>}
 6> alcove:gethostname(Drv, []).
 {ok,<<"host1">>}

unveil(Drv, Pids, Path, Permissions)

-spec unveil(alcove_drv:ref(), [pid_t()], Path :: iodata(), Permissions :: iodata()) ->
                ok | {error, posix()}.

unveil(2): restrict filesystem view

To disable unveil calls, use an empty list ([]) or, equivalently, an empty string ("").

 alcove:unveil(Drv, [Task], <<"/etc">>, <<"r">>),
 alcove:unveil(Drv, [Task], [], []).

Support

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28978}
 3> alcove:unveil(Drv, [Pid], <<"/etc">>, <<"r">>).
 ok
 4> alcove:unveil(Drv, [Pid], [], []).
 ok
 5> alcove:readdir(Drv, [Pid], "/etc").
 {ok,[<<".">>,<<"..">>,<<"acme">>,<<"amd">>,<<"authpf">>,
      <<"daily">>,<<"disktab">>,<<"examples">>,<<"firmware">>,
      <<"hotplug">>,<<"iked">>,<<"isakmpd">>,<<"ldap">>,
      <<"magic">>,<<"mail">>,<<"moduli">>,<<"monthly">>,
      <<"mtree">>,<<"netstart">>,<<"npppd">>,<<"pf.os">>,
      <<"ppp">>,<<"protocols">>,<<"rc">>,<<"rc.conf">>,<<"rc.d">>,
      <<...>>|...]}
 6> alcove:readdir(Drv, [Pid], "/tmp").
 {error,enoent}

unveil(Drv, Pids, Path, Permissions, Timeout)

-spec unveil(alcove_drv:ref(), [pid_t()], Path :: iodata(), Permissions :: iodata(), timeout()) ->
                ok | {error, posix()}.

unveil(2): restrict filesystem view

To disable unveil calls, use an empty list ([]) or, equivalently, an empty string ("").

 alcove:unveil(Drv, [Task], <<"/etc">>, <<"r">>),
 alcove:unveil(Drv, [Task], [], []).

Support

* OpenBSD

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28978}
 3> alcove:unveil(Drv, [Pid], <<"/etc">>, <<"r">>).
 ok
 4> alcove:unveil(Drv, [Pid], [], []).
 ok
 5> alcove:readdir(Drv, [Pid], "/etc").
 {ok,[<<".">>,<<"..">>,<<"acme">>,<<"amd">>,<<"authpf">>,
      <<"daily">>,<<"disktab">>,<<"examples">>,<<"firmware">>,
      <<"hotplug">>,<<"iked">>,<<"isakmpd">>,<<"ldap">>,
      <<"magic">>,<<"mail">>,<<"moduli">>,<<"monthly">>,
      <<"mtree">>,<<"netstart">>,<<"npppd">>,<<"pf.os">>,
      <<"ppp">>,<<"protocols">>,<<"rc">>,<<"rc.conf">>,<<"rc.d">>,
      <<...>>|...]}
 6> alcove:readdir(Drv, [Pid], "/tmp").
 {error,enoent}

version(Drv, Pids)

-spec version(alcove_drv:ref(), [pid_t()]) -> binary().

Retrieve the alcove version

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:version(Drv, []).
 <<"0.37.0">>

version(Drv, Pids, Timeout)

-spec version(alcove_drv:ref(), [pid_t()], timeout()) -> binary().

Retrieve the alcove version

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> alcove:version(Drv, []).
 <<"0.37.0">>

waitpid(Drv, Pids, OSPid, Options)

-spec waitpid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Options :: int32_t() | [constant()]) ->
                 {ok, pid_t(), WaitStatus :: [waitstatus()]} | {error, posix()}.

waitpid(2): wait for process to change state

Process state changes are handled by the alcove SIGCHLD event handler by default. To use waitpid/4,5, disable the signal handler:

 alcove:sigaction(Drv, [Pid], sigchld, sig_info)

Note: if the default SIGCHLD handler is disabled, waitpid/4,5 should be called to reap zombie processes:

 alcove:waitpid(Drv, [], -1, [wnohang])

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28978}
 3> alcove:sigaction(Drv, [Pid], sigchld, sig_info).
 {ok,sig_dfl}
 4> alcove:execvp(Drv, [Pid], "sleep", ["sleep", "20"]).
 ok
 5> alcove:waitpid(Drv, [], -1, []).
 {ok,28978,0,[{exit_status,0}]}

waitpid(Drv, Pids, OSPid, Options, Timeout)

-spec waitpid(alcove_drv:ref(),
              [pid_t()],
              OSPid :: pid_t(),
              Options :: int32_t() | [constant()],
              timeout()) ->
                 {ok, pid_t(), WaitStatus :: [waitstatus()]} | {error, posix()}.

waitpid(2): wait for process to change state

Process state changes are handled by the alcove SIGCHLD event handler by default. To use waitpid/4,5, disable the signal handler:

 alcove:sigaction(Drv, [Pid], sigchld, sig_info)

Note: if the default SIGCHLD handler is disabled, waitpid/4,5 should be called to reap zombie processes:

 alcove:waitpid(Drv, [], -1, [wnohang])

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, Pid} = alcove:fork(Drv, []).
 {ok,28978}
 3> alcove:sigaction(Drv, [Pid], sigchld, sig_info).
 {ok,sig_dfl}
 4> alcove:execvp(Drv, [Pid], "sleep", ["sleep", "20"]).
 ok
 5> alcove:waitpid(Drv, [], -1, []).
 {ok,28978,0,[{exit_status,0}]}

write(Drv, Pids, FD, Buf)

-spec write(alcove_drv:ref(), [pid_t()], FD :: fd(), Buf :: iodata()) ->
               {ok, Count :: ssize_t()} | {error, posix()}.

write(2): write to a file descriptor

Writes a buffer to a file descriptor and returns the number of bytes written.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, FD} = alcove:open(Drv, [], "/tmp/alcove-write-test", [o_wronly,o_creat], 8#644).
 {ok,6}
 3> alcove:write(Drv, [], FD, <<"test">>).
 {ok,4}

write(Drv, Pids, FD, Buf, Timeout)

-spec write(alcove_drv:ref(), [pid_t()], FD :: fd(), Buf :: iodata(), timeout()) ->
               {ok, Count :: ssize_t()} | {error, posix()}.

write(2): write to a file descriptor

Writes a buffer to a file descriptor and returns the number of bytes written.

Examples

 1> {ok, Drv} = alcove_drv:start().
 {ok,<0.177.0>}
 2> {ok, FD} = alcove:open(Drv, [], "/tmp/alcove-write-test", [o_wronly,o_creat], 8#644).
 {ok,6}
 3> alcove:write(Drv, [], FD, <<"test">>).
 {ok,4}