wasi-module-sdk-go/exec/command.go

87 lines
1.5 KiB
Go

package exec
import (
"fmt"
"io"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
rpcv1 "code.icb4dc0.de/buildr/wasi-module-sdk-go/protocol/generated/rpc/v1"
)
func NewCommand(name string, args ...string) *Command {
return &Command{
Name: name,
Args: args,
}
}
type Command struct {
Name string
Args []string
WorkingDir string
Env map[string]string
StdIn io.Reader
}
func (c *Command) AddEnv(envToAdd map[string]string) {
if envToAdd == nil {
return
}
if c.Env == nil {
c.Env = make(map[string]string)
}
for k, v := range envToAdd {
c.Env[k] = v
}
}
func (c *Command) Run() error {
execReq := &rpcv1.ProcessStartRequest{
Command: c.Name,
Args: c.Args,
WorkingDirectory: c.WorkingDir,
Environment: c.Env,
}
if c.StdIn != nil {
if stdInData, err := io.ReadAll(c.StdIn); err != nil {
return err
} else {
execReq.Stdin = stdInData
}
}
data, err := execReq.MarshalVT()
if err != nil {
return err
}
result := _exec(mem.DataToManagedPtr(data))
if result == 0 {
return fmt.Errorf("failed to execute command: %s", c.Name)
}
resultPtr := uint32(result >> 32)
resultSize := uint32(result)
if resultSize == 0 {
return nil
}
execResp := new(rpcv1.ProcessStartResponse)
if err := execResp.UnmarshalVT(mem.PtrToData(resultPtr, resultSize)); err != nil {
return err
}
if execResp.ExitCode != 0 {
return &Error{
ExitCode: int(execResp.ExitCode),
Message: execResp.Error,
StdErr: execResp.Stderr,
}
}
return nil
}