github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/imports/wasi_snapshot_preview1/environ.go (about)

     1  package wasi_snapshot_preview1
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/bananabytelabs/wazero/api"
     7  	"github.com/bananabytelabs/wazero/experimental/sys"
     8  	"github.com/bananabytelabs/wazero/internal/wasip1"
     9  	"github.com/bananabytelabs/wazero/internal/wasm"
    10  )
    11  
    12  // environGet is the WASI function named EnvironGetName that reads
    13  // environment variables.
    14  //
    15  // # Parameters
    16  //
    17  //   - environ: offset to begin writing environment offsets in uint32
    18  //     little-endian encoding to api.Memory
    19  //   - environSizesGet result environc * 4 bytes are written to this offset
    20  //   - environBuf: offset to write the null-terminated variables to api.Memory
    21  //   - the format is like os.Environ: null-terminated "key=val" entries
    22  //   - environSizesGet result environLen bytes are written to this offset
    23  //
    24  // Result (Errno)
    25  //
    26  // The return value is 0 except the following error conditions:
    27  //   - sys.EFAULT: there is not enough memory to write results
    28  //
    29  // For example, if environSizesGet wrote environc=2 and environLen=9 for
    30  // environment variables: "a=b", "b=cd" and parameters environ=11 and
    31  // environBuf=1, this function writes the below to api.Memory:
    32  //
    33  //	                              environLen                 uint32le    uint32le
    34  //	             +------------------------------------+     +--------+  +--------+
    35  //	             |                                    |     |        |  |        |
    36  //	  []byte{?, 'a', '=', 'b', 0, 'b', '=', 'c', 'd', 0, ?, 1, 0, 0, 0, 5, 0, 0, 0, ?}
    37  //	environBuf --^                                          ^           ^
    38  //	                             environ offset for "a=b" --+           |
    39  //	                                        environ offset for "b=cd" --+
    40  //
    41  // See environSizesGet
    42  // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_get
    43  // See https://en.wikipedia.org/wiki/Null-terminated_string
    44  var environGet = newHostFunc(wasip1.EnvironGetName, environGetFn, []api.ValueType{i32, i32}, "environ", "environ_buf")
    45  
    46  func environGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno {
    47  	sysCtx := mod.(*wasm.ModuleInstance).Sys
    48  	environ, environBuf := uint32(params[0]), uint32(params[1])
    49  
    50  	return writeOffsetsAndNullTerminatedValues(mod.Memory(), sysCtx.Environ(), environ, environBuf, sysCtx.EnvironSize())
    51  }
    52  
    53  // environSizesGet is the WASI function named EnvironSizesGetName that
    54  // reads environment variable sizes.
    55  //
    56  // # Parameters
    57  //
    58  //   - resultEnvironc: offset to write the count of environment variables to
    59  //     api.Memory
    60  //   - resultEnvironvLen: offset to write the null-terminated environment
    61  //     variable length to api.Memory
    62  //
    63  // Result (Errno)
    64  //
    65  // The return value is 0 except the following error conditions:
    66  //   - sys.EFAULT: there is not enough memory to write results
    67  //
    68  // For example, if environ are "a=b","b=cd" and parameters resultEnvironc=1 and
    69  // resultEnvironvLen=6, this function writes the below to api.Memory:
    70  //
    71  //	                   uint32le       uint32le
    72  //	                  +--------+     +--------+
    73  //	                  |        |     |        |
    74  //	        []byte{?, 2, 0, 0, 0, ?, 9, 0, 0, 0, ?}
    75  //	 resultEnvironc --^              ^
    76  //		2 variables --+              |
    77  //	             resultEnvironvLen --|
    78  //	    len([]byte{'a','=','b',0,    |
    79  //	           'b','=','c','d',0}) --+
    80  //
    81  // See environGet
    82  // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_sizes_get
    83  // and https://en.wikipedia.org/wiki/Null-terminated_string
    84  var environSizesGet = newHostFunc(wasip1.EnvironSizesGetName, environSizesGetFn, []api.ValueType{i32, i32}, "result.environc", "result.environv_len")
    85  
    86  func environSizesGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno {
    87  	sysCtx := mod.(*wasm.ModuleInstance).Sys
    88  	mem := mod.Memory()
    89  	resultEnvironc, resultEnvironvLen := uint32(params[0]), uint32(params[1])
    90  
    91  	// environc and environv_len offsets are not necessarily sequential, so we
    92  	// have to write them independently.
    93  	if !mem.WriteUint32Le(resultEnvironc, uint32(len(sysCtx.Environ()))) {
    94  		return sys.EFAULT
    95  	}
    96  	if !mem.WriteUint32Le(resultEnvironvLen, sysCtx.EnvironSize()) {
    97  		return sys.EFAULT
    98  	}
    99  	return 0
   100  }