:- module(process, [
- process_create/3,
+ process_create/3,
process_id/2,
- process_release/1,
- process_wait/2,
- process_wait/3,
+ process_release/1,
+ process_wait/2,
+ process_wait/3,
process_kill/1
]).
% Create a new process by executing the executable Exe and passing it the Arguments Args.
%
% Note: On windows please take note of [windows argument splitting](https://doc.rust-lang.org/std/process/index.html#windows-argument-splitting).
-%
+%
% Options is a list consisting of the following options:
%
% * `cwd(+Path)` Set the processes working directory to `Path`
% `env/1` and `environment/1` may not be both specified.
%
% The following stdio `Spec` are available:
-%
+%
% * `std` inherit the current processes original stdio streams (does currently not account for stdio being changed by `set_input` or `set_output`)
-% * `file(+Path)` attach the strea to the file at `Path`
+% * `file(+Path)` attach the stream to the file at `Path`
% * `null` discards writes and behaves as eof for read. Equivalent to using `file(/dev/null)`
-% * `pipe(-Steam)` create a new pipe and assigne one end to the created process and the other end to `Stream`
+% * `pipe(-Steam)` create a new pipe and assign one end to the created process and the other end to `Stream`
%
% Specifying an option multiple times is an error, when an option is not specified the following defaults apply:
%
%
process_wait(Process, Status, Options) :- call_with_error_context(process_wait_(Process, Status, Options), predicate-process_wait/3).
-process_wait_(Process, Status, Options) :-
+process_wait_(Process, Status, Options) :-
valid_process(Process),
check_options(
[
% On Unix this sends SIGKILL.
%
% Only works for processes spawned with `process_create/3` that have not yet been release with `process_release/1`
-%
+%
process_kill(Process) :- call_with_error_context(process_kill_(Process), predicate-process_kill/1).
-process_kill_(Process) :-
+process_kill_(Process) :-
valid_process(Process),
'$process_kill'(Process).
; domain_error(Domain, X, [])
) ,
( member(Option, Found) -> domain_error(non_duplicate_options, Option , [])
- ; member(Option, Valid) -> true
+ ; member(Option, Valid) -> true
; domain_error(Domain, Option, [])
),
must_be_known_options_(Valid, [Option | Found], XS, Domain).
extract_options(KnownOptions, Options) :- call_with_error_context(extract_options_(KnownOptions, Options), predicate-extract_options/2).
extract_options_([], _).
-extract_options_([X | XS], Options) :-
+extract_options_([X | XS], Options) :-
option(Kinds, Pred, Default, Choice) = X,
tfilter(find_option(Kinds), Options, Solutions),
( Solutions = [] -> Choice = Default
- ; Solutions = [Provided] -> functor(Pred, Name, Arity), ArityP1 is Arity+1, call_with_error_context(call(Pred, Provided),predicate-Name/ArityP1), Choice = Provided
+ ; Solutions = [Provided] -> functor(Pred, Name, Arity), ArityP1 is Arity+1, call_with_error_context(call(Pred, Provided),predicate-Name/ArityP1), Choice = Provided
; domain_error(non_conflicting_options, Solutions, [])
),
extract_options_(XS, Options).
-find_option(Names, Found, T) :-
- functor(Found, Name, 1),
+find_option(Names, Found, T) :-
+ functor(Found, Name, 1),
memberd_t(Name, Names, T).
valid_stdio(IO) :- arg(1, IO, Arg),
valid_stdio_(pipe(Stream)) :- must_be(var, Stream).
valid_stdio_(file(Path)) :- must_be(chars, Path).
-valid_env(env(E)) :-
+valid_env(env(E)) :-
must_be(list, E),
- ( valid_env_(E) -> true
+ ( valid_env_(E) -> true
; domain_error(process_create_option, env(E), [])
).
-valid_env(environment(E)) :-
+valid_env(environment(E)) :-
must_be(list, E),
- ( valid_env_(E) -> true
+ ( valid_env_(E) -> true
; domain_error(process_create_option, environment(E), [])
).
valid_env_([]).
-valid_env_([N=V|ES]) :-
- must_be(chars, N),
+valid_env_([N=V|ES]) :-
+ must_be(chars, N),
must_be(chars, V),
valid_env_(ES).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Negotiation of TLS connections.
Part of Scryer Prolog.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- use_module(library(lists)).
:- use_module(library(error)).
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- TLS Clients
- ===========
-
- Use tls_client_context/2 to create a TLS context, for example with:
-
- tls_client_context(Context, [hostname("metalevel.at")])
-
- Using the context and an existing stream S0 (for example, the
- result of socket_client_open/3), a TLS stream S can be negotiated
- with:
-
- tls_client_negotiate(Context, S0, S)
-
- S will be an encrypted and authenticated stream with the server.
-
- The advantage of separating the creation of the client context from
- negotiating a connection is that the context can be created only once,
- and quickly reused if needed. This is currently not implemented: In
- the present implementation, a new internal "Connector" is created for
- every connection, using the specified hostname.
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
+/** Negotiation of TLS connections.
+*/
+
+%% tls_client_context(-Context, +Options)
+%
+% Use `tls_client_context/2` to create a TLS context, for example with:
+%
+% ```
+% tls_client_context(Context, [hostname("metalevel.at")])
+% ```
+%
tls_client_context(tls_context(Host), Options) :-
must_be(list, Options),
( member(hostname(Host), Options) ->
; Host = ""
).
+%% tls_client_negotiate(+Context, +Stream0, -Stream)
+%
+% Using the context and an existing stream `S0` (for example, the result of
+% `socket_client_open/3`), a TLS stream `S` can be negotiated with:
+%
+% ```
+% tls_client_negotiate(Context, S0, S)
+% ```
+%
+% `S` will be an encrypted and authenticated stream with the server.
+%
+% The advantage of separating the creation of the client context from
+% negotiating a connection is that the context can be created only once, and
+% quickly reused if needed. This is currently not implemented: In the present
+% implementation, a new internal "Connector" is created for every connection,
+% using the specified hostname.
tls_client_negotiate(tls_context(Host), S0, S) :-
'$tls_client_connect'(Host, S0, S).
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- TLS Servers
- ===========
-
- Use tls_server_context/2 to create a TLS context, for example with:
-
- tls_server_context(Context, [pkcs12(Chars)])
-
- where Chars is a list of characters with the contents of a
- DER-formatted PKCS #12 archive. The option password(Ps) can be used
- to specify the password Ps (also a string) for decrypting the key.
- On some versions of OSX, and potentially also on other platforms,
- empty passwords are not supported.
-
- The archive should contain a leaf certificate and its private key,
- as well any intermediate certificates that should be sent to
- clients to allow them to build a chain to a trusted root. The chain
- certificates should be in order from the leaf certificate towards
- the root.
-
- PKCS #12 archives typically have the file extension .p12 or .pfx,
- and can be created with the OpenSSL pkcs12 tool:
-
- $ openssl pkcs12 -export -out identity.pfx \
- -inkey key.pem -in cert.pem -certfile chain_certs.pem
-
-
- You can use phrase_from_file/3 from library(pio) and seq//1 from
- library(dcgs) to read the contents of "identity.pfx" into a string:
-
- phrase_from_file(seq(Chars), "identity.pfx", [type(binary)])
-
- The obtained context should be treated as an opaque Prolog term.
-
- Using the context and an existing stream S0 (for example, the
- result of socket_server_accept/4), a TLS stream S can be negotiated
- by a Prolog-based server with:
-
- tls_server_negotiate(Context, S0, S)
-
- S will be an encrypted and authenticated stream with the client.
-
- The advantage of separating the creation of the server context from
- negotiating a connection is that the context can be created only
- once, and quickly cloned for every incoming connection. This is
- currently not implemented: In the present implementation, a new context
- is created for every connection, using the specified parameters.
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
+%% tls_server_context(-Context, +Options)
+%
+% Use `tls_server_context/2` to create a TLS context, for example with:
+%
+% ```
+% tls_server_context(Context, [pkcs12(Chars)])
+% ```
+%
+% where Chars is a list of characters with the contents of a DER-formatted PKCS
+% #12 archive. The option `password(Ps)` can be used to specify the password
+% `Ps` (also a string) for decrypting the key. On some versions of OSX, and
+% potentially also on other platforms, empty passwords are not supported.
+%
+% The archive should contain a leaf certificate and its private key, as well any
+% intermediate certificates that should be sent to clients to allow them to
+% build a chain to a trusted root. The chain certificates should be in order
+% from the leaf certificate towards the root.
+%
+% PKCS #12 archives typically have the file extension `.p12` or `.pfx`, and can
+% be created with the OpenSSL `pkcs12` tool:
+%
+% ```
+% $ openssl pkcs12 -export -out identity.pfx \
+% -inkey key.pem -in cert.pem -certfile chain_certs.pem
+% ```
+%
+% You can use `phrase_from_file/3` from `library(pio)` and `seq//1` from
+% `library(dcgs)` to read the contents of `identity.pfx` into a string:
+%
+% ```
+% phrase_from_file(seq(Chars), "identity.pfx", [type(binary)])
+% ```
+%
+% The obtained context should be treated as an opaque Prolog term.
tls_server_context(tls_context(Cert,Password), Options) :-
( member(pcks12(Cert), Options) ->
must_be(chars, Cert)
; Password = ""
).
+%% tls_server_negotiate(+Context, +Stream0, -Stream)
+%
+% Using the context and an existing stream `S0` (for example, the result of
+% `socket_server_accept/4`), a TLS stream `S` can be negotiated by a
+% Prolog-based server with:
+%
+% ```
+% tls_server_negotiate(Context, S0, S)
+% ```
+%
+% `S` will be an encrypted and authenticated stream with the client.
+%
+% The advantage of separating the creation of the server context from
+% negotiating a connection is that the context can be created only once, and
+% quickly cloned for every incoming connection. This is currently not
+% implemented: In the present implementation, a new context is created for every
+% connection, using the specified parameters.
tls_server_negotiate(tls_context(Cert,Password), S0, S) :-
'$tls_accept_client'(Cert, Password, S0, S).
-