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). 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"; // Please do NOT modify it by hand, as it will be reseted on next build.\n";
const TESTS: [&str; 3] = [ const TESTS: [&str; 3] = ["emtests/env.c", "emtests/puts.c", "emtests/printf.c"];
"emtests/env.c",
"emtests/puts.c",
"emtests/printf.c"
];
pub fn compile(file: &str) -> String { pub fn compile(file: &str) -> String {
let mut output_path = PathBuf::from(file); let mut output_path = PathBuf::from(file);

View File

@ -4,10 +4,22 @@ int main()
{ {
printf("INIT\n"); printf("INIT\n");
const char* UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR"); const char* 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("set UNEXISTENT_ENVVAR = SET\n"); printf("Setting UNEXISTENT_ENVVAR=SET (via putenv)\n");
putenv("UNEXISTENT_ENVVAR=SET"); putenv("UNEXISTENT_ENVVAR=PUTENV");
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR"); 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"); printf("END\n");
} }

View File

@ -1,5 +1,11 @@
INIT INIT
get UNEXISTENT_ENVVAR: [NULL] UNEXISTENT_ENVVAR = [NULL]
set UNEXISTENT_ENVVAR = SET Setting UNEXISTENT_ENVVAR=SET (via putenv)
get UNEXISTENT_ENVVAR: SET 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 END

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,14 @@
use super::super::host; use super::super::host;
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset /// 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::ffi::CStr;
use std::mem; use std::mem;
use std::os::raw::c_char; 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; use crate::webassembly::Instance;
// #[no_mangle] // #[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) } 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 { pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
debug!("emscripten::_getpwnam {}", name_ptr); 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); debug!("emscripten::___build_environment {}", environ);
const MAX_ENV_VALUES: u32 = 64; const MAX_ENV_VALUES: u32 = 64;
const TOTAL_ENV_SIZE: u32 = 1024; const TOTAL_ENV_SIZE: u32 = 1024;
let mut environment = let mut environment = instance.memory_offset_addr(0, environ as _) as *mut c_int;
instance.memory_offset_addr(0, environ as _) as *mut c_int;
unsafe { unsafe {
let (pool_offset, pool_slice): (u32, &mut [u8]) = allocate_on_stack(TOTAL_ENV_SIZE as u32, instance); let (pool_offset, pool_slice): (u32, &mut [u8]) =
let (env_offset, env_slice): (u32, &mut [u8]) = allocate_on_stack((MAX_ENV_VALUES*4) as u32, instance); allocate_on_stack(TOTAL_ENV_SIZE as u32, instance);
let mut env_ptr = let (env_offset, env_slice): (u32, &mut [u8]) =
instance.memory_offset_addr(0, env_offset as _) as *mut c_int; allocate_on_stack((MAX_ENV_VALUES * 4) as u32, instance);
let mut pool_ptr = let mut env_ptr = instance.memory_offset_addr(0, env_offset as _) as *mut c_int;
instance.memory_offset_addr(0, pool_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; *env_ptr = pool_offset as i32;
*environment = env_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 _)); import_object.set("env", "___wait", ImportValue::Func(lock::___wait as _));
// Env // Env
import_object.set("env", "_getenv", ImportValue::Func(env::_getenv as _)); 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", "_getpwnam", ImportValue::Func(env::_getpwnam as _));
import_object.set("env", "_getgrnam", ImportValue::Func(env::_getgrnam as _)); import_object.set("env", "_getgrnam", ImportValue::Func(env::_getgrnam as _));
import_object.set( import_object.set(

View File

@ -1,4 +1,9 @@
#[test] #[test]
fn test_env() { 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"
);
} }