Skip to content

Commit

Permalink
Merge pull request #52 from wasmerio/fix/emscripten-env
Browse files Browse the repository at this point in the history
Fix support for env vars (put, set, unset)
  • Loading branch information
syrusakbary authored Dec 22, 2018
2 parents 63a2ea4 + 3764e02 commit db24e8a
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 10 deletions.
2 changes: 1 addition & 1 deletion build/emtests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +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; 2] = ["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);
Expand Down
25 changes: 25 additions & 0 deletions emtests/env.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("INIT\n");
const char* UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
printf("UNEXISTENT_ENVVAR = %s\n",(UNEXISTENT_ENVVAR!=NULL)? UNEXISTENT_ENVVAR : "[NULL]");
printf("Setting UNEXISTENT_ENVVAR=PUTENV (via putenv)\n");
putenv("UNEXISTENT_ENVVAR=PUTENV");
UNEXISTENT_ENVVAR = getenv("UNEXISTENT_ENVVAR");
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");
}
11 changes: 11 additions & 0 deletions emtests/env.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
INIT
UNEXISTENT_ENVVAR = [NULL]
Setting UNEXISTENT_ENVVAR=PUTENV (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 added emtests/env.wasm
Binary file not shown.
Binary file modified emtests/printf.wasm
Binary file not shown.
20 changes: 14 additions & 6 deletions src/apis/emscripten/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,21 @@

###### ENVIRONMENT

- **\_getenv** &nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
- **\_getenv** &nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust

fn _getenv(name: c_int, instance: &mut Instance)
```
- **\_putenv**&nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust
fn _putenv(name: c_int, instance: &mut Instance)
```
- **\_setenv**&nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust
fn _setenv(name: c_int, value: c_int, overwrite: c_int, instance: &mut Instance
```
- **\_unsetenv**&nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust
fn _unsetenv(name: c_int, instance: &mut Instance)
```

###### THREAD
Expand All @@ -44,10 +56,6 @@
- **\_pthread_setspecific** &nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust

```
- **\_unsetenv** &nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust

```
- **\_\_\_lock** &nbsp;&nbsp;&nbsp;&nbsp;[:top:](#host-apis)
```rust
Expand Down
62 changes: 59 additions & 3 deletions src/apis/emscripten/env.rs
Original file line number Diff line number Diff line change
@@ -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};
use super::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use crate::webassembly::Instance;

// #[no_mangle]
Expand All @@ -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);

Expand Down Expand Up @@ -104,8 +142,26 @@ pub extern "C" fn _getpagesize() -> u32 {
16384
}

pub extern "C" fn ___build_environment(environ: c_int) {
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;
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;
*env_ptr = pool_offset as i32;
*environment = env_offset as i32;

// *env_ptr = 0;
};
// unsafe {
// *env_ptr = 0;
// };
}

pub extern "C" fn _sysconf(name: c_int, _instance: &mut Instance) -> c_long {
Expand Down
3 changes: 3 additions & 0 deletions src/apis/emscripten/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
9 changes: 9 additions & 0 deletions src/emtests/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[test]
fn test_env() {
assert_emscripten_output!(
"../../emtests/env.wasm",
"env",
vec![],
"../../emtests/env.output"
);
}
1 change: 1 addition & 0 deletions src/emtests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
// The _common module is not autogenerated, as it provides common macros for the emtests
#[macro_use]
mod _common;
mod env;
mod printf;
mod puts;

0 comments on commit db24e8a

Please sign in to comment.