Improved emscripten env(get,set,unset,put) integration

This commit is contained in:
Syrus 2018-12-21 17:16:40 -08:00
parent ae77811c4d
commit 1ad580a618
8 changed files with 82 additions and 23 deletions

View File

@ -11,11 +11,7 @@ use std::process::Command;
static BANNER: &str = "// Rust test file autogenerated with cargo build (build/emtests.rs).
// Please do NOT modify it by hand, as it will be reseted on next build.\n";
const TESTS: [&str; 3] = [
"emtests/env.c",
"emtests/puts.c",
"emtests/printf.c"
];
const TESTS: [&str; 3] = ["emtests/env.c", "emtests/puts.c", "emtests/printf.c"];
pub fn compile(file: &str) -> String {
let mut output_path = PathBuf::from(file);

View File

@ -4,10 +4,22 @@ int main()
{
printf("INIT\n");
const char* UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("get UNEXISTENT_ENVVAR: %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("set UNEXISTENT_ENVVAR = SET\n");
putenv("UNEXISTENT_ENVVAR=SET");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("Setting UNEXISTENT_ENVVAR=SET (via putenv)\n");
putenv("UNEXISTENT_ENVVAR=PUTENV");
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("get UNEXISTENT_ENVVAR: %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("Setting UNEXISTENT_ENVVAR=SETENV (via setenv, overwrite)\n");
setenv("UNEXISTENT_ENVVAR", "SETENV", 1);
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("Setting UNEXISTENT_ENVVAR=SETENV_NEW (via setenv, NO overwrite)\n");
setenv("UNEXISTENT_ENVVAR", "SETENV_NEW", 0);
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("Unsetting UNEXISTENT_ENVVAR\n");
unsetenv("UNEXISTENT_ENVVAR");
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("END\n");
}

View File

@ -1,5 +1,11 @@
INIT
get UNEXISTENT_ENVVAR: [NULL]
set UNEXISTENT_ENVVAR = SET
get UNEXISTENT_ENVVAR: SET
UNEXISTENT_ENVVAR = [NULL]
Setting UNEXISTENT_ENVVAR=SET (via putenv)
UNEXISTENT_ENVVAR = PUTENV
Setting UNEXISTENT_ENVVAR=SETENV (via setenv, overwrite)
UNEXISTENT_ENVVAR = SETENV
Setting UNEXISTENT_ENVVAR=SETENV_NEW (via setenv, NO overwrite)
UNEXISTENT_ENVVAR = SETENV
Unsetting UNEXISTENT_ENVVAR
UNEXISTENT_ENVVAR = [NULL]
END

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,14 @@
use super::super::host;
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
use libc::{c_int, c_long, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, sysconf};
use libc::{
c_int, c_long, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv,
sysconf, unsetenv,
};
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_char;
use super::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs, allocate_on_stack};
use super::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use crate::webassembly::Instance;
// #[no_mangle]
@ -25,6 +28,41 @@ pub extern "C" fn _getenv(name: c_int, instance: &mut Instance) -> u32 {
unsafe { copy_cstr_into_wasm(instance, c_str) }
}
/// 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) };
}
pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
debug!("emscripten::_getpwnam {}", name_ptr);
@ -108,15 +146,14 @@ pub extern "C" fn ___build_environment(environ: c_int, instance: &mut Instance)
debug!("emscripten::___build_environment {}", environ);
const MAX_ENV_VALUES: u32 = 64;
const TOTAL_ENV_SIZE: u32 = 1024;
let mut environment =
instance.memory_offset_addr(0, environ as _) as *mut c_int;
let mut environment = instance.memory_offset_addr(0, environ as _) as *mut c_int;
unsafe {
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;
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;
*env_ptr = pool_offset as i32;
*environment = env_offset as i32;

View File

@ -114,6 +114,9 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
import_object.set("env", "___wait", ImportValue::Func(lock::___wait as _));
// Env
import_object.set("env", "_getenv", ImportValue::Func(env::_getenv as _));
import_object.set("env", "_setenv", ImportValue::Func(env::_setenv as _));
import_object.set("env", "_putenv", ImportValue::Func(env::_putenv as _));
import_object.set("env", "_unsetenv", ImportValue::Func(env::_unsetenv as _));
import_object.set("env", "_getpwnam", ImportValue::Func(env::_getpwnam as _));
import_object.set("env", "_getgrnam", ImportValue::Func(env::_getgrnam as _));
import_object.set(

View File

@ -1,4 +1,9 @@
#[test]
fn test_env() {
assert_emscripten_output!("../../emtests/env.wasm", "env", vec![], "../../emtests/env.output");
assert_emscripten_output!(
"../../emtests/env.wasm",
"env",
vec![],
"../../emtests/env.output"
);
}