Copyright © 2015-2018 Michael Santos <michael.santos@gmail.com>
Behaviours: gen_statem.
constant() = atom() | integer()
cpid() = #{pid := pid_t(), flowcontrol := uint32_t(), signaloneof := uint32_t(), exec := boolean(), fdctl := fd(), stdin := fd(), stdout := fd(), stderr := fd()}
cstruct() = [binary() | {ptr, binary() | non_neg_integer()}, ...]
fd() = int32_t()
gid_t() = uint32_t()
int32_t() = -2147483647..2147483647
int64_t() = -9223372036854775807..9223372036854775807
mode_t() = uint32_t()
off_t() = uint64_t()
pid_t() = int32_t()
posix() = alcove:posix()
prx_opt() = maxchild | exit_status | maxforkdepth | termsig | flowcontrol | signaloneof
ptr_arg() = binary() | constant() | cstruct()
ptr_val() = binary() | integer() | cstruct()
size_t() = uint64_t()
ssize_t() = int64_t()
task() = pid()
uid_t() = uint32_t()
uint32_t() = 0..4294967295
uint64_t() = 0..18446744073709551615
waitstatus() = {exit_status, int32_t()} | {termsig, atom()} | {stopsig, atom()} | continued
atexit/2 | Register a function to be called at task termination. |
call/3 | Make a synchronous call into the port driver. |
cap_enter/1 | (FreeBSD only) cap_enter(2) : put process into capability mode. |
cap_fcntls_get/2 | (FreeBSD only) cap_fcntls_get(2) : get allowed fnctl(2) commands on file descriptor. |
cap_fcntls_limit/3 | (FreeBSD only) cap_fcntls_limit(2) : set allowed fnctl(2) commands on file descriptor. |
cap_getmode/1 | (FreeBSD only) cap_getmode(2) : returns capability mode status of process. |
cap_ioctls_limit/3 | (FreeBSD only) cap_ioctls_limit(2) : set allowed ioctl(2) commands on file descriptor. |
cap_rights_limit/3 | (FreeBSD only) cap_rights_limit(2) : set allowed rights(4) of file descriptor. |
chdir/2 | chdir(2) : change process current working directory. |
chmod/3 | chmod(2) : change file permissions. |
chown/4 | chown(2) : change file ownership. |
chroot/2 | chroot(2) : change root directory. |
clearenv/1 | clearenv(3) : zero process environment. |
clone/2 | (Linux only) clone(2) : create a new process. |
close/2 | close(2) : close a file descriptor. |
cmd/2 | |
cpid/1 | Returns the list of child PIDs for this process. |
cpid/2 | retrieve process info for forked processes. |
drv/1 | |
environ/1 | environ(7) : return the process environment variables. |
eof/2 | close stdin of child process. |
eof/3 | close stdin, stdout or stderr of child process. |
execed/1 | test if the task has called exec(2). |
execve/3 | execve(2) : replace the process image, specifying the environment for the new process image. |
execve/4 | execve(2) : replace the process image, specifying the environment for the new process image. |
execvp/2 | execvp(2) : replace the current process image using the search path. |
execvp/3 | execvp(2) : replace the current process image using the search path. |
exit/2 | exit(3) : cause the child process to exit. |
fcntl/3 | fcntl(2) : perform operation on a file descriptor. |
fcntl/4 | fcntl(2) : perform operation on a file descriptor with argument. |
fexecve/4 | fexecve(2) : replace the process image, specifying the environment for the new process image, using a previously opened file descriptor. |
filter/2 | filter() : restrict calls available to a control process. |
fork/0 | fork(2) : create a new system process. |
fork/1 | fork(2) : create a child process. |
forkchain/1 | |
getcpid/2 | getcpid() : Get options for child process of prx control process. |
getcpid/3 | getcpid() : Retrieve attributes set by the prx control process for a child process. |
getcwd/1 | getcwd(3) : return the current working directory. |
getenv/2 | getenv(3) : retrieve an environment variable. |
getgid/1 | getgid(2) : retrieve the processes' group ID. |
getgroups/1 | getgroups(2) : retrieve the list of supplementary groups. |
gethostname/1 | gethostname(2) : retrieve the system hostname. |
getopt/2 | getopt() : get options for the prx control process. |
getpgrp/1 | getpgrp(2) : retrieve the process group. |
getpid/1 | getpid(2) : retrieve the system PID of the process. |
getpriority/3 | getpriority(2) : retrieve scheduling priority of process, process group or user. |
getresgid/1 | getresgid(2) : get real, effective and saved group ID. |
getresuid/1 | getresuid(2) : get real, effective and saved user ID. |
getrlimit/2 | getrlimit(2) : retrieve the resource limits for a process. |
getsid/2 | getsid(2) : retrieve the session ID. |
getuid/1 | getuid(2) : returns the process user ID. |
ioctl/4 | ioctl(2) : control device. |
jail/2 | (FreeBSD only) jail(2) : restrict the current process in a system jail. |
kill/3 | kill(2) : terminate a process. |
lseek/4 | lseek(2) : set file offset for read/write. |
mkdir/3 | mkdir(2) : create a directory. |
mkfifo/3 | mkfifo(3) : create a named pipe. |
mount/6 | mount(2) : mount a filesystem, Linux style. |
mount/7 | (Solaris only) mount(2) : mount a filesystem. |
open/3 | open(2) : returns a file descriptor associated with a file. |
open/4 | open(2) : create a file, specifying permissions. |
parent/1 | |
pidof/1 | retrieves the system PID of the process similar to getpid(2). |
pivot_root/3 | (Linux only) pivot_root(2) : change the root filesystem. |
pledge/3 | (OpenBSD only) pledge(2) : restrict system operations
prx:pledge(Task, "stdio proc exec", []) |
prctl/6 | (Linux only) prctl(2) : operations on a process. |
ptrace/5 | (Linux only) ptrace(2) : trace processes. |
read/3 | read(2) : read bytes from a file descriptor. |
readdir/2 | readdir(3) : retrieve list of objects in a directory. |
replace_process_image/1 | Replace the port process image using execve(2)/fexecve(2). |
replace_process_image/3 | Replace the port process image using execve(2)/fexecve(2). |
rmdir/2 | rmdir(2) : delete a directory. |
seccomp/4 | seccomp(2) : restrict system operations. |
select/5 | select(2) : poll a list of file descriptor for events. |
setcpid/3 | setcpid() : Set options for child process of prx control process. |
setcpid/4 | setcpid() : Set options for child process of prx control process. |
setenv/4 | setenv(3) : set an environment variable. |
setgid/2 | setgid(2) : set the GID of the process. |
setgroups/2 | setgroups(2) : set the supplementary groups of the process. |
sethostname/2 | sethostname(2) : set the system hostname. |
setns/2 | (Linux only) setns(2) : attach to a namespace. |
setns/3 | (Linux only) setns(2) : attach to a namespace, specifying namespace type. |
setopt/3 | setopt() : set options for the prx control process. |
setpgid/3 | setpgid(2) : set process group. |
setpriority/4 | setpriority(2) : set scheduling priority of process, process group or user. |
setproctitle/2 | setproctitle(3) : set the process title. |
setresgid/4 | setresgid(2) : set real, effective and saved group ID. |
setresuid/4 | setresuid(2) : set real, effective and saved user ID. |
setrlimit/3 | setrlimit(2) : set a resource limit. |
setsid/1 | setsid(2) : create a new session. |
setuid/2 | setuid(2) : change UID. |
sh/2 | |
sigaction/3 | sigaction(2) : set process behaviour for signals. |
socket/4 | socket(2) : retrieve file descriptor for communication endpoint. |
start_link/1 | |
stdin/2 | Send data to the standard input of the process. |
stop/1 | terminate the task. |
sudo/0 | Convenience function to fork a privileged process in the shell. |
sudo/1 | Convenience function to fork a privileged process in the shell. |
task/3 | |
task/4 | |
umount/2 | umount(2) : unmount a filesystem. |
unlink/2 | unlink(2) : delete references to a file. |
unsetenv/2 | unsetenv(3) : remove an environment variable. |
unshare/2 | (Linux only) unshare(2) : allows creating a new namespace in the current process. |
waitpid/3 | waitpid(2) : wait for child process. |
write/3 | write(2): writes a buffer to a file descriptor and returns the number of bytes written. |
Register a function to be called at task termination
The atexit function runs in the parent of the process. atexit/2 must use prx_drv:call/4 to manipulate the task.
The default function closes stdin, stdout and stderr of the system process:
fun(Drv, ForkChain, Pid) -> prx_drv:call(Drv, ForkChain, close, [maps:get(stdout, Pid)]), prx_drv:call(Drv, ForkChain, close, [maps:get(stdin, Pid)]), prx_drv:call(Drv, ForkChain, close, [maps:get(stderr, Pid)]) end
call(Task::task(), Call::atom(), Argv::[any()]) -> any()
Make a synchronous call into the port driver.
The list of available calls and their arguments can be found here:
https://github.com/msantos/alcove#alcove-1
For example, to directly call alcove:execve/5
:
call(Task, execve, ["/bin/ls", ["/bin/ls", "-al"], ["HOME=/home/foo"]])
(FreeBSD only) cap_enter(2) : put process into capability mode
(FreeBSD only) cap_fcntls_get(2) : get allowed fnctl(2) commands on file descriptor
cap_fcntls_limit(Task::task(), Arg1::fd(), Arg2::[constant()]) -> ok | {error, posix()}
(FreeBSD only) cap_fcntls_limit(2) : set allowed fnctl(2) commands on file descriptor
(FreeBSD only) cap_getmode(2) : returns capability mode status of process
*0
: false
* 1
: true
cap_ioctls_limit(Task::task(), Arg1::fd(), Arg2::[constant()]) -> ok | {error, posix()}
(FreeBSD only) cap_ioctls_limit(2) : set allowed ioctl(2) commands on file descriptor
cap_rights_limit(Task::task(), Arg1::fd(), Arg2::[constant()]) -> ok | {error, posix()}
(FreeBSD only) cap_rights_limit(2) : set allowed rights(4) of file descriptor
chdir(2) : change process current working directory.
chmod(2) : change file permissions
chown(2) : change file ownership
chroot(2) : change root directory
clearenv(3) : zero process environment
clone(Task::task(), Flags::[constant()]) -> {ok, task()} | {error, posix()}
(Linux only) clone(2) : create a new process
close(2) : close a file descriptor.
Returns the list of child PIDs for this process.
Each child task is a map composed of: * pid: system pid * exec: true if the child has called exec() * fdctl: parent end of CLOEXEC file descriptor used to monitor if the child process has called exec() * stdin: parent end of the child process' standard input * stdout: parent end of the child process' standard output * stderr: parent end of the child process' standard errorretrieve process info for forked processes
Retrieve the map for a child process as returned in prx:cpid/1.
cpid/2 searches the list of a process' children for a PID (an erlang or a system PID) and returns a map containing the parent's file descriptors towards the child.drv(Task::task()) -> pid()
environ(Task::task()) -> [binary()]
environ(7) : return the process environment variables
close stdin of child process
close stdin, stdout or stderr of child process
execed(Task::task()) -> boolean()
test if the task has called exec(2)
Returnstrue
if the task is running in exec mode.
execve(2) : replace the process image, specifying the environment for the new process image.
execve(2) : replace the process image, specifying the environment for the new process image.
Allows setting the command name in the process list:prx:execve(Task, "/bin/cat", ["name-in-process-list", "-n"], ["VAR=1"])
execvp(2) : replace the current process image using the search path
execvp(2) : replace the current process image using the search path
Allows setting the command name in the process list:prx:execvp(Task, "cat", ["name-in-process-list", "-n"])
exit(3) : cause the child process to exit
fcntl(Task::task(), Arg1::fd(), Arg2::constant()) -> {ok, int64_t()} | {error, posix()}
fcntl(2) : perform operation on a file descriptor
fcntl(Task::task(), Arg1::fd(), Arg2::constant(), Arg3::int64_t()) -> {ok, int64_t()} | {error, posix()}
fcntl(2) : perform operation on a file descriptor with argument
fexecve(2) : 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, FD} = prx:open(Task, "/bin/ls", [o_rdonly,o_cloexec]), ok = prx:fexecve(Task, FD, ["-al"], ["FOO=123"]).
Linux and FreeBSD only. Linux requires an environment be set unlike with execve(2). The environment can be empty:
% Environment required on Linux ok = prx:fexecve(Task, FD, ["-al"], [""]), [<<>>] = prx:environ(Task).
filter(Task::task(), Calls0::[constant()] | constant()) -> ok
filter() : restrict calls available to a control process
filter/2 restricts calls for a prx control process. A control process will continue to proxy data as well as monitor and reap subprocesses.
Invoking a filtered call will crash the process with 'undef'.
If the filter/1 call is filtered, subsequent calls to filter/1 will fail.
Once a filter for a call is added, the call cannot be removed from the filter set.
Filters are inherited by the child process from the parent.
{ok, Ctrl} = prx:fork(), {ok, Task} = prx:fork(Ctrl), ok = prx:filter(Ctrl, fork), {'EXIT', {undef, _}} = (catch prx:fork(Ctrl)).
fork(2) : create a new system process
The behaviour of the process can be controlled by setting the application environment:
Option = {exec, string()} | {progname, string()} | {ctldir, string()}
* {exec, Exec}
Default: ""
Sets a command to run the port under such as sudo or valgrind.
For example, to start the process as root using sudo
, allow running
prx
as root:
sudo visudo -f /etc/sudoers.d/99_prx <user> ALL = NOPASSWD: /path/to/prx/priv/prx Defaults!/path/to/alcove/priv/alcove !requiretty ``` Then: ``` application:set_env(prx, options, [{exec, "sudo -n"}])
* {progname, Path}
Default: priv/prx
Sets the path to the prx executable.
* {ctldir, Path}
Default: priv
A control directory writable by the prx port process (the Unix process may be running under a different user than the Erlang VM).
The control directory contains a FIFO shared by beam and the port process which is used to notify the Erlang VM that the port process has called exec().fork(2) : create a child process
Forks child processes from an existing task. For example:
{ok, Task} = prx:fork(), % PID 16341 {ok, Child1} = prx:fork(Task), % PID 16349 {ok, Child2} = prx:fork(Task), % PID 16352 {ok, Child2a} = prx:fork(Child2), % PID 16354 {ok, Child2aa} = prx:fork(Child2a), % PID 16357 {ok, Child2ab} = prx:fork(Child2a). % PID 16482
Results in a process tree:
prx(16341)-+-prx(16349) `-prx(16352)---prx(16354)-+-prx(16357) `-prx(16482)
getcpid() : Get options for child process of prx control process
Control behaviour of an exec()'ed process.
See getcpid/3 for options.getcpid() : Retrieve attributes set by the prx control process for a child process
* flowcontrol: number of messages allowed from process
-1 : flowcontrol disabled 0 : stdout/stderr for process is not read 0+ : read this many messages from the process
* signaloneof: signal sent to child process on shutdowngetcwd(3) : return the current working directory
getenv(Task::task(), Arg1::iodata()) -> binary() | false
getenv(3) : retrieve an environment variable
getgid(2) : retrieve the processes' group ID
getgroups(2) : retrieve the list of supplementary groups
gethostname(2) : retrieve the system hostname
getopt() : get options for the prx control process
Retrieve port options for a prx control process. These 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 prx:fork/0:
maxchild : non_neg_integer() : (ulimit -n) / 4 - 4
Number of child processes allowed for this process. This value can be modified by adjusting RLIMIT_NOFILE for the process.
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 fork chain.
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/3,4.
signaloneof : 0-254 : 15
Send a signal to a child process on shutdown (stdin of the alcove control process is closed).
See setcpid/3,4.getpgrp(2) : retrieve the process group.
getpid(2) : retrieve the system PID of the process.
getpriority(Task::task(), Arg1::constant(), Arg2::int32_t()) -> {ok, int32_t()} | {error, posix()}
getpriority(2) : retrieve scheduling priority of process, process group or user
getresgid(2) : get real, effective and saved group ID
Supported on Linux and BSD's.getresuid(2) : get real, effective and saved user ID
Supported on Linux and BSD's.getrlimit(Task::task(), Resource::constant()) -> {ok, #{cur => uint64_t(), max => uint64_t()}} | {error, posix()}
getrlimit(2) : retrieve the resource limits for a process
getsid(2) : retrieve the session ID
getuid(2) : returns the process user ID
ioctl(Task::task(), Arg1::fd(), Arg2::constant(), Arg3::cstruct()) -> {ok, #{return_value := integer(), arg := iodata()}} | {error, posix()}
ioctl(2) : control device
Controls a device using a file descriptor previously obtained using open/4.
Argp can be either a binary or a list representation of a C struct. See prctl/6 below for a description of the list elements.
On success, ioctl/4 returns a 2-tuple containing a map. The map keys are:
return_value: an integer equal to the return value of the ioctl.
Usually 0, however some ioctl's on Linux use the return value as the output parameter.
arg: 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
An example of creating a tap device in a net namespace on Linux:
{ok, Child} = prx:clone(Task, [clone_newnet]), {ok, FD} = prx:open(Child, "/dev/net/tun", [o_rdwr], 0), {ok, #{return_value = 0, arg = <<"tap", N, _/binary>>}} = prx:ioctl(Child, FD, tunsetiff, << 0:(16*8), % generate a tuntap device name (16#0002 bor 16#1000):2/native-unsigned-integer-unit:8, % IFF_TAP, IFF_NO_PI 0:(14*8) >>), {ok, <<"tap", N>>}.
jail(Task::task(), Arg1::#{version => alcove:uint32_t(), path => iodata(), hostname => iodata(), jailname => iodata(), ip4 => [inet:ip4_address()], ip6 => [inet:ip6_address()]} | cstruct()) -> {ok, int32_t()} | {error, posix()}
(FreeBSD only) jail(2) : restrict the current process in a system jail
kill(Task::task(), Arg1::pid_t(), Arg2::constant()) -> ok | {error, posix()}
kill(2) : terminate a process
lseek(2) : set file offset for read/write
mkdir(2) : create a directory
mkfifo(3) : create a named pipe
mount(Task::task(), Arg1::iodata(), Arg2::iodata(), Arg3::iodata(), Arg4::uint64_t() | [constant()], Arg5::iodata()) -> ok | {error, posix()}
mount(2) : mount a filesystem, Linux style
The arguments are:
* source
* target
* filesystem type
* flags
* data
An empty binary 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 mount namespace using the MS_REC|MS_PRIVATE
flags:
{ok, Task} = prx:clone(Parent, [clone_newns]), ok = prx:mount(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);mount(Task::task(), Arg1::iodata(), Arg2::iodata(), Arg3::iodata(), Arg4::uint64_t() | [constant()], Arg5::iodata(), Arg6::iodata()) -> ok | {error, posix()}
(Solaris only) mount(2) : mount a filesystem
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.open(Task::task(), Arg1::iodata(), Arg2::int32_t() | [constant()]) -> {ok, fd()} | {error, posix()}
open(2) : returns a file descriptor associated with a file
Lists of values are OR'ed:
prx:open(Task, "/etc/motd", [o_rdonly])
open(Task::task(), Arg1::iodata(), Arg2::int32_t() | [constant()], Arg3::mode_t()) -> {ok, fd()} | {error, posix()}
open(2) : create a file, specifying permissions
prx:open(Task, "/tmp/test", [o_wronly,o_creat], 8#644)
retrieves the system PID of the process similar to getpid(2)
Returns the cached value for the PID of the system process.OSPid = prx:getpid(Task), OSPid = prx:pidof(Task).
(Linux only) pivot_root(2) : change the root filesystem
(OpenBSD only) pledge(2) : restrict system operations
prx:pledge(Task, "stdio proc exec", [])
prctl(Task::task(), Arg1::constant(), Arg2::ptr_arg(), Arg3::ptr_arg(), Arg4::ptr_arg(), Arg5::ptr_arg()) -> {ok, integer(), ptr_val(), ptr_val(), ptr_val(), ptr_val()} | {error, posix()}
(Linux only) 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 zero'ed memory is allocated. 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.
For example, to enforce a seccomp filter:
% NOTE: this filter will result in the port being sent a SIGSYS % The prx process requires the following syscalls to run: % sys_exit % sys_exit_group % sys_getrlimit % sys_poll % sys_read % sys_restart_syscall % sys_rt_sigreturn % sys_setrlimit % sys_sigreturn % sys_ugetrlimit % sys_write % sys_writev Arch = prx:call(Task, syscall_constant, [alcove:audit_arch]), Filter = [ ?VALIDATE_ARCHITECTURE(Arch), ?EXAMINE_SYSCALL, sys_read, sys_write ], {ok,_,_,_,_,_} = prx:prctl(Task, 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)} ], prx:prctl(Task, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).
ptrace(Task::task(), Arg1::constant(), Arg2::pid_t(), Arg3::ptr_arg(), Arg4::ptr_arg()) -> {ok, integer(), ptr_val(), ptr_val()} | {error, posix()}
(Linux only) ptrace(2) : trace processes
read(2) : read bytes from a file descriptor
readdir(3) : retrieve list of objects in a directory
Replace the port process image using execve(2)/fexecve(2)
The call stack of the child processes grow because the port process forks recursively. The stack layout will also be the same as the parent, defeating ASLR protections.
For most processes this is not a concern: the process will call exec() after performing some operations.
Some "system" or "supervisor" type processes may remain in call mode: these processes can call replace_process_image/1 to exec() the port.
On platforms supporting fexecve(2) (FreeBSD, Linux), prx will open a file descriptor to the port binary and use it to re-exec() the port.
On other OS'es, execve(2) will be used with the the default path to the port binary.
If the binary is not accessible or, on Linux, /proc is not mounted, replace_process_image/1 will fail.replace_process_image(Task::task(), Argv::{fd, int32_t(), iodata()} | iodata(), Env::iodata()) -> ok | {error, posix()}
Replace the port process image using execve(2)/fexecve(2)
Specify the port program path or a file descriptor to the binary and the process environment.rmdir(2) : delete a directory
seccomp(Task::task(), Arg1::constant(), Arg2::constant(), Arg3::cstruct()) -> boolean()
seccomp(2) : restrict system operations
See prctl/6.select(Task::task(), Readfds::[fd()], Writefds::[fd()], Exceptfds::[fd()], Timeout::null | 'NULL' | #{sec => int64_t(), usec => int64_t()}) -> {ok, [fd()], [fd()], [fd()]} | {error, posix()}
select(2) : poll a list of file descriptor for events
select/5 will block until an event occurs on a file descriptor, a timeout is reached or interrupted by a signal.
The Timeout value may be:
* null
(block forever)
sec : number of seconds to wait usec : number of microseconds to waitFor example:
{ok,[],[],[]} = prx:select(Task, [], [], [], #{sec => 10, usec => 100}).
setcpid() : Set options for child process of prx control process
Control behaviour of an exec()'ed process.
See setcpid/4 for options.setcpid() : Set options for child process of prx control process
* flowcontrol: enable 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: the prx control process sends this signal to the child process on shutdown (default: 15 (SIGTERM))setenv(3) : set an environment variable
setgid(2) : set the GID of the process
setgroups(2) : set the supplementary groups of the process
sethostname(2) : set the system hostname
This function is probably only useful if running in a uts namespace:
{ok, Child} = prx:clone(Task, [clone_newuts]), ok = prx:sethostname(Child, "test"), Hostname1 = prx:gethostname(Task), Hostname2 = prx:gethostname(Child), Hostname1 =/= Hostname2.
(Linux only) 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
For example, to attach to another process' network namespace:
{ok, Child1} = prx:clone(Task, [clone_newnet]), {ok, Child2} = prx:fork(Task), % Move Child2 into the Child1 network namespace {ok,FD} = prx:open(Child2, ["/proc/", integer_to_list(Child1), "/ns/net"], [o_rdonly], 0), ok = prx:setns(Child2, FD, 0), ok = prx:close(Child2, FD).
setns(Task::task(), Arg1::iodata(), Arg2::constant()) -> ok | {error, posix()}
(Linux only) setns(2) : attach to a namespace, specifying namespace type
ok = prx:setns(Task, FD, clone_newnet)
setopt() : set options for the prx control process
See getopt/3 for options.setpgid(2) : set process group
setpriority(Task::task(), Arg1::constant(), Arg2::int32_t(), Arg3::int32_t()) -> ok | {error, posix()}
setpriority(2) : set scheduling priority of process, process group or user
setproctitle(Task::task(), Name::iodata()) -> ok
setproctitle(3) : set the process title
Set the process title displayed in utilities like ps(1).
Linux systems may also want to set the command name using prctl/6:
prx:prctl(Task, pr_set_name, <<"newname">>, 0, 0, 0)
setresgid(2) : set real, effective and saved group ID
Supported on Linux and BSD's.setresuid(2) : set real, effective and saved user ID
Supported on Linux and BSD's.setrlimit(Task::task(), Resource::constant(), Rlim::#{cur => uint64_t(), max => uint64_t()}) -> ok | {error, posix()}
setrlimit(2) : set a resource limit
setsid(2) : create a new session
setuid(2) : change UID
sigaction(Task::task(), Arg1::constant(), Arg2::atom() | <<>>) -> {ok, 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.
* <<>>
: retrieve current handler for signal
socket(Task::task(), Arg1::constant(), Arg2::constant(), Arg3::int32_t()) -> {ok, fd()} | {error, posix()}
socket(2) : retrieve file descriptor for communication endpoint
{ok, FD} = prx:socket(Task, af_inet, sock_stream, 0).
stdin(Task::task(), Buf::iodata()) -> ok
Send data to the standard input of the process.
stop(Task::task()) -> ok
terminate the task
sudo() -> ok
Convenience function to fork a privileged process in the shell
Sets the application environment so prx can fork a privileged
process. sudo
must be configured to run the prx binary.
The application environment must be set before prx:fork/0 is called.
Equivalent to:application:set_env(prx, options, [{exec, "sudo -n"}]), {ok, Task} = prx:fork(), 0 = prx:getuid(Task).
sudo(Exec::string()) -> ok
Convenience function to fork a privileged process in the shell
Allows specifying the command. For example, on OpenBSD:prx:sudo("doas"), {ok, Task} = prx:fork(), 0 = prx:getuid(Task).
task(Task::task(), Ops::[prx_task:op() | [prx_task:op()]], State::any()) -> {ok, task()} | {error, posix()}
task(Task::task(), Ops::[prx_task:op() | [prx_task:op()]], State::any(), Config::[prx_task:config()]) -> {ok, task()} | {error, posix()}
umount(2) : unmount a filesystem
On BSD systems, calls unmount(2).unlink(2) : delete references to a file
unsetenv(3) : remove an environment variable
unshare(Task::task(), Arg1::int32_t() | [constant()]) -> ok | {error, posix()}
(Linux only) unshare(2) : allows creating a new namespace in the current process
unshare(2) lets you make a new namespace without calling clone(2):
% The port is now running in a namespace without network access. ok = prx:unshare(Task, [clone_newnet]).
waitpid(Task::task(), Arg1::pid_t(), Arg2::int32_t() | [constant()]) -> {ok, pid_t(), int32_t(), [waitstatus()]} | {error, posix()}
waitpid(2) : wait for child process
To use waitpid/3, disable handling of child processes by the event loop:
{ok, sig_dfl} = prx:sigaction(Task, sigchld, sig_info), {ok, Child} = prx:fork(Task), Pid = prx:getpid(Child), ok = prx:exit(Child, 2), {ok, Pid, _, [{exit_status, 2}]} = prx:waitpid(Task, Pid, [wnohang]).
write(2): writes a buffer to a file descriptor and returns the number of bytes written.
Generated by EDoc