// Package exe provides a mechanism for executing system commands.
package exe
import (
"fmt"
"log"
"os"
"os/exec"
"strings"
)
// ExeCtx represents the context needed for program execution.
type ExeCtx struct {
Args []string
Command string
EnvName string
EnvVars []string
Prefix string
Displays map[string]string
Stderr *os.File
Stdout *os.File
Suffix string
Title string
WorkDir string
}
func (ec *ExeCtx) Execute() error {
var c *exec.Cmd
var cmnd string
var args []string
if ec.Prefix != "" {
prefix := strings.Split(ec.Prefix, " ")
p, a := prefix[0], prefix[1:]
cmnd = p
if len(prefix) > 1 {
args = append(args, a...)
}
args = append(args, ec.Command)
args = append(args, ec.Args...)
} else {
cmnd = ec.Command
args = append(args, ec.Args...)
}
c = exec.Command(cmnd)
c.Args = append(c.Args, args...)
c.Dir = ec.WorkDir
c.Stderr = ec.Stderr
c.Stdout = ec.Stdout
c.Env = append(c.Env, ec.EnvVars...)
c.Env = append(c.Env, userEnv(ec.Command)...)
err := c.Run()
if err != nil {
return err
}
return nil
}
func QuickExe(cmnd string, args ...string) (string, error) {
c := exec.Command(cmnd, args...)
o, err := c.CombinedOutput()
if err != nil {
return "", err
}
return string(o), nil
}
func exePath(exeName string) (string, error) {
path, err := exec.LookPath(exeName)
if err != nil {
return "", err
}
return path, nil
}
func GenPrefix(wineExe, winePrefix, wineArch string) error {
wine, err := exePath("wine")
if err == nil {
wineExe = wine
} else {
log.Println("WARNING: New wine prefixes should be created with a system wine but WEM couldn't find one")
log.Println("WARNING: Proceeding anyways with the configured WineExe but please note that there may be issues with this prefix!")
}
c := exec.Command(wineExe, "WEMTEST")
devnull, err := os.Open(os.DevNull)
if err != nil {
return err
}
c.Stderr = devnull
c.Stdout = devnull
c.Env = append(c.Env, userEnv(wineExe)...)
c.Env = append(c.Env,
fmt.Sprintf("WINEPREFIX=%s", winePrefix),
fmt.Sprintf("WINEARCH=%s", wineArch),
)
// This will fail, but it will first create the prefix
_ = c.Run()
return nil
}
// userEnv provides key variables from the user's
// environment that are needed for wine to run.
func userEnv(cmnd string) []string {
return []string{
"DISPLAY=" + os.Getenv("DISPLAY"),
"HOME=" + os.Getenv("HOME"),
"PATH=" + os.Getenv("PATH"),
"XDG_RUNTIME_DIR=" + os.Getenv("XDG_RUNTIME_DIR"),
}
}