summaryrefslogtreecommitdiff
path: root/std/process.zc
diff options
context:
space:
mode:
Diffstat (limited to 'std/process.zc')
-rw-r--r--std/process.zc136
1 files changed, 136 insertions, 0 deletions
diff --git a/std/process.zc b/std/process.zc
new file mode 100644
index 0000000..3ce43b6
--- /dev/null
+++ b/std/process.zc
@@ -0,0 +1,136 @@
+
+import "./core.zc";
+import "./vec.zc";
+import "./mem.zc";
+import "./string.zc";
+import "./option.zc";
+
+include <stdio.h>
+include <stdlib.h>
+
+// system() can be externed directly with const char*
+extern fn system(command: const char*) -> int;
+
+// Minimal raw block: only for opaque FILE* types
+// popen/pclose/fgets use FILE* which conflicts with void*
+raw {
+ void *_z_popen(const char *command, const char *type) {
+ return (void *)popen(command, type);
+ }
+
+ int _z_pclose(void *stream) {
+ return pclose((FILE *)stream);
+ }
+
+ char *_z_fgets(char *s, int size, void *stream) {
+ return fgets(s, size, (FILE *)stream);
+ }
+}
+
+extern fn _z_popen(command: const char*, type: const char*) -> void*;
+extern fn _z_pclose(stream: void*) -> int;
+extern fn _z_fgets(s: char*, size: int, stream: void*) -> char*;
+
+struct Output {
+ stdout: String;
+ exit_code: int;
+}
+
+struct Command {
+ program: String;
+ args: Vec<String>;
+}
+
+impl Command {
+ fn new(program: char*) -> Command {
+ return Command {
+ program: String::from(program),
+ args: Vec<String>::new()
+ };
+ }
+
+ fn arg(self, arg: char*) -> Command* {
+ self.args.push(String::from(arg));
+ return self;
+ }
+
+ fn _build_cmd(self) -> String {
+ let cmd_str = self.program.substring(0, self.program.length());
+
+ for arg in &self.args {
+ let space = String::from(" ");
+ cmd_str.append(&space);
+ space.free();
+
+ cmd_str.append(arg);
+ }
+
+ return cmd_str;
+ }
+
+ fn output(self) -> Output {
+ let cmd_str = self._build_cmd();
+ let cmd_c = cmd_str.c_str();
+
+ let fp = _z_popen(cmd_c, "r");
+
+ if (fp == 0) {
+ cmd_str.free();
+ // TODO: Better error handling...
+ return Output {
+ stdout: String::from(""),
+ exit_code: -1
+ };
+ }
+
+ let out = String::from("");
+ let buf_size: usize = 1024;
+ let buf = (char*)malloc(buf_size);
+
+ while (true) {
+ let res = _z_fgets(buf, (int)buf_size, fp);
+ if (res == 0) break;
+
+ let chunk = String::from(buf);
+ out.append(&chunk);
+ chunk.free();
+ }
+
+ let code = _z_pclose(fp);
+ free(buf);
+ cmd_str.free();
+
+ return Output {
+ stdout: out,
+ exit_code: code
+ };
+ }
+
+ fn status(self) -> int {
+ let cmd_str = self._build_cmd();
+ let code = system(cmd_str.c_str());
+ cmd_str.free();
+ return code;
+ }
+
+ fn free(self) {
+ self.program.free();
+
+ for s in &self.args {
+ s.free();
+ }
+ self.args.free();
+ }
+}
+
+impl Drop for Command {
+ fn drop(self) {
+ self.free();
+ }
+}
+
+impl Drop for Output {
+ fn drop(self) {
+ self.stdout.free();
+ }
+}