package main
import "C"
import (
"encoding/json"
"fmt"
"os"
"unsafe"
)
func lastError() string {
errPtr := C.rust_bash_last_error()
if errPtr == nil {
return "unknown error"
}
return C.GoString(errPtr)
}
func execCommand(sb *C.struct_RustBash, command string) (string, string, int, error) {
cCmd := C.CString(command)
defer C.free(unsafe.Pointer(cCmd))
result := C.rust_bash_exec(sb, cCmd)
if result == nil {
return "", "", -1, fmt.Errorf("exec failed: %s", lastError())
}
defer C.rust_bash_result_free(result)
stdout := C.GoStringN(result.stdout_ptr, C.int(result.stdout_len))
stderr := C.GoStringN(result.stderr_ptr, C.int(result.stderr_len))
exitCode := int(result.exit_code)
return stdout, stderr, exitCode, nil
}
func main() {
version := C.GoString(C.rust_bash_version())
fmt.Printf("rust-bash version: %s\n\n", version)
config := map[string]interface{}{
"files": map[string]string{
"/hello.txt": "Hello from Go!",
"/data.csv": "name,age\nAlice,30\nBob,25\n",
},
"env": map[string]string{
"GREETING": "Hi there",
"APP_MODE": "demo",
},
"cwd": "/",
}
configJSON, err := json.Marshal(config)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to marshal config: %v\n", err)
os.Exit(1)
}
cConfig := C.CString(string(configJSON))
defer C.free(unsafe.Pointer(cConfig))
sb := C.rust_bash_create(cConfig)
if sb == nil {
fmt.Fprintf(os.Stderr, "Failed to create sandbox: %s\n", lastError())
os.Exit(1)
}
defer C.rust_bash_free(sb)
fmt.Println("--- cat /hello.txt ---")
stdout, _, exitCode, err := execCommand(sb, "cat /hello.txt")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("stdout: %q\n", stdout)
fmt.Printf("exit code: %d\n\n", exitCode)
fmt.Println("--- echo $GREETING ---")
stdout, _, _, err = execCommand(sb, "echo $GREETING")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("stdout: %q\n\n", stdout)
fmt.Println("--- text processing pipeline ---")
stdout, _, _, err = execCommand(sb, "cat /data.csv | grep -v name | sort")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("stdout: %q\n\n", stdout)
fmt.Println("--- state persistence ---")
_, _, _, err = execCommand(sb, "MY_VAR=42")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
stdout, _, _, err = execCommand(sb, "echo $MY_VAR")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("MY_VAR = %q\n\n", stdout)
fmt.Println("--- stderr capture ---")
_, stderr, _, err := execCommand(sb, "echo 'this is stderr' >&2")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("stderr: %q\n\n", stderr)
fmt.Println("--- non-zero exit ---")
_, _, exitCode, err = execCommand(sb, "exit 42")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
fmt.Printf("exit code: %d\n\n", exitCode)
fmt.Println("--- error handling ---")
badConfig := C.CString("not valid json")
defer C.free(unsafe.Pointer(badConfig))
badSb := C.rust_bash_create(badConfig)
if badSb == nil {
fmt.Printf("Expected error: %s\n\n", lastError())
} else {
C.rust_bash_free(badSb)
}
fmt.Println("All examples completed successfully!")
}