From 121c0ab08948416b23d404c483723c40cb2bf536 Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Wed, 30 Dec 2020 20:13:13 +0100 Subject: [PATCH] feat: add experimental rust lib binding --- .gitignore | 1 + src/environment.go | 80 +++++++++++++++------------------------------- 2 files changed, 27 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index d8732129..6bf2d5d3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.dll *.so *.dylib +*.h # Initialization scripts generated by https://github.com/kevinburke/go-bindata init.go diff --git a/src/environment.go b/src/environment.go index 11f66081..4dddac60 100644 --- a/src/environment.go +++ b/src/environment.go @@ -1,10 +1,14 @@ package main +/* +#cgo CFLAGS: -I. +#cgo LDFLAGS: -L. -lposh3 +#include +#include +*/ +import "C" import ( - "bufio" - "bytes" "context" - "io" "io/ioutil" "log" "net/http" @@ -14,6 +18,7 @@ import ( "runtime" "strings" "time" + "unsafe" "github.com/distatus/battery" "github.com/shirou/gopsutil/host" @@ -155,61 +160,28 @@ func (env *environment) getPlatform() string { } func (env *environment) runCommand(command string, args ...string) (string, error) { - getOutputString := func(io io.ReadCloser) string { - output := new(bytes.Buffer) - defer output.Reset() - buf := bufio.NewReader(io) - multiline := false - for { - line, _, _ := buf.ReadLine() - if line == nil { - break - } - if multiline { - output.WriteString("\n") - } - output.Write(line) - multiline = true - } - return output.String() + cleanOutput := func(output string) string { + return strings.TrimSuffix(output, "\n") } - cmd := exec.Command(command, args...) - stdout, err := cmd.StdoutPipe() - if err != nil { + commandC := C.CString(command) + defer C.free(unsafe.Pointer(commandC)) + var argsC *C.char + if args != nil { + argsJoined := strings.Join(args, ";") + argsC = C.CString(argsJoined) + defer C.free(unsafe.Pointer(argsC)) + } + response := C.getCommandOutput(commandC, argsC) + defer C.DestroyResponse(response) + output := C.GoString(response.output) + err := C.GoString(response.err) + if err != "" { return "", &commandError{ - err: err.Error(), - exitCode: 666, + err: cleanOutput(err), + exitCode: int(response.status_code), } } - stderr, err := cmd.StderrPipe() - if err != nil { - return "", &commandError{ - err: err.Error(), - exitCode: 667, - } - } - err = cmd.Start() - if err != nil { - return "", &commandError{ - err: err.Error(), - exitCode: 668, - } - } - defer func() { - _ = cmd.Process.Kill() - }() - stdoutString := getOutputString(stdout) - stderrString := getOutputString(stderr) - if stderrString != "" { - // only wait in case of error reduces the lead time on successful - // commands on windows due to not calling process.Wait() - _ = cmd.Wait() - return "", &commandError{ - err: stderrString, - exitCode: cmd.ProcessState.ExitCode(), - } - } - return stdoutString, nil + return cleanOutput(output), nil } func (env *environment) runShellCommand(shell, command string) string {