GetEnv,
SetEnv,
UnsetEnv,
+ Shell,
PID,
CharsBase64,
DevourWhitespace,
&SystemClauseType::GetEnv => clause_name!("$getenv"),
&SystemClauseType::SetEnv => clause_name!("$setenv"),
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
+ &SystemClauseType::Shell => clause_name!("$shell"),
&SystemClauseType::PID => clause_name!("$pid"),
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
&SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"),
("$getenv", 2) => Some(SystemClauseType::GetEnv),
("$setenv", 2) => Some(SystemClauseType::SetEnv),
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
+ ("$shell", 2) => Some(SystemClauseType::Shell),
("$pid", 1) => Some(SystemClauseType::PID),
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
("$load_library_as_stream", 3) => Some(SystemClauseType::LoadLibraryAsStream),
:- module(os, [getenv/2,
setenv/2,
unsetenv/1,
+ shell/1,
+ shell/2,
pid/1]).
:- use_module(library(error)).
must_be_env_var(Key),
'$unsetenv'(Key).
+shell(Command) :- shell(Command, 0).
+shell(Command, Status) :-
+ '$shell'(Command, Status).
+
pid(PID) :-
can_be(integer, PID),
- '$pid'(PID).
+ '$pid'(PID).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
For now, we only support a restricted subset of variable names.
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
env::remove_var(key);
}
+ &SystemClauseType::Shell => {
+ // shell executes a command in a system shell
+ // the code looks for a SHELL env var to do it in a UNIX-style
+ // if not found, the code looks for COMSPEC env var to do it in a DOS-style
+ // the output is printed directly to stdout
+ // the output status code is returned after finishing
+ fn command_result(machine: &mut MachineState, command: std::io::Result<process::ExitStatus>) {
+ match command {
+ Ok(status) => {
+ match status.code() {
+ Some(code) => {
+ let addr = machine.heap.put_constant(Constant::Integer(Rc::new(Integer::from(code))));
+ (machine.unify_fn)(machine, machine[temp_v!(2)], addr);
+ }
+ _ => {
+ machine.fail = true;
+ }
+ }
+ }
+ _ => {
+ machine.fail = true;
+ }
+ }
+ }
+
+ let command = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
+ match env::var("SHELL") {
+ Ok(value) => {
+ let command = process::Command::new(&value)
+ .arg("-c")
+ .arg(command)
+ .status();
+ command_result(self, command);
+ }
+ _ => {
+ match env::var("COMSPEC") {
+ Ok(value) => {
+ let command = process::Command::new(&value)
+ .arg("/C")
+ .arg(command)
+ .status();
+ command_result(self, command);
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
+ };
+ }
&SystemClauseType::PID => {
let a1 = self[temp_v!(1)];
let pid = process::id();