Skip to content

Commit 8d2af4a

Browse files
jackpot51jD91mZM2
authored andcommitted
Update to new system calls and enviromental variables
1 parent 40123a1 commit 8d2af4a

File tree

7 files changed

+168
-58
lines changed

7 files changed

+168
-58
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
url = https://github.com/rust-lang/rust-installer.git
1111
[submodule "src/liblibc"]
1212
path = src/liblibc
13-
url = https://github.com/rust-lang/libc.git
13+
url = https://gitlab.redox-os.org/redox-os/liblibc.git
1414
[submodule "src/doc/nomicon"]
1515
path = src/doc/nomicon
1616
url = https://github.com/rust-lang-nursery/nomicon.git

src/libstd/sys/redox/mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,29 @@ pub fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
7575
result.map_err(|err| io::Error::from_raw_os_error(err.errno))
7676
}
7777

78+
#[doc(hidden)]
79+
pub trait IsMinusOne {
80+
fn is_minus_one(&self) -> bool;
81+
}
82+
83+
macro_rules! impl_is_minus_one {
84+
($($t:ident)*) => ($(impl IsMinusOne for $t {
85+
fn is_minus_one(&self) -> bool {
86+
*self == -1
87+
}
88+
})*)
89+
}
90+
91+
impl_is_minus_one! { i8 i16 i32 i64 isize }
92+
93+
pub fn cvt_libc<T: IsMinusOne>(t: T) -> io::Result<T> {
94+
if t.is_minus_one() {
95+
Err(io::Error::last_os_error())
96+
} else {
97+
Ok(t)
98+
}
99+
}
100+
78101
/// On Redox, use an illegal instruction to abort
79102
pub unsafe fn abort_internal() -> ! {
80103
::core::intrinsics::abort();

src/libstd/sys/redox/os.rs

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
1313
#![allow(unused_imports)] // lots of cfg code here
1414

15+
use libc::{self, c_char};
16+
1517
use os::unix::prelude::*;
1618

1719
use error::Error as StdError;
18-
use ffi::{OsString, OsStr};
20+
use ffi::{CStr, CString, OsStr, OsString};
1921
use fmt;
2022
use io::{self, Read, Write};
2123
use iter;
@@ -27,7 +29,7 @@ use ptr;
2729
use slice;
2830
use str;
2931
use sys_common::mutex::Mutex;
30-
use sys::{cvt, fd, syscall};
32+
use sys::{cvt, cvt_libc, fd, syscall};
3133
use vec;
3234

3335
extern {
@@ -129,6 +131,8 @@ pub fn current_exe() -> io::Result<PathBuf> {
129131
Ok(PathBuf::from(path))
130132
}
131133

134+
pub static ENV_LOCK: Mutex = Mutex::new();
135+
132136
pub struct Env {
133137
iter: vec::IntoIter<(OsString, OsString)>,
134138
_dont_send_or_sync_me: PhantomData<*mut ()>,
@@ -140,52 +144,83 @@ impl Iterator for Env {
140144
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
141145
}
142146

147+
pub unsafe fn environ() -> *mut *const *const c_char {
148+
extern { static mut environ: *const *const c_char; }
149+
&mut environ
150+
}
151+
143152
/// Returns a vector of (variable, value) byte-vector pairs for all the
144153
/// environment variables of the current process.
145154
pub fn env() -> Env {
146-
let mut variables: Vec<(OsString, OsString)> = Vec::new();
147-
if let Ok(mut file) = ::fs::File::open("env:") {
148-
let mut string = String::new();
149-
if file.read_to_string(&mut string).is_ok() {
150-
for line in string.lines() {
151-
let mut parts = line.splitn(2, '=');
152-
if let Some(name) = parts.next() {
153-
let value = parts.next().unwrap_or("");
154-
variables.push((OsString::from(name.to_string()),
155-
OsString::from(value.to_string())));
156-
}
155+
unsafe {
156+
let _guard = ENV_LOCK.lock();
157+
let mut environ = *environ();
158+
if environ == ptr::null() {
159+
panic!("os::env() failure getting env string from OS: {}",
160+
io::Error::last_os_error());
161+
}
162+
let mut result = Vec::new();
163+
while *environ != ptr::null() {
164+
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
165+
result.push(key_value);
157166
}
167+
environ = environ.offset(1);
168+
}
169+
return Env {
170+
iter: result.into_iter(),
171+
_dont_send_or_sync_me: PhantomData,
172+
}
173+
}
174+
175+
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
176+
// Strategy (copied from glibc): Variable name and value are separated
177+
// by an ASCII equals sign '='. Since a variable name must not be
178+
// empty, allow variable names starting with an equals sign. Skip all
179+
// malformed lines.
180+
if input.is_empty() {
181+
return None;
158182
}
183+
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
184+
pos.map(|p| (
185+
OsStringExt::from_vec(input[..p].to_vec()),
186+
OsStringExt::from_vec(input[p+1..].to_vec()),
187+
))
159188
}
160-
Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData }
161189
}
162190

163-
pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> {
164-
if ! key.is_empty() {
165-
if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) {
166-
let mut string = String::new();
167-
file.read_to_string(&mut string)?;
168-
Ok(Some(OsString::from(string)))
191+
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
192+
// environment variables with a nul byte can't be set, so their value is
193+
// always None as well
194+
let k = CString::new(k.as_bytes())?;
195+
unsafe {
196+
let _guard = ENV_LOCK.lock();
197+
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
198+
let ret = if s.is_null() {
199+
None
169200
} else {
170-
Ok(None)
171-
}
172-
} else {
173-
Ok(None)
201+
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
202+
};
203+
Ok(ret)
174204
}
175205
}
176206

177-
pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> {
178-
if ! key.is_empty() {
179-
let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?;
180-
file.write_all(value.as_bytes())?;
181-
file.set_len(value.len() as u64)?;
207+
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
208+
let k = CString::new(k.as_bytes())?;
209+
let v = CString::new(v.as_bytes())?;
210+
211+
unsafe {
212+
let _guard = ENV_LOCK.lock();
213+
cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
182214
}
183-
Ok(())
184215
}
185216

186-
pub fn unsetenv(key: &OsStr) -> io::Result<()> {
187-
::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?;
188-
Ok(())
217+
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
218+
let nbuf = CString::new(n.as_bytes())?;
219+
220+
unsafe {
221+
let _guard = ENV_LOCK.lock();
222+
cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
223+
}
189224
}
190225

191226
pub fn page_size() -> usize {

src/libstd/sys/redox/process.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
// except according to those terms.
1010

1111
use env::{split_paths};
12-
use ffi::OsStr;
12+
use ffi::{CStr, OsStr};
1313
use os::unix::ffi::OsStrExt;
1414
use fmt;
1515
use io::{self, Error, ErrorKind};
1616
use iter;
1717
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
1818
use path::{Path, PathBuf};
19+
use ptr;
1920
use sys::fd::FileDesc;
2021
use sys::fs::{File, OpenOptions};
22+
use sys::os::{ENV_LOCK, environ};
2123
use sys::pipe::{self, AnonPipe};
2224
use sys::{cvt, syscall};
2325
use sys_common::process::{CommandEnv, DefaultEnvKey};
@@ -297,12 +299,6 @@ impl Command {
297299
t!(callback());
298300
}
299301

300-
let args: Vec<[usize; 2]> = iter::once(
301-
[self.program.as_ptr() as usize, self.program.len()]
302-
).chain(
303-
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
304-
).collect();
305-
306302
self.env.apply();
307303

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

324-
if let Some(program) = program {
325-
if let Err(err) = syscall::execve(program.as_os_str().as_bytes(), &args) {
326-
io::Error::from_raw_os_error(err.errno as i32)
327-
} else {
328-
panic!("return from exec without err");
320+
let fd = if let Some(program) = program {
321+
t!(cvt(syscall::open(program.as_os_str().as_bytes(), syscall::O_RDONLY)))
322+
} else {
323+
return io::Error::from_raw_os_error(syscall::ENOENT);
324+
};
325+
326+
let mut args: Vec<[usize; 2]> = iter::once(
327+
[self.program.as_ptr() as usize, self.program.len()]
328+
).chain(
329+
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
330+
).collect();
331+
332+
let mut vars: Vec<[usize; 2]> = Vec::new();
333+
unsafe {
334+
let _guard = ENV_LOCK.lock();
335+
let mut environ = *environ();
336+
while *environ != ptr::null() {
337+
let var = CStr::from_ptr(*environ).to_bytes();
338+
vars.push([var.as_ptr() as usize, var.len()]);
339+
environ = environ.offset(1);
329340
}
341+
}
342+
343+
if let Err(err) = syscall::fexec(fd, &args, &vars) {
344+
io::Error::from_raw_os_error(err.errno as i32)
330345
} else {
331-
io::Error::from_raw_os_error(syscall::ENOENT)
346+
panic!("return from exec without err");
332347
}
333348
}
334349

src/libstd/sys/redox/syscall/call.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,6 @@ pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
8282
unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
8383
}
8484

85-
/// Replace the current process with a new executable
86-
pub fn execve<T: AsRef<[u8]>>(path: T, args: &[[usize; 2]]) -> Result<usize> {
87-
unsafe { syscall4(SYS_EXECVE, path.as_ref().as_ptr() as usize,
88-
path.as_ref().len(), args.as_ptr() as usize, args.len()) }
89-
}
90-
9185
/// Exit the current process
9286
pub fn exit(status: usize) -> Result<usize> {
9387
unsafe { syscall1(SYS_EXIT, status) }
@@ -110,9 +104,10 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
110104
unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
111105
}
112106

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

118113
/// Map a file into memory

src/libstd/sys/redox/syscall/flag.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,46 @@ pub const SA_RESTART: usize = 0x10000000;
113113
pub const SA_NODEFER: usize = 0x40000000;
114114
pub const SA_RESETHAND: usize = 0x80000000;
115115

116-
pub const WNOHANG: usize = 1;
116+
pub const WNOHANG: usize = 0x01;
117+
pub const WUNTRACED: usize = 0x02;
118+
pub const WCONTINUED: usize = 0x08;
119+
120+
/// True if status indicates the child is stopped.
121+
pub fn wifstopped(status: usize) -> bool {
122+
(status & 0xff) == 0x7f
123+
}
124+
125+
/// If wifstopped(status), the signal that stopped the child.
126+
pub fn wstopsig(status: usize) -> usize {
127+
(status >> 8) & 0xff
128+
}
129+
130+
/// True if status indicates the child continued after a stop.
131+
pub fn wifcontinued(status: usize) -> bool {
132+
status == 0xffff
133+
}
134+
135+
/// True if STATUS indicates termination by a signal.
136+
pub fn wifsignaled(status: usize) -> bool {
137+
((status & 0x7f) + 1) as i8 >= 2
138+
}
139+
140+
/// If wifsignaled(status), the terminating signal.
141+
pub fn wtermsig(status: usize) -> usize {
142+
status & 0x7f
143+
}
144+
145+
/// True if status indicates normal termination.
146+
pub fn wifexited(status: usize) -> bool {
147+
wtermsig(status) == 0
148+
}
149+
150+
/// If wifexited(status), the exit status.
151+
pub fn wexitstatus(status: usize) -> usize {
152+
(status >> 8) & 0xff
153+
}
154+
155+
/// True if status indicates a core dump was created.
156+
pub fn wcoredump(status: usize) -> bool {
157+
(status & 0x80) != 0
158+
}

src/libstd/sys/redox/syscall/number.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94;
3636
pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207;
3737
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
3838
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
39+
pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11;
3940
pub const SYS_FMAP: usize = SYS_CLASS_FILE | 90;
4041
pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91;
4142
pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
@@ -50,7 +51,6 @@ pub const SYS_BRK: usize = 45;
5051
pub const SYS_CHDIR: usize = 12;
5152
pub const SYS_CLOCK_GETTIME: usize = 265;
5253
pub const SYS_CLONE: usize = 120;
53-
pub const SYS_EXECVE: usize = 11;
5454
pub const SYS_EXIT: usize = 1;
5555
pub const SYS_FUTEX: usize = 240;
5656
pub const SYS_GETCWD: usize = 183;

0 commit comments

Comments
 (0)