add native functions of subprocess

This commit is contained in:
ValKmjolnir 2024-06-10 00:30:30 +08:00
parent 7e3c6d06b2
commit d48c9f44e8
5 changed files with 146 additions and 33 deletions

View File

@ -60,7 +60,9 @@ private:
"__pipe", "__fork", "__waitpid", "__chdir", "__pipe", "__fork", "__waitpid", "__chdir",
"__environ", "__getcwd", "__getenv", "__environ", "__getcwd", "__getenv",
// subprocess // subprocess
"__subprocess_run" "__subprocess_popen",
"__subprocess_pclose",
"__subprocess_read_stdout"
}; };
// file mapper for file -> index // file mapper for file -> index

View File

@ -1,13 +1,62 @@
#include "natives/subprocess.h" #include "natives/subprocess.h"
#include <cstdio>
namespace nasal { namespace nasal {
var builtin_subprocess_run(context* ctx, gc* ngc) { const auto subprocess_object_name = "subprocess";
return nil;
void subprocess_destructor(void* ptr) {
pclose(static_cast<FILE*>(ptr));
}
var builtin_subprocess_popen(context* ctx, gc* ngc) {
auto command = ctx->localr[1];
if (!command.is_str()) {
return nas_err("subprocess::popen", "expect a string as the command");
}
auto fd = popen(command.str().c_str(), "r");
if (fd == nullptr) {
return nas_err("subprocess::popen", "failed to create sub-process");
}
var ret = ngc->alloc(vm_type::vm_ghost);
ret.ghost().set(subprocess_object_name, subprocess_destructor, nullptr, fd);
return ret;
}
var builtin_subprocess_pclose(context* ctx, gc* ngc) {
auto fd = ctx->localr[1];
if (!fd.object_check(subprocess_object_name)) {
return nas_err("subprocess::pclose", "not a valid subprocess");
}
auto res = pclose(static_cast<FILE*>(fd.ghost().pointer));
fd.ghost().pointer = nullptr;
fd.ghost().clear();
return var::num(res);
}
var builtin_subprocess_read_stdout(context* ctx, gc* ngc) {
auto fd = ctx->localr[1];
if (!fd.object_check(subprocess_object_name)) {
return nas_err("subprocess::pclose", "not a valid subprocess");
}
char buffer[1025];
auto res = ngc->alloc(vm_type::vm_str);
while(fgets(
buffer,
sizeof(buffer)-1,
static_cast<FILE*>(fd.ghost().pointer))!=nullptr) {
res.str() += buffer;
}
return res;
} }
nasal_builtin_table subprocess_native[] = { nasal_builtin_table subprocess_native[] = {
{"__subprocess_run", builtin_subprocess_run}, {"__subprocess_popen", builtin_subprocess_popen},
{"__subprocess_pclose", builtin_subprocess_pclose},
{"__subprocess_read_stdout", builtin_subprocess_read_stdout},
{nullptr, nullptr} {nullptr, nullptr}
}; };

View File

@ -6,8 +6,11 @@
namespace nasal { namespace nasal {
var builtin_subprocess_run(context*, gc*); void subprocess_destructor(void*);
var builtin_subprocess_popen(context*, gc*);
var builtin_subprocess_pclose(context*, gc*);
var builtin_subprocess_read_stdout(context*, gc*);
extern nasal_builtin_table subprocess_native[]; extern nasal_builtin_table subprocess_native[];
} }

View File

@ -1,3 +1,11 @@
var run = func() { var popen = func(cmd) {
return __subprocess_run(); return __subprocess_popen(cmd);
}
var pclose = func(subproc) {
return __subprocess_pclose(subproc);
}
var read = func(subproc) {
return __subprocess_read_stdout(subproc);
} }

View File

@ -3,62 +3,113 @@ use std.os;
use std.io; use std.io;
use std.unix; use std.unix;
use std.subprocess;
runtime.windows.set_utf8_output();
var os_time = func() { var os_time = func() {
return "\e[33;1m["~os.time()~"]\e[0m "; return "\e[33;1m[" ~ os.time() ~ "]\e[0m ";
} }
var err_hd = func() { var err_hd = func() {
return "\e[91;1m[error]\e[0m "; return "\e[91;1m[error]\e[0m ";
} }
var info_hd = func() { var info_hd = func() {
return "\e[96;1m[info]\e[0m "; return "\e[96;1m[info]\e[0m ";
} }
var modified_hd = func() { var modified_hd = func() {
return "\e[92;1m[modified]\e[0m "; return "\e[92;1m[modified]\e[0m ";
} }
var usage = func() { var usage = func() {
println(os_time(),info_hd(),"\e[1musage: nasal watchdog.nas <filename> [\"argv\"]\e[0m"); println(
os_time(),
info_hd(),
"\e[1musage: nasal watchdog.nas <filename> [\"argv\"]\e[0m"
);
} }
var argv=runtime.argv(); var argv = runtime.argv();
if (size(argv)<1) { if (size(argv)<1) {
println(os_time(),err_hd(),"\e[1mneed correct file path to watch\e[0m"); println(
usage(); os_time(),
exit(-1); err_hd(),
} "\e[1mneed correct file path to watch\e[0m"
var filename=argv[0]; );
if (!io.exists(filename)) {
println(os_time(),err_hd(),"\e[1mfile <",filename,"> does not exist\e[0m");
usage(); usage();
exit(-1); exit(-1);
} }
var args=[]; var filename = argv[0];
if (!io.exists(filename)) {
println(
os_time(),
err_hd(),
"\e[1mfile <",
filename,
"> does not exist\e[0m"
);
usage();
exit(-1);
}
var args = [];
if (size(argv)==2) { if (size(argv)==2) {
println(os_time(),info_hd(),"\e[1mwith argument(s) ",argv[1],"\e[0m"); println(
args=split(" ",argv[1]); os_time(),
info_hd(),
"\e[1mwith argument(s) ",
argv[1],
"\e[0m"
);
args = split(" ", argv[1]);
} }
var modified_time = io.fstat(filename).st_mtime; var modified_time = io.fstat(filename).st_mtime;
println(os_time(),info_hd(),"\e[1mwatching ",filename," ..\e[0m"); println(os_time(), info_hd(), "\e[1mwatching ", filename, " ..\e[0m");
while(1) { while(1) {
unix.sleep(5); unix.sleep(5);
if (!io.exists(filename)) { if (!io.exists(filename)) {
println(os_time(),err_hd(),"\e[1mfile <",filename,"> does not exist\e[0m"); println(
os_time(),
err_hd(),
"\e[1mfile <",
filename,
"> does not exist\e[0m"
);
break; break;
} }
var latest_modified_time = io.fstat(filename).st_mtime; var latest_modified_time = io.fstat(filename).st_mtime;
if (latest_modified_time!=modified_time) { if (latest_modified_time!=modified_time) {
modified_time=latest_modified_time; modified_time = latest_modified_time;
println(os_time(),modified_hd(),"\e[1m",filename,"\e[0m"); println(os_time(), modified_hd(), "\e[1m", filename, "\e[0m");
var cmd=(os.platform()=="windows"?"":"./")~"nasal "~filename;
foreach(var i;args) var cmd = (os.platform()=="windows"?"":"./") ~ "nasal " ~ filename;
cmd~=" "~i; foreach(var i; args) {
println(os_time(),info_hd(),"\e[1mexecuting command \"",cmd,"\"\e[0m"); cmd ~= " " ~ i;
var ret=system(cmd);
if (ret!=0) {
println(os_time(),err_hd(),"\e[1mprocess returned ",ret,"\e[0m");
} else {
println(os_time(),info_hd(),"\e[1mprocess returned ",ret,"\e[0m");
} }
cmd ~= " 2>&1";
println(
os_time(),
info_hd(),
"\e[1mexecuting command \"",
cmd,
"\"\e[0m"
);
var subproc = subprocess.popen(cmd);
var stdout_info = subprocess.read(subproc);
var ret = subprocess.pclose(subproc);
if (size(stdout_info)>0) {
println(stdout_info);
}
println(
os_time(),
ret!=0? err_hd():info_hd(),
"\e[1mprocess returned " ~ ret ~ "\e[0m"
);
} }
} }