Skip to content

Instantly share code, notes, and snippets.

@Luigi-Pizzolito
Created February 11, 2024 20:03
Show Gist options
  • Save Luigi-Pizzolito/d14c9bca1cd689fe86824c3dc043e13a to your computer and use it in GitHub Desktop.
Save Luigi-Pizzolito/d14c9bca1cd689fe86824c3dc043e13a to your computer and use it in GitHub Desktop.
Embeds the entire ./bin folder into the go executable. At run time, extracts ./bin to temporary directory and calls your_executable with any dynamic libraries in ./bin. Also provides method for passing input+\n to stdin.
package main
import (
"embed"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"bytes"
"fmt"
)
//go:embed bin/*
var embeddedBinaries embed.FS
func main() {
// Create a temporary directory to extract files
tmpDir, err := ioutil.TempDir("", "extracted_files")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpDir)
// Extract files from embedded resources
extractFiles(tmpDir)
fmt.Println("Extracted!", tmpDir)
// Set LD_LIBRARY_PATH to include the extracted shared library
ldLibraryPath := tmpDir
os.Setenv("LD_LIBRARY_PATH", ldLibraryPath)
// Execute the binary
binaryPath := filepath.Join(tmpDir, "your_executable")
// Set execute permission on the binary file
if err = os.Chmod(binaryPath, 0755); err != nil {
panic("Error setting execute permission on binary file: "+err.Error())
}
fmt.Println("running!")
RunWithStdinNReturn("input to program here!", binaryPath)
}
func extractFiles(destinationDir string) {
// List the contents of the embedded bin directory
entries, err := embeddedBinaries.ReadDir("bin")
if err != nil {
panic(err)
}
// Loop through each entry and extract it
for _, entry := range entries {
src := filepath.Join("bin", entry.Name())
dst := filepath.Join(destinationDir, entry.Name())
// Read the file content
content, err := embeddedBinaries.ReadFile(src)
if err != nil {
panic(err)
}
// Write the file content to the destination
if err := ioutil.WriteFile(dst, content, 0644); err != nil {
panic(err)
}
}
}
func RunWithStdinNReturn(stringin, binaryPath string) (string, error) {
// Create the command with the desired command and arguments
cmd := exec.Command(binaryPath)
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
// if err := cmd.Run(); err != nil {
// panic(err)
// }
// Get a pipe to the command's stdin
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Println("Error obtaining stdin pipe:", err)
return "", err
}
// Get a pipe to capture the command's stdout
var stdout bytes.Buffer
cmd.Stdout = &stdout
// Start the command
err = cmd.Start()
if err != nil {
fmt.Println("Error starting command:", err)
return "", err
}
// Write the string followed by a newline to stdin
_, err = fmt.Fprintf(stdin, stringin+"\n")
if err != nil {
fmt.Println("Error writing to stdin:", err)
return "", err
}
// Close stdin to indicate that we're done writing
stdin.Close()
// Wait for the command to finish
err = cmd.Wait()
if err != nil {
fmt.Println("Command finished with error:", err)
return "", err
}
// Print the stdout of the command
fmt.Println("Command output:", stdout.String())
return stdout.String(), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment