Skip to content

Commit

Permalink
Update to new system calls and enviromental variables
Browse files Browse the repository at this point in the history
  • Loading branch information
jackpot51 authored and jD91mZM2 committed Oct 18, 2018
1 parent 40123a1 commit 8d2af4a
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Expand Up @@ -10,7 +10,7 @@
url = https://github.com/rust-lang/rust-installer.git
[submodule "src/liblibc"]
path = src/liblibc
url = https://github.com/rust-lang/libc.git
url = https://gitlab.redox-os.org/redox-os/liblibc.git
[submodule "src/doc/nomicon"]
path = src/doc/nomicon
url = https://github.com/rust-lang-nursery/nomicon.git
Expand Down
23 changes: 23 additions & 0 deletions src/libstd/sys/redox/mod.rs
Expand Up @@ -75,6 +75,29 @@ pub fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
result.map_err(|err| io::Error::from_raw_os_error(err.errno))
}

#[doc(hidden)]
pub trait IsMinusOne {
fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
($($t:ident)*) => ($(impl IsMinusOne for $t {
fn is_minus_one(&self) -> bool {
*self == -1
}
})*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

pub fn cvt_libc<T: IsMinusOne>(t: T) -> io::Result<T> {
if t.is_minus_one() {
Err(io::Error::last_os_error())
} else {
Ok(t)
}
}

/// On Redox, use an illegal instruction to abort
pub unsafe fn abort_internal() -> ! {
::core::intrinsics::abort();
Expand Down
101 changes: 68 additions & 33 deletions src/libstd/sys/redox/os.rs
Expand Up @@ -12,10 +12,12 @@

#![allow(unused_imports)] // lots of cfg code here

use libc::{self, c_char};

use os::unix::prelude::*;

use error::Error as StdError;
use ffi::{OsString, OsStr};
use ffi::{CStr, CString, OsStr, OsString};
use fmt;
use io::{self, Read, Write};
use iter;
Expand All @@ -27,7 +29,7 @@ use ptr;
use slice;
use str;
use sys_common::mutex::Mutex;
use sys::{cvt, fd, syscall};
use sys::{cvt, cvt_libc, fd, syscall};
use vec;

extern {
Expand Down Expand Up @@ -129,6 +131,8 @@ pub fn current_exe() -> io::Result<PathBuf> {
Ok(PathBuf::from(path))
}

pub static ENV_LOCK: Mutex = Mutex::new();

pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
Expand All @@ -140,52 +144,83 @@ impl Iterator for Env {
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

pub unsafe fn environ() -> *mut *const *const c_char {
extern { static mut environ: *const *const c_char; }
&mut environ
}

/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
pub fn env() -> Env {
let mut variables: Vec<(OsString, OsString)> = Vec::new();
if let Ok(mut file) = ::fs::File::open("env:") {
let mut string = String::new();
if file.read_to_string(&mut string).is_ok() {
for line in string.lines() {
let mut parts = line.splitn(2, '=');
if let Some(name) = parts.next() {
let value = parts.next().unwrap_or("");
variables.push((OsString::from(name.to_string()),
OsString::from(value.to_string())));
}
unsafe {
let _guard = ENV_LOCK.lock();
let mut environ = *environ();
if environ == ptr::null() {
panic!("os::env() failure getting env string from OS: {}",
io::Error::last_os_error());
}
let mut result = Vec::new();
while *environ != ptr::null() {
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
result.push(key_value);
}
environ = environ.offset(1);
}
return Env {
iter: result.into_iter(),
_dont_send_or_sync_me: PhantomData,
}
}

fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
// Strategy (copied from glibc): Variable name and value are separated
// by an ASCII equals sign '='. Since a variable name must not be
// empty, allow variable names starting with an equals sign. Skip all
// malformed lines.
if input.is_empty() {
return None;
}
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
pos.map(|p| (
OsStringExt::from_vec(input[..p].to_vec()),
OsStringExt::from_vec(input[p+1..].to_vec()),
))
}
Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData }
}

pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> {
if ! key.is_empty() {
if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) {
let mut string = String::new();
file.read_to_string(&mut string)?;
Ok(Some(OsString::from(string)))
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
let k = CString::new(k.as_bytes())?;
unsafe {
let _guard = ENV_LOCK.lock();
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
let ret = if s.is_null() {
None
} else {
Ok(None)
}
} else {
Ok(None)
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
};
Ok(ret)
}
}

pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> {
if ! key.is_empty() {
let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?;
file.write_all(value.as_bytes())?;
file.set_len(value.len() as u64)?;
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
let k = CString::new(k.as_bytes())?;
let v = CString::new(v.as_bytes())?;

unsafe {
let _guard = ENV_LOCK.lock();
cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
}
Ok(())
}

pub fn unsetenv(key: &OsStr) -> io::Result<()> {
::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?;
Ok(())
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
let nbuf = CString::new(n.as_bytes())?;

unsafe {
let _guard = ENV_LOCK.lock();
cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
}
}

pub fn page_size() -> usize {
Expand Down
41 changes: 28 additions & 13 deletions src/libstd/sys/redox/process.rs
Expand Up @@ -9,15 +9,17 @@
// except according to those terms.

use env::{split_paths};
use ffi::OsStr;
use ffi::{CStr, OsStr};
use os::unix::ffi::OsStrExt;
use fmt;
use io::{self, Error, ErrorKind};
use iter;
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
use path::{Path, PathBuf};
use ptr;
use sys::fd::FileDesc;
use sys::fs::{File, OpenOptions};
use sys::os::{ENV_LOCK, environ};
use sys::pipe::{self, AnonPipe};
use sys::{cvt, syscall};
use sys_common::process::{CommandEnv, DefaultEnvKey};
Expand Down Expand Up @@ -297,12 +299,6 @@ impl Command {
t!(callback());
}

let args: Vec<[usize; 2]> = iter::once(
[self.program.as_ptr() as usize, self.program.len()]
).chain(
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
).collect();

self.env.apply();

let program = if self.program.contains(':') || self.program.contains('/') {
Expand All @@ -321,14 +317,33 @@ impl Command {
None
};

if let Some(program) = program {
if let Err(err) = syscall::execve(program.as_os_str().as_bytes(), &args) {
io::Error::from_raw_os_error(err.errno as i32)
} else {
panic!("return from exec without err");
let fd = if let Some(program) = program {
t!(cvt(syscall::open(program.as_os_str().as_bytes(), syscall::O_RDONLY)))
} else {
return io::Error::from_raw_os_error(syscall::ENOENT);
};

let mut args: Vec<[usize; 2]> = iter::once(
[self.program.as_ptr() as usize, self.program.len()]
).chain(
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
).collect();

let mut vars: Vec<[usize; 2]> = Vec::new();
unsafe {
let _guard = ENV_LOCK.lock();
let mut environ = *environ();
while *environ != ptr::null() {
let var = CStr::from_ptr(*environ).to_bytes();
vars.push([var.as_ptr() as usize, var.len()]);
environ = environ.offset(1);
}
}

if let Err(err) = syscall::fexec(fd, &args, &vars) {
io::Error::from_raw_os_error(err.errno as i32)
} else {
io::Error::from_raw_os_error(syscall::ENOENT)
panic!("return from exec without err");
}
}

Expand Down
13 changes: 4 additions & 9 deletions src/libstd/sys/redox/syscall/call.rs
Expand Up @@ -82,12 +82,6 @@ pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
}

/// Replace the current process with a new executable
pub fn execve<T: AsRef<[u8]>>(path: T, args: &[[usize; 2]]) -> Result<usize> {
unsafe { syscall4(SYS_EXECVE, path.as_ref().as_ptr() as usize,
path.as_ref().len(), args.as_ptr() as usize, args.len()) }
}

/// Exit the current process
pub fn exit(status: usize) -> Result<usize> {
unsafe { syscall1(SYS_EXIT, status) }
Expand All @@ -110,9 +104,10 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
}

/// Register a file for event-based I/O
pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
unsafe { syscall2(SYS_FEVENT, fd, flags) }
/// Replace the current process with a new executable
pub fn fexec<T: AsRef<[u8]>>(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(),
vars.as_ptr() as usize, vars.len()) }
}

/// Map a file into memory
Expand Down
44 changes: 43 additions & 1 deletion src/libstd/sys/redox/syscall/flag.rs
Expand Up @@ -113,4 +113,46 @@ pub const SA_RESTART: usize = 0x10000000;
pub const SA_NODEFER: usize = 0x40000000;
pub const SA_RESETHAND: usize = 0x80000000;

pub const WNOHANG: usize = 1;
pub const WNOHANG: usize = 0x01;
pub const WUNTRACED: usize = 0x02;
pub const WCONTINUED: usize = 0x08;

/// True if status indicates the child is stopped.
pub fn wifstopped(status: usize) -> bool {
(status & 0xff) == 0x7f
}

/// If wifstopped(status), the signal that stopped the child.
pub fn wstopsig(status: usize) -> usize {
(status >> 8) & 0xff
}

/// True if status indicates the child continued after a stop.
pub fn wifcontinued(status: usize) -> bool {
status == 0xffff
}

/// True if STATUS indicates termination by a signal.
pub fn wifsignaled(status: usize) -> bool {
((status & 0x7f) + 1) as i8 >= 2
}

/// If wifsignaled(status), the terminating signal.
pub fn wtermsig(status: usize) -> usize {
status & 0x7f
}

/// True if status indicates normal termination.
pub fn wifexited(status: usize) -> bool {
wtermsig(status) == 0
}

/// If wifexited(status), the exit status.
pub fn wexitstatus(status: usize) -> usize {
(status >> 8) & 0xff
}

/// True if status indicates a core dump was created.
pub fn wcoredump(status: usize) -> bool {
(status & 0x80) != 0
}
2 changes: 1 addition & 1 deletion src/libstd/sys/redox/syscall/number.rs
Expand Up @@ -36,6 +36,7 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94;
pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207;
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11;
pub const SYS_FMAP: usize = SYS_CLASS_FILE | 90;
pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91;
pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
Expand All @@ -50,7 +51,6 @@ pub const SYS_BRK: usize = 45;
pub const SYS_CHDIR: usize = 12;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const SYS_CLONE: usize = 120;
pub const SYS_EXECVE: usize = 11;
pub const SYS_EXIT: usize = 1;
pub const SYS_FUTEX: usize = 240;
pub const SYS_GETCWD: usize = 183;
Expand Down

0 comments on commit 8d2af4a

Please sign in to comment.