Together with library(files), this addresses #511.
Predicates for opening and accepting TCP connections as streams.
TLS negotiation is performed via the option `tls(true)` in
`socket_client_open/3`, yielding secure encrypted connections.
+* [`os`](src/lib/os.pl)
+ Predicates for reasoning about environment variables.
* [`crypto`](src/lib/crypto.pl)
Cryptographically secure random numbers and hashes, HMAC-based
key derivation (HKDF), password-based key derivation (PBKDF2),
Ed25519KeyPairPublicKey,
LoadHTML,
LoadXML,
+ GetEnv,
+ SetEnv,
+ UnsetEnv,
}
impl SystemClauseType {
&SystemClauseType::Ed25519KeyPairPublicKey => clause_name!("$ed25519_keypair_public_key"),
&SystemClauseType::LoadHTML => clause_name!("$load_html"),
&SystemClauseType::LoadXML => clause_name!("$load_xml"),
+ &SystemClauseType::GetEnv => clause_name!("$getenv"),
+ &SystemClauseType::SetEnv => clause_name!("$setenv"),
+ &SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
}
}
("$ed25519_keypair_public_key", 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
("$load_html", 3) => Some(SystemClauseType::LoadHTML),
("$load_xml", 3) => Some(SystemClauseType::LoadXML),
+ ("$getenv", 2) => Some(SystemClauseType::GetEnv),
+ ("$setenv", 2) => Some(SystemClauseType::SetEnv),
+ ("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
_ => None,
}
}
).
must_be_(integer, Term) :- check_(integer, integer, 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_(type, Term) :- check_(type, type, Term).
must_be_(boolean, Term) :- check_(boolean, boolean, Term).
boolean(B) :- ( B == true ; B == false ).
+character(C) :-
+ atom(C),
+ atom_length(C, 1).
+
ilist(V) :- var(V), instantiation_error(must_be/2).
ilist([]).
ilist([_|Ls]) :- ilist(Ls).
type(type).
type(integer).
type(atom).
+type(character).
type(list).
type(var).
type(boolean).
can_(integer, Term) :- integer(Term).
can_(atom, Term) :- atom(Term).
+can_(character, T) :- character(T).
can_(list, Term) :- list_or_partial_list(Term).
can_(boolean, Term) :- boolean(Term).
--- /dev/null
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ Predicates for reasoning about the operating system (OS) environment.
+
+ 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).
use std::ops::Sub;
use std::rc::Rc;
use std::num::NonZeroU32;
+use std::env;
use std::time::{Duration, SystemTime};
use crate::cpu_time::ProcessTime;
}
}
}
+ &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)