145 lines
3.9 KiB
Prolog
145 lines
3.9 KiB
Prolog
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Predicates for reasoning about the operating system (OS) environment.
|
|
Written July 2020 by Markus Triska (triska@metalevel.at).
|
|
|
|
Lists of characters are used throughout to represent keys and values.
|
|
|
|
Example:
|
|
|
|
?- getenv("LANG", Ls).
|
|
Ls = "en_US.UTF-8".
|
|
|
|
Public domain code.
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
/** Predicates for reasoning about the operating system (OS) environment.
|
|
|
|
This includes predicates about environment variables, calls to shell and
|
|
finding out the PID of the running system.
|
|
*/
|
|
|
|
:- module(os, [getenv/2,
|
|
setenv/2,
|
|
unsetenv/1,
|
|
shell/1,
|
|
shell/2,
|
|
pid/1,
|
|
raw_argv/1,
|
|
argv/1]).
|
|
|
|
:- use_module(library(error)).
|
|
:- use_module(library(charsio)).
|
|
:- use_module(library(lists)).
|
|
:- use_module(library(si)).
|
|
|
|
%% getenv(+Key, -Value).
|
|
%
|
|
% True iff Value contains the value of the environment variable Key.
|
|
% Example:
|
|
%
|
|
% ```
|
|
% ?- getenv("LANG", Ls).
|
|
% Ls = "en_US.UTF-8".
|
|
% ```
|
|
getenv(Key, Value) :-
|
|
must_be_env_var(Key),
|
|
'$getenv'(Key, Value).
|
|
|
|
%% setenv(+Key, +Value).
|
|
%
|
|
% Sets the environment variable Key to Value
|
|
setenv(Key, Value) :-
|
|
must_be_env_var(Key),
|
|
must_be_chars(Value),
|
|
'$setenv'(Key, Value).
|
|
|
|
%% unsetenv(+Key).
|
|
%
|
|
% Unsets the environment variable Key
|
|
unsetenv(Key) :-
|
|
must_be_env_var(Key),
|
|
'$unsetenv'(Key).
|
|
|
|
%% shell(+Command)
|
|
%
|
|
% Equivalent to `shell(Command, 0)`.
|
|
shell(Command) :- shell(Command, 0).
|
|
|
|
%% shell(+Command, -Status).
|
|
%
|
|
% True iff executes Command in a shell of the operating system and the exit code is Status.
|
|
% Keep in mind the shell syntax is dependant on the operating system, so it should be
|
|
% used very carefully.
|
|
%
|
|
% Example (using Linux and fish shell):
|
|
%
|
|
% ```
|
|
% ?- shell("echo $SHELL", Status).
|
|
% /bin/fish
|
|
% Status = 0.
|
|
% ```
|
|
shell(Command, Status) :-
|
|
must_be_chars(Command),
|
|
can_be(integer, Status),
|
|
'$shell'(Command, Status).
|
|
|
|
%% pid(-PID).
|
|
%
|
|
% True iff PID is the process identification number of current Scryer Prolog instance.
|
|
pid(PID) :-
|
|
can_be(integer, PID),
|
|
'$pid'(PID).
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
For now, we only support a restricted subset of variable names.
|
|
|
|
The reason is that Rust may panic if a key is empty, contains an
|
|
ASCII equals sign '=' or the NUL character '\0', or when the value
|
|
contains the NUL character.
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
must_be_env_var(Cs) :-
|
|
must_be_chars(Cs),
|
|
Cs = [_|_],
|
|
( maplist(permitted, Cs) -> true
|
|
; domain_error(env_var, Cs, os)
|
|
).
|
|
|
|
permitted(C) :- char_type(C, alnum).
|
|
permitted(C) :- char_type(C, ascii_punctuation).
|
|
permitted('_').
|
|
|
|
must_be_chars(Cs) :-
|
|
must_be(list, Cs),
|
|
maplist(must_be(character), Cs).
|
|
|
|
%% raw_argv(-Argv)
|
|
%
|
|
% True iff Argv is the list of arguments that this program was started with (usually passed via command line).
|
|
% In contrast to `argv/1`, this version includes every argument, without any postprocessing, just as the operating
|
|
% system reports it to the system. This includes-flags of Scryer itself, which are not needed in general.
|
|
raw_argv(Argv) :-
|
|
can_be(list, Argv),
|
|
'$argv'(Argv).
|
|
|
|
%% argv(-Argv)
|
|
%
|
|
% True if Argv is the list of arguments that this program was started with (usually passed via command line).
|
|
% In this version, only arguments specific to the program are passed. To differentiate between the system
|
|
% arguments and the program arguments, we use `--` as a separator.
|
|
%
|
|
% Example:
|
|
%
|
|
% ```
|
|
% % Call with scryer-prolog -f -- -t hello
|
|
% ?- argv(X).
|
|
% X = ["-t", "hello"].
|
|
% ```
|
|
argv(Argv) :-
|
|
can_be(list, Argv),
|
|
'$argv'(Argv0),
|
|
( append(_, ["--"|Argv], Argv0) ->
|
|
true
|
|
; Argv = []
|
|
).
|