Files
RedBear-OS/src/todo/oldlib/process.rs
T
2018-03-04 05:08:32 -08:00

208 lines
5.8 KiB
Rust

use libc::{c_char, c_int, c_void, size_t, gid_t, uid_t, ptrdiff_t};
use ::types::pid_t;
use core::slice;
use alloc::Vec;
use syscall::error::{Error, EINVAL};
use syscall;
const MAXPATHLEN: usize = 1024;
static mut CURR_BRK: usize = 0;
libc_fn!(unsafe chdir(path: *const c_char) -> Result<c_int> {
Ok(syscall::chdir(::cstr_to_slice(path))? as c_int)
});
libc_fn!(unsafe fchdir(fd: c_int) -> Result<c_int> {
let mut buf = [0; MAXPATHLEN];
let length = syscall::fpath(fd as usize, &mut buf)?;
Ok(syscall::chdir(&buf[0..length])? as c_int)
});
libc_fn!(unsafe _exit(code: c_int) {
::__libc_fini_array();
syscall::exit(code as usize).unwrap();
});
libc_fn!(unsafe _execve(name: *const c_char, argv: *const *const c_char, env: *const *const c_char) -> Result<c_int> {
let mut env = env;
while !(*env).is_null() {
let slice = ::cstr_to_slice(*env);
// Should always contain a =, but worth checking
if let Some(sep) = slice.iter().position(|&c| c == b'=') {
let mut path = b"env:".to_vec();
path.extend_from_slice(&slice[..sep]);
if let Ok(fd) = ::RawFile::open(&path, syscall::O_WRONLY | syscall::O_CREAT) {
let _ = syscall::write(*fd, &slice[sep+1..]);
}
}
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, ::strlen(*arg)]);
arg = arg.offset(1);
}
Ok(syscall::execve(::cstr_to_slice(name), &args)? as c_int)
});
libc_fn!(unsafe _fork() -> Result<c_int> {
Ok(syscall::clone(0)? as c_int)
});
libc_fn!(unsafe vfork() -> Result<c_int> {
Ok(syscall::clone(syscall::CLONE_VFORK)? as c_int)
});
libc_fn!(unsafe getcwd(buf: *mut c_char, size: size_t) -> Result<*const c_char> {
let mut size = size;
if size == 0 {
size = ::file::PATH_MAX;
}
let buf = ::MallocNull::new(buf, size);
let slice = slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, size);
let count = syscall::getcwd(&mut slice[..size-1])?;
slice[count] = b'\0';
Ok(buf.into_raw())
// FIXME: buffer too small
});
libc_fn!(unsafe getwd(buf: *mut c_char) -> Result<*const c_char> {
if buf.is_null() {
Err(Error::new(EINVAL))
} else {
let mut tmp: [u8; MAXPATHLEN] = [0; MAXPATHLEN];
syscall::getcwd(&mut tmp)?;
slice::from_raw_parts_mut(buf as *mut u8, MAXPATHLEN)
.copy_from_slice(&mut tmp);
Ok(buf)
}
});
libc_fn!(unsafe _getpid() -> pid_t {
syscall::getpid().unwrap() as pid_t
});
libc_fn!(unsafe getppid() -> pid_t {
syscall::getppid().unwrap() as pid_t
});
libc_fn!(unsafe getegid() -> gid_t {
syscall::getegid().unwrap() as gid_t
});
libc_fn!(unsafe geteuid() -> uid_t {
syscall::geteuid().unwrap() as uid_t
});
libc_fn!(unsafe getgid() -> gid_t {
syscall::getgid().unwrap() as gid_t
});
libc_fn!(unsafe getuid() -> uid_t {
syscall::getuid().unwrap() as uid_t
});
libc_fn!(unsafe _kill(pid: c_int, sig: c_int) -> Result<c_int> {
Ok(syscall::kill(pid as usize, sig as usize)? as c_int)
});
libc_fn!(unsafe _brk(end_data_segment: *mut c_void) -> Result<c_int> {
CURR_BRK = syscall::brk(end_data_segment as usize)?;
Ok(0)
});
libc_fn!(unsafe _sbrk(increment: ptrdiff_t) -> *mut c_void {
if CURR_BRK == 0 {
CURR_BRK = syscall::brk(0).unwrap();
}
let old_brk = CURR_BRK;
if increment != 0 {
let addr = if increment >= 0 {
old_brk + increment as usize
} else {
old_brk - (-increment) as usize
};
CURR_BRK = match syscall::brk(addr) {
Ok(x) => x,
Err(err) => {
*::__errno() = err.errno;
return -1 as isize as *mut c_void;
}
}
}
old_brk as *mut c_void
});
libc_fn!(unsafe _sched_yield() -> Result<c_int> {
Ok(syscall::sched_yield()? as c_int)
});
libc_fn!(unsafe _system(s: *const c_char) -> Result<c_int> {
match syscall::clone(0)? {
0 => {
let shell = "/bin/sh";
let arg1 = "-c";
let args = [
[shell.as_ptr() as usize, shell.len()],
[arg1.as_ptr() as usize, arg1.len()],
[s as usize, ::strlen(s)]
];
syscall::execve(shell, &args)?;
syscall::exit(100)?;
unreachable!()
}
pid => {
let mut status = 0;
syscall::waitpid(pid, &mut status, 0)?;
Ok(status as c_int)
}
}
});
libc_fn!(unsafe setregid(rgid: gid_t, egid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(rgid as usize, egid as usize)? as c_int)
});
libc_fn!(unsafe setegid(egid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(-1isize as usize, egid as usize)? as c_int)
});
libc_fn!(unsafe setgid(gid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(gid as usize, gid as usize)? as c_int)
});
libc_fn!(unsafe setreuid(ruid: uid_t, euid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(ruid as usize, euid as usize)? as c_int)
});
libc_fn!(unsafe seteuid(euid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(-1isize as usize, euid as usize)? as c_int)
});
libc_fn!(unsafe setuid(uid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(uid as usize, uid as usize)? as c_int)
});
libc_fn!(unsafe _wait(status: *mut c_int) -> Result<c_int> {
let mut buf = 0;
let res = syscall::waitpid(0, &mut buf, 0)?;
*status = buf as c_int;
Ok(res as c_int)
});
libc_fn!(unsafe waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> Result<c_int> {
let mut buf = 0;
let pid = if pid == -1 {
0
} else {
pid as usize
};
let res = syscall::waitpid(pid as usize, &mut buf, options as usize)?;
*status = buf as c_int;
Ok(res as c_int)
});