wa-lang.org/wazero@v1.0.2/imports/wasi_snapshot_preview1/environ.go (about)

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