Skip to content

Commit

Permalink
WIP: proof of concept for stdout() and stderr() functions to open str…
Browse files Browse the repository at this point in the history
…eams
  • Loading branch information
schodet committed Jun 16, 2017
1 parent 6d79132 commit 6deed40
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 24 deletions.
68 changes: 44 additions & 24 deletions src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,105 @@
use core::{fmt, slice};
use core::fmt::Write;

/// File descriptors
const STDOUT: usize = 1;
const STDERR: usize = 2;
use nr;

/// Host's standard error
struct Stderr;
pub struct Stderr {
fd: usize,
}

/// Construct a new handle to the host's standard error.
pub fn stderr() -> Stderr {
Stderr { fd: open(":tt\0", nr::open::W_APPEND).unwrap() }
}

/// Host's standard output
struct Stdout;
pub struct Stdout {
fd: usize,
}

/// Construct a new handle to the host's standard output.
pub fn stdout() -> Stdout {
Stdout { fd: open(":tt\0", nr::open::W_TRUNC).unwrap() }
}

fn open(name: &str, mode: usize) -> Result<usize, ()> {
let name = name.as_bytes();
match unsafe { syscall!(OPEN, name.as_ptr(), mode, name.len() - 1) } as isize {
-1 => Err(()),
fd => Ok(fd as usize),
}
}

fn write_all(fd: usize, mut buffer: &[u8]) {
fn write_all(fd: usize, mut buffer: &[u8]) -> fmt::Result {
while !buffer.is_empty() {
match unsafe { syscall!(WRITE, fd, buffer.as_ptr(), buffer.len()) } {
// Done
0 => return,
0 => return Ok(()),
// `n` bytes were not written
n => {
n if n <= buffer.len() => {
let offset = (buffer.len() - n) as isize;
buffer = unsafe {
slice::from_raw_parts(buffer.as_ptr().offset(offset as isize), n)
slice::from_raw_parts(buffer.as_ptr().offset(offset), n)
}
}
// Error
_ => return Err(fmt::Error::default()),
}
}
Ok(())
}

impl Stderr {
fn write_all(&mut self, buffer: &[u8]) {
write_all(STDERR, buffer);
fn write_all(&mut self, buffer: &[u8]) -> fmt::Result {
write_all(self.fd, buffer)
}
}

impl Stdout {
fn write_all(&mut self, buffer: &[u8]) {
write_all(STDOUT, buffer);
fn write_all(&mut self, buffer: &[u8]) -> fmt::Result {
write_all(self.fd, buffer)
}
}

impl Write for Stderr {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_all(s.as_bytes());
Ok(())
self.write_all(s.as_bytes())
}
}

impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_all(s.as_bytes());
Ok(())
self.write_all(s.as_bytes())
}
}

/// Write a `buffer` to the host's stderr
pub fn ewrite(buffer: &[u8]) {
Stderr.write_all(buffer)
stderr().write_all(buffer).ok();
}

/// Write `fmt::Arguments` to the host's stderr
pub fn ewrite_fmt(args: fmt::Arguments) {
Stderr.write_fmt(args).ok();
stderr().write_fmt(args).ok();
}

/// Write a `string` to the host's stderr
pub fn ewrite_str(string: &str) {
Stderr.write_all(string.as_bytes())
stderr().write_all(string.as_bytes()).ok();
}

/// Write a `buffer` to the host's stdout
pub fn write(buffer: &[u8]) {
Stdout.write_all(buffer)
stdout().write_all(buffer).ok();
}

/// Write `fmt::Arguments` to the host's stdout
pub fn write_fmt(args: fmt::Arguments) {
Stdout.write_fmt(args).ok();
stdout().write_fmt(args).ok();
}

/// Write a `string` to the host's stdout
pub fn write_str(string: &str) {
Stdout.write_all(string.as_bytes())
stdout().write_all(string.as_bytes()).ok();
}
15 changes: 15 additions & 0 deletions src/nr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,18 @@ pub const WRITE: usize = 0x05;
pub const WRITEC: usize = 0x03;
pub const ENTER_SVC: usize = 0x17;
pub const REPORT_EXCEPTION: usize = 0x18;

pub mod open {
pub const R: usize = 0;
pub const R_TEXT: usize = 1;
pub const RW: usize = 2;
pub const RW_TEXT: usize = 3;
pub const W_TRUNC: usize = 4;
pub const W_TRUNC_TEXT: usize = 5;
pub const RW_TRUNC: usize = 6;
pub const RW_TRUNC_TEXT: usize = 7;
pub const W_APPEND: usize = 8;
pub const W_APPEND_TEXT: usize = 9;
pub const RW_APPEND: usize = 10;
pub const RW_APPEND_TEXT: usize = 11;
}

0 comments on commit 6deed40

Please sign in to comment.