ADDED: library(os), reasoning about environment variables.
Together with library(files), this addresses #511.
This commit is contained in:
@@ -442,6 +442,8 @@ The modules that ship with Scryer Prolog are also called
|
|||||||
Predicates for opening and accepting TCP connections as streams.
|
Predicates for opening and accepting TCP connections as streams.
|
||||||
TLS negotiation is performed via the option `tls(true)` in
|
TLS negotiation is performed via the option `tls(true)` in
|
||||||
`socket_client_open/3`, yielding secure encrypted connections.
|
`socket_client_open/3`, yielding secure encrypted connections.
|
||||||
|
* [`os`](src/lib/os.pl)
|
||||||
|
Predicates for reasoning about environment variables.
|
||||||
* [`crypto`](src/lib/crypto.pl)
|
* [`crypto`](src/lib/crypto.pl)
|
||||||
Cryptographically secure random numbers and hashes, HMAC-based
|
Cryptographically secure random numbers and hashes, HMAC-based
|
||||||
key derivation (HKDF), password-based key derivation (PBKDF2),
|
key derivation (HKDF), password-based key derivation (PBKDF2),
|
||||||
|
|||||||
@@ -306,6 +306,9 @@ pub enum SystemClauseType {
|
|||||||
Ed25519KeyPairPublicKey,
|
Ed25519KeyPairPublicKey,
|
||||||
LoadHTML,
|
LoadHTML,
|
||||||
LoadXML,
|
LoadXML,
|
||||||
|
GetEnv,
|
||||||
|
SetEnv,
|
||||||
|
UnsetEnv,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemClauseType {
|
impl SystemClauseType {
|
||||||
@@ -510,6 +513,9 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::Ed25519KeyPairPublicKey => clause_name!("$ed25519_keypair_public_key"),
|
&SystemClauseType::Ed25519KeyPairPublicKey => clause_name!("$ed25519_keypair_public_key"),
|
||||||
&SystemClauseType::LoadHTML => clause_name!("$load_html"),
|
&SystemClauseType::LoadHTML => clause_name!("$load_html"),
|
||||||
&SystemClauseType::LoadXML => clause_name!("$load_xml"),
|
&SystemClauseType::LoadXML => clause_name!("$load_xml"),
|
||||||
|
&SystemClauseType::GetEnv => clause_name!("$getenv"),
|
||||||
|
&SystemClauseType::SetEnv => clause_name!("$setenv"),
|
||||||
|
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,6 +700,9 @@ impl SystemClauseType {
|
|||||||
("$ed25519_keypair_public_key", 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
|
("$ed25519_keypair_public_key", 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
|
||||||
("$load_html", 3) => Some(SystemClauseType::LoadHTML),
|
("$load_html", 3) => Some(SystemClauseType::LoadHTML),
|
||||||
("$load_xml", 3) => Some(SystemClauseType::LoadXML),
|
("$load_xml", 3) => Some(SystemClauseType::LoadXML),
|
||||||
|
("$getenv", 2) => Some(SystemClauseType::GetEnv),
|
||||||
|
("$setenv", 2) => Some(SystemClauseType::SetEnv),
|
||||||
|
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ must_be_(var, Term) :-
|
|||||||
).
|
).
|
||||||
must_be_(integer, Term) :- check_(integer, integer, Term).
|
must_be_(integer, Term) :- check_(integer, integer, Term).
|
||||||
must_be_(atom, Term) :- check_(atom, atom, Term).
|
must_be_(atom, Term) :- check_(atom, atom, Term).
|
||||||
|
must_be_(character, T) :- check_(character, character, T).
|
||||||
must_be_(list, Term) :- check_(ilist, list, Term).
|
must_be_(list, Term) :- check_(ilist, list, Term).
|
||||||
must_be_(type, Term) :- check_(type, type, Term).
|
must_be_(type, Term) :- check_(type, type, Term).
|
||||||
must_be_(boolean, Term) :- check_(boolean, boolean, Term).
|
must_be_(boolean, Term) :- check_(boolean, boolean, Term).
|
||||||
@@ -56,6 +57,10 @@ check_(Pred, Type, Term) :-
|
|||||||
|
|
||||||
boolean(B) :- ( B == true ; B == false ).
|
boolean(B) :- ( B == true ; B == false ).
|
||||||
|
|
||||||
|
character(C) :-
|
||||||
|
atom(C),
|
||||||
|
atom_length(C, 1).
|
||||||
|
|
||||||
ilist(V) :- var(V), instantiation_error(must_be/2).
|
ilist(V) :- var(V), instantiation_error(must_be/2).
|
||||||
ilist([]).
|
ilist([]).
|
||||||
ilist([_|Ls]) :- ilist(Ls).
|
ilist([_|Ls]) :- ilist(Ls).
|
||||||
@@ -63,6 +68,7 @@ ilist([_|Ls]) :- ilist(Ls).
|
|||||||
type(type).
|
type(type).
|
||||||
type(integer).
|
type(integer).
|
||||||
type(atom).
|
type(atom).
|
||||||
|
type(character).
|
||||||
type(list).
|
type(list).
|
||||||
type(var).
|
type(var).
|
||||||
type(boolean).
|
type(boolean).
|
||||||
@@ -90,6 +96,7 @@ can_be(Type, Term) :-
|
|||||||
|
|
||||||
can_(integer, Term) :- integer(Term).
|
can_(integer, Term) :- integer(Term).
|
||||||
can_(atom, Term) :- atom(Term).
|
can_(atom, Term) :- atom(Term).
|
||||||
|
can_(character, T) :- character(T).
|
||||||
can_(list, Term) :- list_or_partial_list(Term).
|
can_(list, Term) :- list_or_partial_list(Term).
|
||||||
can_(boolean, Term) :- boolean(Term).
|
can_(boolean, Term) :- boolean(Term).
|
||||||
|
|
||||||
|
|||||||
58
src/lib/os.pl
Normal file
58
src/lib/os.pl
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
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"
|
||||||
|
; false.
|
||||||
|
|
||||||
|
Public domain code.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
:- module(os, [getenv/2,
|
||||||
|
setenv/2,
|
||||||
|
unsetenv/1]).
|
||||||
|
|
||||||
|
:- use_module(library(error)).
|
||||||
|
:- use_module(library(charsio)).
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
|
getenv(Key, Value) :-
|
||||||
|
must_be_env_var(Key),
|
||||||
|
'$getenv'(Key, Value).
|
||||||
|
|
||||||
|
setenv(Key, Value) :-
|
||||||
|
must_be_env_var(Key),
|
||||||
|
must_be_chars(Value),
|
||||||
|
'$setenv'(Key, Value).
|
||||||
|
|
||||||
|
unsetenv(Key) :-
|
||||||
|
must_be_env_var(Key),
|
||||||
|
'$unsetenv'(Key).
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
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).
|
||||||
@@ -32,6 +32,7 @@ use std::net::{TcpListener, TcpStream};
|
|||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use crate::cpu_time::ProcessTime;
|
use crate::cpu_time::ProcessTime;
|
||||||
@@ -5637,6 +5638,28 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::GetEnv => {
|
||||||
|
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
|
||||||
|
match env::var(key) {
|
||||||
|
Ok(value) => {
|
||||||
|
let cstr = self.heap.put_complete_string(&value);
|
||||||
|
self.unify(self[temp_v!(2)], cstr);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&SystemClauseType::SetEnv => {
|
||||||
|
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
|
||||||
|
let value = self.heap_pstr_iter(self[temp_v!(2)]).to_string();
|
||||||
|
env::set_var(key, value);
|
||||||
|
}
|
||||||
|
&SystemClauseType::UnsetEnv => {
|
||||||
|
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
|
||||||
|
env::remove_var(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return_from_clause!(self.last_call, self)
|
return_from_clause!(self.last_call, self)
|
||||||
|
|||||||
Reference in New Issue
Block a user