Merge pull request #1052 from aarroyoc/shell-predicate
Implement shell/1 and shell/2
This commit is contained in:
@@ -301,6 +301,7 @@ pub(crate) enum SystemClauseType {
|
|||||||
GetEnv,
|
GetEnv,
|
||||||
SetEnv,
|
SetEnv,
|
||||||
UnsetEnv,
|
UnsetEnv,
|
||||||
|
Shell,
|
||||||
PID,
|
PID,
|
||||||
CharsBase64,
|
CharsBase64,
|
||||||
DevourWhitespace,
|
DevourWhitespace,
|
||||||
@@ -592,6 +593,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::GetEnv => clause_name!("$getenv"),
|
&SystemClauseType::GetEnv => clause_name!("$getenv"),
|
||||||
&SystemClauseType::SetEnv => clause_name!("$setenv"),
|
&SystemClauseType::SetEnv => clause_name!("$setenv"),
|
||||||
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
|
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
|
||||||
|
&SystemClauseType::Shell => clause_name!("$shell"),
|
||||||
&SystemClauseType::PID => clause_name!("$pid"),
|
&SystemClauseType::PID => clause_name!("$pid"),
|
||||||
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
|
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
|
||||||
&SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"),
|
&SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"),
|
||||||
@@ -813,6 +815,7 @@ impl SystemClauseType {
|
|||||||
("$getenv", 2) => Some(SystemClauseType::GetEnv),
|
("$getenv", 2) => Some(SystemClauseType::GetEnv),
|
||||||
("$setenv", 2) => Some(SystemClauseType::SetEnv),
|
("$setenv", 2) => Some(SystemClauseType::SetEnv),
|
||||||
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
|
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
|
||||||
|
("$shell", 2) => Some(SystemClauseType::Shell),
|
||||||
("$pid", 1) => Some(SystemClauseType::PID),
|
("$pid", 1) => Some(SystemClauseType::PID),
|
||||||
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
|
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
|
||||||
("$load_library_as_stream", 3) => Some(SystemClauseType::LoadLibraryAsStream),
|
("$load_library_as_stream", 3) => Some(SystemClauseType::LoadLibraryAsStream),
|
||||||
|
|||||||
@@ -15,11 +15,14 @@
|
|||||||
:- module(os, [getenv/2,
|
:- module(os, [getenv/2,
|
||||||
setenv/2,
|
setenv/2,
|
||||||
unsetenv/1,
|
unsetenv/1,
|
||||||
|
shell/1,
|
||||||
|
shell/2,
|
||||||
pid/1]).
|
pid/1]).
|
||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
:- use_module(library(charsio)).
|
:- use_module(library(charsio)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
|
:- use_module(library(si)).
|
||||||
|
|
||||||
getenv(Key, Value) :-
|
getenv(Key, Value) :-
|
||||||
must_be_env_var(Key),
|
must_be_env_var(Key),
|
||||||
@@ -34,6 +37,12 @@ unsetenv(Key) :-
|
|||||||
must_be_env_var(Key),
|
must_be_env_var(Key),
|
||||||
'$unsetenv'(Key).
|
'$unsetenv'(Key).
|
||||||
|
|
||||||
|
shell(Command) :- shell(Command, 0).
|
||||||
|
shell(Command, Status) :-
|
||||||
|
must_be_chars(Command),
|
||||||
|
can_be(integer, Status),
|
||||||
|
'$shell'(Command, Status).
|
||||||
|
|
||||||
pid(PID) :-
|
pid(PID) :-
|
||||||
can_be(integer, PID),
|
can_be(integer, PID),
|
||||||
'$pid'(PID).
|
'$pid'(PID).
|
||||||
|
|||||||
@@ -5382,6 +5382,56 @@ impl MachineState {
|
|||||||
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
|
let key = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
|
||||||
env::remove_var(key);
|
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 => {
|
&SystemClauseType::PID => {
|
||||||
let a1 = self[temp_v!(1)];
|
let a1 = self[temp_v!(1)];
|
||||||
let pid = process::id();
|
let pid = process::id();
|
||||||
|
|||||||
Reference in New Issue
Block a user