diff --git a/include/bits/exec.h b/include/bits/exec.h new file mode 100644 index 0000000000000000000000000000000000000000..94024518ba8fd7999a7b8902e357810504a1191f --- /dev/null +++ b/include/bits/exec.h @@ -0,0 +1,47 @@ +#ifndef _BITS_EXEC_H +#define _BITS_EXEC_H + +int execl(const char *path, const char* argv0, ...) +{ + int argc; + va_list ap; + va_start(ap, argv0); + for (argc = 1; va_arg(ap, const char*); argc++); + va_end(ap); + { + int i; + char *argv[argc+1]; + va_start(ap, argv0); + argv[0] = (char *)argv0; + for (i = 1; i < argc; i++) { + argv[i] = va_arg(ap, char *); + } + argv[i] = NULL; + va_end(ap); + return execv(path, argv); + } +} + +int execle(const char *path, const char* argv0, ...) +{ + int argc; + va_list ap; + va_start(ap, argv0); + for (argc = 1; va_arg(ap, const char *); argc++); + va_end(ap); + { + int i; + char *argv[argc+1]; + char **envp; + va_start(ap, argv0); + argv[0] = (char *)argv0; + for (i = 1; i <= argc; i++) { + argv[i] = va_arg(ap, char *); + } + envp = va_arg(ap, char **); + va_end(ap); + return execve(path, argv, envp); + } +} + +#endif diff --git a/src/platform/Cargo.toml b/src/platform/Cargo.toml index e25b8251c0c6bb44761c2f5a8af2e7eda0c70881..dd5ba725ac56ffd3eb4431e3df80d7b94791eff0 100644 --- a/src/platform/Cargo.toml +++ b/src/platform/Cargo.toml @@ -8,3 +8,6 @@ sc = "0.2" [target.'cfg(target_os = "redox")'.dependencies] redox_syscall = "0.1" + +[dependencies] +ralloc = { path = "../../ralloc" } diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs index 4919e61308e9350268b528008383c49aefd79954..78bc4c39cac2d16fc081b744b78594cf38a8cafe 100644 --- a/src/platform/src/lib.rs +++ b/src/platform/src/lib.rs @@ -2,6 +2,8 @@ #![no_std] #![allow(non_camel_case_types)] +#![feature(alloc)] +#![feature(global_allocator)] //TODO #![feature(thread_local)] #[cfg(all(not(feature = "no_std"), target_os = "linux"))] @@ -22,12 +24,17 @@ mod sys; #[path = "redox/mod.rs"] mod sys; +extern crate alloc; +extern crate ralloc; + pub mod types; use core::fmt; use types::*; +#[global_allocator] +static ALLOCATOR: ralloc::Allocator = ralloc::Allocator; //TODO #[thread_local] #[allow(non_upper_case_globals)] #[no_mangle] diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index 0ae481e4f393662b131ef0c185d3386a62e2edd3..1046549b0e671261904d6d6ad7461576158bec85 100644 --- a/src/platform/src/linux/mod.rs +++ b/src/platform/src/linux/mod.rs @@ -54,6 +54,10 @@ pub fn dup2(fildes: c_int, fildes2: c_int) -> c_int { e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int } +pub fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { + e(unsafe { syscall!(EXECVE, path, argv, envp) }) as c_int +} + pub fn exit(status: c_int) -> ! { unsafe { syscall!(EXIT, status); diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 56eed2b259393dafc12a79ba02135f94c6c7cd5c..71019375f7c9f4400a34fe805bb1e8ac77a4a02e 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -1,5 +1,7 @@ use core::ptr; use core::slice; +use core::mem; +use alloc::Vec; use syscall; use syscall::flag::*; use syscall::data::TimeSpec as redox_timespec; @@ -66,6 +68,58 @@ pub fn dup2(fd1: c_int, fd2: c_int) -> c_int { e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int } +pub fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { + unsafe { + let mut env = envp; + while !(*env).is_null() { + let slice = c_str(*env); + // Should always contain a =, but worth checking + if let Some(sep) = slice.iter().position(|&c| c == b'=') { + // If the environment variable has no name, do not attempt + // to add it to the env. + if sep > 0 { + let mut path = b"env:".to_vec(); + path.extend_from_slice(&slice[..sep]); + match syscall::open(&path, O_WRONLY | O_CREAT) { + Ok(fd) => { + // If the environment variable has no value, there + // is no need to write anything to the env scheme. + if sep + 1 < slice.len() { + let n = match syscall::write(fd, &slice[sep + 1..]) { + Ok(n) => n, + err => { + return e(err) as c_int; + } + }; + } + // Cleanup after adding the variable. + match syscall::close(fd) { + Ok(_) => (), + err => { + return e(err) as c_int; + } + } + } + err => { + return e(err) as c_int; + } + } + } + } + env = env.offset(1); + } + + let mut args: Vec<[usize; 2]> = Vec::new(); + let mut arg = argv; + while !(*arg).is_null() { + args.push([*arg as usize, c_str(*arg).len()]); + arg = arg.offset(1); + } + + e(syscall::execve(c_str(path), &args)) as c_int + } +} + pub fn exit(status: c_int) -> ! { let _ = syscall::exit(status as usize); loop {} diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index f88743581d81d1bc2ccd9b08574ce53076436acc..ff5404d56dc1307331fbc3db06798a47645e8eb6 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -2,7 +2,6 @@ #![no_std] #![feature(core_intrinsics)] -#![feature(global_allocator)] extern crate ctype; extern crate errno; diff --git a/src/unistd/cbindgen.toml b/src/unistd/cbindgen.toml index cf1de270d4e51c0643f3858b8327402b09fcdd1e..ef4ad8123a3ed5aed99c7d22f7187965d2a72dca 100644 --- a/src/unistd/cbindgen.toml +++ b/src/unistd/cbindgen.toml @@ -1,5 +1,6 @@ -sys_includes = ["stddef.h", "stdint.h", "sys/types.h"] +sys_includes = ["stddef.h", "stdint.h", "sys/types.h", "stdarg.h", "bits/exec.h"] include_guard = "_UNISTD_H" +trailer = "#include <bits/fcntl.h>" language = "C" [enum] diff --git a/src/unistd/src/getopt.rs b/src/unistd/src/getopt.rs index e1dac2dad77298c515b5f19fe164dd2fb06382c5..1457e732be2b88a2cbb395dcfd936d595f9595d4 100644 --- a/src/unistd/src/getopt.rs +++ b/src/unistd/src/getopt.rs @@ -1,7 +1,6 @@ //! getopt implementation for Redox, following http://pubs.opengroup.org/onlinepubs/009695399/functions/getopt.html use super::platform::types::*; -use super::platform; use super::stdio; use super::string; use core::ptr; diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index a757781e2b9f894799a5ca4678fef8d12cd32da3..db90a9feafd2f975a00f343166e92f7196d9a9b8 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -9,6 +9,7 @@ extern crate sys_utsname; pub use platform::types::*; pub use getopt::*; + use core::ptr; mod getopt; @@ -31,6 +32,9 @@ pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; +#[no_mangle] +pub static mut environ: *const *mut c_char = 0 as *const *mut c_char; + #[no_mangle] pub extern "C" fn _exit(status: c_int) { platform::exit(status) @@ -97,23 +101,27 @@ pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) { } // #[no_mangle] -// pub extern "C" fn execl(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int { +// pub extern "C" fn execl(path: *const c_char, args: *const *mut c_char) -> c_int { // unimplemented!(); // } -// + // #[no_mangle] -// pub extern "C" fn execle(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int { +// pub extern "C" fn execle( +// path: *const c_char, +// args: *const *mut c_char, +// envp: *const *mut c_char, +// ) -> c_int { // unimplemented!(); // } -// + // #[no_mangle] -// pub extern "C" fn execlp(file: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int { +// pub extern "C" fn execlp(file: *const c_char, args: *const *mut c_char) -> c_int { // unimplemented!(); // } #[no_mangle] pub extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int { - unimplemented!(); + unsafe { execve(path, argv, environ) } } #[no_mangle] @@ -122,7 +130,7 @@ pub extern "C" fn execve( argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int { - unimplemented!(); + platform::execve(path, argv, envp) } #[no_mangle] @@ -396,7 +404,7 @@ pub extern "C" fn sbrk(incr: intptr_t) -> *mut c_void { #[no_mangle] pub extern "C" fn setgid(gid: gid_t) -> c_int { - unimplemented!(); + platform::setregid(gid, gid) } #[no_mangle] @@ -426,7 +434,7 @@ pub extern "C" fn setsid() -> pid_t { #[no_mangle] pub extern "C" fn setuid(uid: uid_t) -> c_int { - unimplemented!(); + platform::setreuid(uid, uid) } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index c6837db38168e7cd13cc47bc80b7a93639d625d2..c60d7feecf6720f05e8ee899c0f6ba2fe3a4f2ab 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -11,6 +11,7 @@ /ctype /dup /error +/exec /fchdir /fcntl /fsync diff --git a/tests/Makefile b/tests/Makefile index dcea342362dbadc01638ac6729871a2112c1efba..dbe6063de243a036f087e7555b016eb0b2bb2970 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -9,6 +9,7 @@ EXPECT_BINS=\ ctype \ dup \ error \ + exec \ fchdir \ fcntl \ fsync \ diff --git a/tests/exec.c b/tests/exec.c new file mode 100644 index 0000000000000000000000000000000000000000..4a09e743b59e80de89fbf221a3115cbac6f78af4 --- /dev/null +++ b/tests/exec.c @@ -0,0 +1,8 @@ +#include <unistd.h> + +int main(int argc, char** argv) { + char *const args[1] = {"arg"}; + execv("write", args); + perror("execv"); + return 0; +}