2018-11-21 23:10:03 +00:00
|
|
|
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
|
2018-12-22 01:16:40 +00:00
|
|
|
use libc::{
|
|
|
|
c_int, c_long, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv,
|
|
|
|
sysconf, unsetenv,
|
|
|
|
};
|
2018-11-21 23:10:03 +00:00
|
|
|
use std::ffi::CStr;
|
2018-11-27 04:28:13 +00:00
|
|
|
use std::mem;
|
2018-11-27 04:29:26 +00:00
|
|
|
use std::os::raw::c_char;
|
2018-11-21 23:10:03 +00:00
|
|
|
|
2018-12-22 01:16:40 +00:00
|
|
|
use super::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
2019-01-06 21:21:06 +00:00
|
|
|
use crate::apis::emscripten::EmscriptenData;
|
2019-01-03 02:50:13 +00:00
|
|
|
use crate::runtime::{types::Value, Instance};
|
2018-12-30 10:23:16 +00:00
|
|
|
|
|
|
|
impl Instance {
|
|
|
|
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize {
|
|
|
|
unimplemented!("TODO replace this stub")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn emscripten_data(&self) -> &'static mut Option<EmscriptenData> {
|
|
|
|
unimplemented!("TODO replace this stub")
|
|
|
|
}
|
|
|
|
}
|
2018-11-21 23:10:03 +00:00
|
|
|
|
2018-12-18 12:44:15 +00:00
|
|
|
// #[no_mangle]
|
2018-12-13 23:09:07 +00:00
|
|
|
/// emscripten: _getenv // (name: *const char) -> *const c_char;
|
2018-12-17 08:15:08 +00:00
|
|
|
pub extern "C" fn _getenv(name: c_int, instance: &mut Instance) -> u32 {
|
2018-12-18 12:44:15 +00:00
|
|
|
debug!("emscripten::_getenv");
|
|
|
|
|
|
|
|
let name_addr = instance.memory_offset_addr(0, name as usize) as *const c_char;
|
|
|
|
|
|
|
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
|
|
|
|
|
|
|
let c_str = unsafe { getenv(name_addr) };
|
2018-12-18 17:43:59 +00:00
|
|
|
if c_str.is_null() {
|
|
|
|
return 0;
|
2018-11-21 23:10:03 +00:00
|
|
|
}
|
2018-12-18 12:44:15 +00:00
|
|
|
|
|
|
|
unsafe { copy_cstr_into_wasm(instance, c_str) }
|
2018-11-21 23:10:03 +00:00
|
|
|
}
|
2018-11-26 06:17:33 +00:00
|
|
|
|
2018-12-22 01:16:40 +00:00
|
|
|
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
|
|
|
pub extern "C" fn _setenv(name: c_int, value: c_int, overwrite: c_int, instance: &mut Instance) {
|
|
|
|
debug!("emscripten::_setenv");
|
|
|
|
|
|
|
|
let name_addr = instance.memory_offset_addr(0, name as usize) as *const c_char;
|
|
|
|
let value_addr = instance.memory_offset_addr(0, value as usize) as *const c_char;
|
|
|
|
|
|
|
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
|
|
|
debug!("=> value({:?})", unsafe { CStr::from_ptr(value_addr) });
|
|
|
|
|
|
|
|
unsafe { setenv(name_addr, value_addr, overwrite) };
|
|
|
|
}
|
|
|
|
|
|
|
|
/// emscripten: _putenv // (name: *const char);
|
|
|
|
pub extern "C" fn _putenv(name: c_int, instance: &mut Instance) {
|
|
|
|
debug!("emscripten::_putenv");
|
|
|
|
|
|
|
|
let name_addr = instance.memory_offset_addr(0, name as usize) as *const c_char;
|
|
|
|
|
|
|
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
|
|
|
|
|
|
|
unsafe { putenv(name_addr as _) };
|
|
|
|
}
|
|
|
|
|
|
|
|
/// emscripten: _unsetenv // (name: *const char);
|
|
|
|
pub extern "C" fn _unsetenv(name: c_int, instance: &mut Instance) {
|
|
|
|
debug!("emscripten::_unsetenv");
|
|
|
|
|
|
|
|
let name_addr = instance.memory_offset_addr(0, name as usize) as *const c_char;
|
|
|
|
|
|
|
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
|
|
|
|
|
|
|
unsafe { unsetenv(name_addr) };
|
|
|
|
}
|
|
|
|
|
2018-11-26 06:17:33 +00:00
|
|
|
pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
|
2018-11-26 22:30:28 +00:00
|
|
|
debug!("emscripten::_getpwnam {}", name_ptr);
|
|
|
|
|
2018-11-26 06:17:33 +00:00
|
|
|
#[repr(C)]
|
|
|
|
struct GuestPasswd {
|
|
|
|
pw_name: u32,
|
|
|
|
pw_passwd: u32,
|
|
|
|
pw_uid: u32,
|
|
|
|
pw_gid: u32,
|
|
|
|
pw_gecos: u32,
|
|
|
|
pw_dir: u32,
|
|
|
|
pw_shell: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = unsafe {
|
|
|
|
let memory_name_ptr = instance.memory_offset_addr(0, name_ptr as usize) as *const c_char;
|
|
|
|
CStr::from_ptr(memory_name_ptr)
|
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let passwd = &*libc_getpwnam(name.as_ptr());
|
2019-01-03 02:50:13 +00:00
|
|
|
let passwd_struct_offset = call_malloc(mem::size_of::<GuestPasswd>() as _, instance);
|
2018-11-26 06:17:33 +00:00
|
|
|
|
2018-11-27 04:29:26 +00:00
|
|
|
let passwd_struct_ptr =
|
|
|
|
instance.memory_offset_addr(0, passwd_struct_offset as _) as *mut GuestPasswd;
|
2018-11-26 06:17:33 +00:00
|
|
|
(*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(instance, passwd.pw_name);
|
|
|
|
(*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(instance, passwd.pw_passwd);
|
|
|
|
(*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(instance, passwd.pw_gecos);
|
|
|
|
(*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(instance, passwd.pw_dir);
|
|
|
|
(*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(instance, passwd.pw_shell);
|
|
|
|
(*passwd_struct_ptr).pw_uid = passwd.pw_uid;
|
|
|
|
(*passwd_struct_ptr).pw_gid = passwd.pw_gid;
|
|
|
|
|
|
|
|
passwd_struct_offset as c_int
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
|
2018-11-26 22:30:28 +00:00
|
|
|
debug!("emscripten::_getgrnam {}", name_ptr);
|
|
|
|
|
2018-11-26 06:17:33 +00:00
|
|
|
#[repr(C)]
|
|
|
|
struct GuestGroup {
|
|
|
|
gr_name: u32,
|
|
|
|
gr_passwd: u32,
|
|
|
|
gr_gid: u32,
|
|
|
|
gr_mem: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = unsafe {
|
|
|
|
let memory_name_ptr = instance.memory_offset_addr(0, name_ptr as usize) as *const c_char;
|
|
|
|
CStr::from_ptr(memory_name_ptr)
|
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let group = &*libc_getgrnam(name.as_ptr());
|
2019-01-03 02:50:13 +00:00
|
|
|
let group_struct_offset = call_malloc(mem::size_of::<GuestGroup>() as _, instance);
|
2018-11-26 06:17:33 +00:00
|
|
|
|
2018-11-27 04:29:26 +00:00
|
|
|
let group_struct_ptr =
|
|
|
|
instance.memory_offset_addr(0, group_struct_offset as _) as *mut GuestGroup;
|
2018-11-26 06:17:33 +00:00
|
|
|
(*group_struct_ptr).gr_name = copy_cstr_into_wasm(instance, group.gr_name);
|
|
|
|
(*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(instance, group.gr_passwd);
|
|
|
|
(*group_struct_ptr).gr_gid = group.gr_gid;
|
|
|
|
(*group_struct_ptr).gr_mem = copy_terminated_array_of_cstrs(instance, group.gr_mem);
|
|
|
|
|
|
|
|
group_struct_offset as c_int
|
|
|
|
}
|
2018-11-26 21:01:15 +00:00
|
|
|
}
|
2018-11-26 20:42:47 +00:00
|
|
|
|
2019-01-03 02:50:13 +00:00
|
|
|
pub fn call_malloc(size: i32, instance: &mut Instance) -> u32 {
|
|
|
|
let ret = instance
|
|
|
|
.call("_malloc", &[Value::I32(size)])
|
|
|
|
.expect("_malloc call failed");
|
|
|
|
if let Some(Value::I32(ptr)) = ret {
|
|
|
|
ptr as u32
|
|
|
|
} else {
|
|
|
|
panic!("unexpected value from _malloc: {:?}", ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call_memalign(alignment: u32, size: u32, instance: &mut Instance) -> u32 {
|
|
|
|
let ret = instance
|
|
|
|
.call(
|
|
|
|
"_memalign",
|
|
|
|
&[Value::I32(alignment as i32), Value::I32(size as i32)],
|
|
|
|
)
|
|
|
|
.expect("_memalign call failed");
|
|
|
|
if let Some(Value::I32(res)) = ret {
|
|
|
|
res as u32
|
|
|
|
} else {
|
|
|
|
panic!("unexpected value from _memalign {:?}", ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call_memset(pointer: u32, value: i32, size: u32, instance: &mut Instance) -> u32 {
|
|
|
|
let ret = instance
|
|
|
|
.call(
|
|
|
|
"_memset",
|
|
|
|
&[
|
|
|
|
Value::I32(pointer as i32),
|
|
|
|
Value::I32(value),
|
|
|
|
Value::I32(size as i32),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.expect("_memset call failed");
|
|
|
|
if let Some(Value::I32(res)) = ret {
|
|
|
|
res as u32
|
|
|
|
} else {
|
|
|
|
panic!("unexpected value from _memset {:?}", ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-27 04:29:26 +00:00
|
|
|
pub extern "C" fn _getpagesize() -> u32 {
|
2018-11-26 22:30:28 +00:00
|
|
|
debug!("emscripten::_getpagesize");
|
2018-11-27 03:48:19 +00:00
|
|
|
16384
|
2018-11-27 04:29:26 +00:00
|
|
|
}
|
2018-11-30 05:59:43 +00:00
|
|
|
|
2018-12-12 06:10:35 +00:00
|
|
|
pub extern "C" fn ___build_environment(environ: c_int, instance: &mut Instance) {
|
2018-11-30 05:59:43 +00:00
|
|
|
debug!("emscripten::___build_environment {}", environ);
|
2018-12-12 06:10:35 +00:00
|
|
|
const MAX_ENV_VALUES: u32 = 64;
|
|
|
|
const TOTAL_ENV_SIZE: u32 = 1024;
|
2018-12-22 01:16:40 +00:00
|
|
|
let mut environment = instance.memory_offset_addr(0, environ as _) as *mut c_int;
|
2018-12-12 06:10:35 +00:00
|
|
|
unsafe {
|
2018-12-22 01:16:40 +00:00
|
|
|
let (pool_offset, pool_slice): (u32, &mut [u8]) =
|
|
|
|
allocate_on_stack(TOTAL_ENV_SIZE as u32, instance);
|
|
|
|
let (env_offset, env_slice): (u32, &mut [u8]) =
|
|
|
|
allocate_on_stack((MAX_ENV_VALUES * 4) as u32, instance);
|
|
|
|
let mut env_ptr = instance.memory_offset_addr(0, env_offset as _) as *mut c_int;
|
|
|
|
let mut pool_ptr = instance.memory_offset_addr(0, pool_offset as _) as *mut c_int;
|
2018-12-12 06:10:35 +00:00
|
|
|
*env_ptr = pool_offset as i32;
|
|
|
|
*environment = env_offset as i32;
|
|
|
|
|
|
|
|
// *env_ptr = 0;
|
|
|
|
};
|
|
|
|
// unsafe {
|
|
|
|
// *env_ptr = 0;
|
|
|
|
// };
|
2018-11-30 05:59:43 +00:00
|
|
|
}
|
2018-12-05 23:14:58 +00:00
|
|
|
|
2018-12-08 06:31:49 +00:00
|
|
|
pub extern "C" fn _sysconf(name: c_int, _instance: &mut Instance) -> c_long {
|
2018-12-05 23:14:58 +00:00
|
|
|
debug!("emscripten::_sysconf {}", name);
|
|
|
|
// TODO: Implement like emscripten expects regarding memory/page size
|
2018-12-15 06:46:11 +00:00
|
|
|
unsafe { sysconf(name) }
|
2018-12-05 23:14:58 +00:00
|
|
|
}
|