aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorMarijn Haverbeke <[email protected]>2011-03-11 13:30:18 +0100
committerGraydon Hoare <[email protected]>2011-03-14 14:57:13 -0700
commitea5dc54c3f0444fd3f20191fa1b1d94372c74c65 (patch)
tree0a80b98563553f56962cc956e94210462a9d66e2 /src/lib
parentExtend stream functionality (diff)
downloadrust-ea5dc54c3f0444fd3f20191fa1b1d94372c74c65.tar.xz
rust-ea5dc54c3f0444fd3f20191fa1b1d94372c74c65.zip
Add functionality for running external programs to the std lib
See lib/run_program.rs.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/io.rs19
-rw-r--r--src/lib/linux_os.rs23
-rw-r--r--src/lib/macos_os.rs20
-rw-r--r--src/lib/run_program.rs96
-rw-r--r--src/lib/std.rc4
-rw-r--r--src/lib/win32_os.rs22
6 files changed, 182 insertions, 2 deletions
diff --git a/src/lib/io.rs b/src/lib/io.rs
index 45bdb4a0..7135c2bc 100644
--- a/src/lib/io.rs
+++ b/src/lib/io.rs
@@ -17,6 +17,8 @@ type reader =
impure fn read_bytes(uint len) -> vec[u8];
impure fn read_char() -> int;
impure fn unread_char(int i);
+ impure fn eof() -> bool;
+ impure fn read_line() -> str;
impure fn read_c_str() -> str;
impure fn read_le_uint(uint size) -> uint;
impure fn read_le_int(uint size) -> int;
@@ -31,7 +33,7 @@ state obj FILE_reader(os.libc.FILE f, bool must_close) {
impure fn read_bytes(uint len) -> vec[u8] {
auto buf = _vec.alloc[u8](len);
auto read = os.libc.fread(_vec.buf[u8](buf), 1u, len, f);
- check(read == len);
+ _vec.len_set[u8](buf, read);
ret buf;
}
impure fn read_char() -> int {
@@ -40,6 +42,21 @@ state obj FILE_reader(os.libc.FILE f, bool must_close) {
impure fn unread_char(int ch) {
os.libc.ungetc(ch, f);
}
+ impure fn eof() -> bool {
+ auto ch = os.libc.fgetc(f);
+ if (ch == -1) {ret true;}
+ os.libc.ungetc(ch, f);
+ ret false;
+ }
+ impure fn read_line() -> str {
+ auto buf = "";
+ while (true) {
+ auto ch = os.libc.fgetc(f);
+ if (ch == -1) {break;} if (ch == 10) {break;}
+ buf += _str.unsafe_from_bytes(vec(ch as u8));
+ }
+ ret buf;
+ }
impure fn read_c_str() -> str {
auto buf = "";
while (true) {
diff --git a/src/lib/linux_os.rs b/src/lib/linux_os.rs
index bed8fdbc..6695377d 100644
--- a/src/lib/linux_os.rs
+++ b/src/lib/linux_os.rs
@@ -1,6 +1,9 @@
import _str.sbuf;
import _vec.vbuf;
+// FIXE Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
+// by https://github.com/graydon/rust/issues#issue/268
+
native mod libc = "libc.so.6" {
fn open(sbuf s, int flags, uint mode) -> int;
@@ -10,6 +13,7 @@ native mod libc = "libc.so.6" {
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
+ fn fdopen(int fd, sbuf mode) -> FILE;
fn fclose(FILE f);
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
@@ -25,6 +29,9 @@ native mod libc = "libc.so.6" {
fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
fn unsetenv(sbuf n) -> int;
+
+ fn pipe(vbuf buf) -> int;
+ fn waitpid(int pid, vbuf status, int options) -> int;
}
mod libc_constants {
@@ -50,6 +57,22 @@ fn target_os() -> str {
ret "linux";
}
+fn pipe() -> tup(int, int) {
+ let vec[mutable int] fds = vec(mutable 0, 0);
+ check(os.libc.pipe(_vec.buf[mutable int](fds)) == 0);
+ ret tup(fds.(0), fds.(1));
+}
+
+fn fd_FILE(int fd) -> libc.FILE {
+ ret libc.fdopen(fd, _str.buf("r"));
+}
+
+fn waitpid(int pid) -> int {
+ let vec[mutable int] status = vec(mutable 0);
+ check(os.libc.waitpid(pid, _vec.buf[mutable int](status), 0) != -1);
+ ret status.(0);
+}
+
// Local Variables:
// mode: rust;
// fill-column: 78;
diff --git a/src/lib/macos_os.rs b/src/lib/macos_os.rs
index bacf2d8a..a484f72b 100644
--- a/src/lib/macos_os.rs
+++ b/src/lib/macos_os.rs
@@ -9,6 +9,7 @@ native mod libc = "libc.dylib" {
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
+ fn fdopen(int fd, sbuf mode) -> FILE;
fn fclose(FILE f);
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
@@ -24,6 +25,9 @@ native mod libc = "libc.dylib" {
fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
fn unsetenv(sbuf n) -> int;
+
+ fn pipe(vbuf buf) -> int;
+ fn waitpid(int pid, vbuf status, int options) -> int;
}
mod libc_constants {
@@ -49,6 +53,22 @@ fn target_os() -> str {
ret "macos";
}
+fn pipe() -> tup(int, int) {
+ let vec[mutable int] fds = vec(mutable 0, 0);
+ check(os.libc.pipe(_vec.buf[mutable int](fds)) == 0);
+ ret tup(fds.(0), fds.(1));
+}
+
+fn fd_FILE(int fd) -> libc.FILE {
+ ret libc.fdopen(fd, _str.buf("r"));
+}
+
+fn waitpid(int pid) -> int {
+ let vec[mutable int] status = vec(mutable 0);
+ check(os.libc.waitpid(pid, _vec.buf[mutable int](status), 0) != -1);
+ ret status.(0);
+}
+
// Local Variables:
// mode: rust;
// fill-column: 78;
diff --git a/src/lib/run_program.rs b/src/lib/run_program.rs
new file mode 100644
index 00000000..bd9edbc8
--- /dev/null
+++ b/src/lib/run_program.rs
@@ -0,0 +1,96 @@
+import _str.sbuf;
+import _vec.vbuf;
+
+native "rust" mod rustrt {
+ fn rust_run_program(vbuf argv, int in_fd, int out_fd, int err_fd) -> int;
+}
+
+fn argvec(str prog, vec[str] args) -> vec[sbuf] {
+ auto argptrs = vec(_str.buf(prog));
+ for (str arg in args) {
+ argptrs = _vec.push[sbuf](argptrs, _str.buf(arg));
+ }
+ argptrs = _vec.push[sbuf](argptrs, 0 as sbuf);
+ ret argptrs;
+}
+
+impure fn run_program(str prog, vec[str] args) -> int {
+ auto pid = rustrt.rust_run_program(_vec.buf[sbuf](argvec(prog, args)),
+ 0, 0, 0);
+ ret os.waitpid(pid);
+}
+
+type program =
+ state obj {
+ fn get_id() -> int;
+ fn input() -> io.writer;
+ fn output() -> io.reader;
+ impure fn close_input();
+ impure fn finish() -> int;
+ };
+
+impure fn start_program(str prog, vec[str] args) -> @program {
+ auto pipe_input = os.pipe();
+ auto pipe_output = os.pipe();
+ auto pid = rustrt.rust_run_program
+ (_vec.buf[sbuf](argvec(prog, args)),
+ pipe_input._0, pipe_output._1, 0);
+ if (pid == -1) {fail;}
+ os.libc.close(pipe_input._0);
+ os.libc.close(pipe_output._1);
+
+ state obj new_program(int pid,
+ int in_fd,
+ os.libc.FILE out_file,
+ mutable bool finished) {
+ fn get_id() -> int {ret pid;}
+ fn input() -> io.writer {
+ ret io.new_writer(io.fd_buf_writer(in_fd, false));
+ }
+ fn output() -> io.reader {
+ ret io.FILE_reader(out_file, false);
+ }
+ impure fn close_input() {
+ os.libc.close(in_fd);
+ }
+ impure fn finish() -> int {
+ if (finished) {ret 0;}
+ finished = true;
+ os.libc.close(in_fd);
+ ret os.waitpid(pid);
+ }
+ drop {
+ if (!finished) {
+ os.libc.close(in_fd);
+ os.waitpid(pid);
+ }
+ os.libc.fclose(out_file);
+ }
+ }
+ ret @new_program(pid, pipe_input._1,
+ os.fd_FILE(pipe_output._0),
+ false);
+}
+
+impure fn program_output(str prog, vec[str] args)
+ -> rec(int status, str out) {
+ auto pr = start_program(prog, args);
+ pr.close_input();
+ auto out = pr.output();
+ auto buf = "";
+ while (!out.eof()) {
+ auto bytes = out.read_bytes(4096u);
+ buf += _str.unsafe_from_bytes(bytes);
+ }
+ ret rec(status=pr.finish(), out=buf);
+}
+
+
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
diff --git a/src/lib/std.rc b/src/lib/std.rc
index 8098a4e9..a339fd85 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -27,7 +27,9 @@ mod util;
auth io = unsafe;
auth fs = unsafe;
+auth os = unsafe;
auth os_fs = unsafe;
+auth run = unsafe;
auth _str = unsafe;
auth _vec = unsafe;
auth _task = unsafe;
@@ -52,9 +54,9 @@ alt (target_os) {
mod os_fs = "posix_fs.rs";
}
}
+mod run = "run_program.rs";
mod fs;
-
// FIXME: parametric
mod map;
mod deque;
diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs
index 1c037c77..56c65bfc 100644
--- a/src/lib/win32_os.rs
+++ b/src/lib/win32_os.rs
@@ -9,11 +9,14 @@ native mod libc = "msvcrt.dll" {
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
+ fn _fdopen(int fd, sbuf mode) -> FILE;
fn fclose(FILE f);
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
+
+ fn _pipe(vbuf fds, uint size, int mode) -> int;
}
mod libc_constants {
@@ -39,6 +42,25 @@ fn target_os() -> str {
ret "win32";
}
+fn pipe() -> tup(int, int) {
+ let vec[mutable int] fds = vec(mutable 0, 0);
+ check(os.libc._pipe(_vec.buf[mutable int](fds), 1024u,
+ libc_constants.O_BINARY()) == 0);
+ ret tup(fds.(0), fds.(1));
+}
+
+fn fd_FILE(int fd) -> libc.FILE {
+ ret libc._fdopen(fd, _str.buf("r"));
+}
+
+native "rust" mod rustrt {
+ fn rust_process_wait(int handle) -> int;
+}
+
+fn waitpid(int pid) -> int {
+ ret rustrt.rust_process_wait(pid);
+}
+
// Local Variables:
// mode: rust;
// fill-column: 78;