Last active
March 13, 2022 01:53
-
-
Save hhsprings/4f181f3aaf19543a02baffa3cdac8688 to your computer and use it in GitHub Desktop.
A program that mimics the target application (EXE) on Windows. It is supposed to be used by hard linking with the same name as the target application.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"io" | |
"os" | |
"os/exec" | |
"text/template" | |
"bytes" | |
"strings" | |
"regexp" | |
"path/filepath" | |
"fmt" | |
"reflect" | |
"github.com/clbanning/mxj/v2" | |
) | |
const ( | |
CONF_DEFAULT = `{{/* | |
configuration of exemimicry.go. | |
basically this file is a json-like format. | |
*/}} | |
{ | |
"ll": { | |
"prog": "ls", | |
"args": [["-l", "--color=always"], []] | |
}, | |
"ffmpeg": { | |
"prog": "ffmpeg", | |
"args": [["-hide_banner"], ["-c:v", "libx265"]] | |
}, | |
"ffplay": { | |
"prog": "ffplay", | |
"args": [["-hide_banner"], ["-autoexit"]] | |
} | |
} | |
` | |
) | |
func getcmdl() (string, []string) { | |
mypath, _ := filepath.Abs(filepath.Clean(os.Args[0])) | |
mypath_noext := mypath[:len(mypath) - len(filepath.Ext(mypath))] | |
mypath_noext = filepath.ToSlash(mypath_noext) | |
basename := filepath.Base(mypath_noext) | |
// | |
getconf := func () string { | |
home := os.Getenv("USERPROFILE") | |
if home == "" { | |
home = os.Getenv("HOME") | |
} | |
confpath := filepath.Join(home, ".exemimicry.go.conf.json") | |
_, err := os.Stat(confpath) | |
var f *os.File | |
if err != nil { | |
f, _ = os.OpenFile(confpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0744) | |
fmt.Fprintf(f, "%s\n", CONF_DEFAULT) | |
f.Close() | |
} | |
f, _ = os.Open(confpath) | |
defer f.Close() | |
cont, _ := io.ReadAll(f) | |
return string(cont) | |
} | |
conftmpl, err := template.New("exemimicryconf").Parse(getconf()) | |
if err != nil { | |
panic(err) | |
} | |
var tmplout bytes.Buffer | |
var data interface{} | |
err = conftmpl.Execute(&tmplout, data) | |
if err != nil { | |
panic(err) | |
} | |
conf, err := mxj.NewMapJson([]byte(tmplout.String())) | |
if err != nil { | |
panic(err) | |
} | |
tosarr := func (v interface{}) []string { | |
resi := reflect.ValueOf(v) | |
var res []string | |
for i := 0; i < resi.Len(); i++ { | |
res = append(res, fmt.Sprint(resi.Index(i))) | |
} | |
return res | |
} | |
hasExt := func (file string) bool { | |
i := strings.LastIndex(file, ".") | |
if i < 0 { | |
return false | |
} | |
return strings.LastIndexAny(file, `:\/`) < i | |
} | |
getexts := func (prog string) []string { | |
if hasExt(prog) { | |
return []string{""} | |
} | |
var exts []string | |
x := os.Getenv(`PATHEXT`) | |
if x != "" { | |
for _, e := range strings.Split(strings.ToLower(x), `;`) { | |
if e == "" { | |
continue | |
} | |
if e[0] != '.' { | |
e = "." + e | |
} | |
exts = append(exts, e) | |
} | |
} else { | |
exts = []string{".com", ".exe", ".bat", ".cmd"} | |
} | |
return exts | |
} | |
findExecutable := func (prog string) string { | |
if filepath.IsAbs(prog) { | |
return prog | |
} | |
for _, dir := range filepath.SplitList(os.Getenv("path")) { | |
dir, _ = filepath.Abs(dir) | |
dir = filepath.Clean(dir) | |
for _, e := range getexts(prog) { | |
if e != "" && e[0] != '.' { | |
e = "." + e | |
} | |
fwh := filepath.Join(dir, prog + e) | |
if fwh == mypath { | |
continue | |
} | |
_, sterr := os.Stat(fwh) | |
if sterr == nil { | |
return fwh | |
} | |
} | |
} | |
panic(fmt.Sprintf("findExecutable: unknown command (%s)", prog)) | |
} | |
revertMsysroot := func (argn string) string { | |
return regexp.MustCompile(`^[a-zA-Z]:/.*/msys/1.0/`).ReplaceAllString(argn, "/") | |
} | |
var args []string | |
var targetexe string | |
var revert_msysroot bool | |
if conf[basename] != nil { | |
m := conf[basename].(map[string]interface{}) | |
prog := m["prog"].(string) | |
argsi := m["args"].([]interface{}) | |
pre := tosarr(argsi[0]) | |
post := tosarr(argsi[1]) | |
targetexe = findExecutable(prog) | |
args = append(args, pre...) | |
args = append(args, os.Args[1:]...) | |
args = append(args, post...) | |
if m["revert_msysroot"] != nil { | |
revert_msysroot = m["revert_msysroot"].(bool) | |
} | |
} else { | |
targetexe = findExecutable(basename) | |
args = os.Args[1:] | |
} | |
if revert_msysroot { | |
for i, _ := range args { | |
args[i] = revertMsysroot(args[i]) | |
} | |
} | |
progext := strings.ToLower(filepath.Ext(targetexe)) | |
if progext == ".bat" || progext == ".cmd" { | |
return "cmd.exe", append([]string{"/c", targetexe}, args...) | |
} | |
if progext == ".vbs" || | |
progext == ".js" || | |
progext == ".vbe" /* encoded. (I haven't tested this.) */ || | |
progext == ".jse" /* encoded. (I haven't tested this.) */ || | |
progext == ".wsf" || progext == ".wsh" { | |
// FIXME: Would you love to use "wscript.exe"? | |
return "cscript.exe", append([]string{"/nologo", targetexe}, args...) | |
} | |
if progext == ".msc" { | |
return "mmc.exe", append([]string{targetexe}, args...) | |
} | |
return targetexe, args | |
} | |
func main() { | |
shell, args := getcmdl() | |
cmd := exec.Command(shell, args...) | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
cmd.Stdin = os.Stdin | |
cmd.Run() | |
os.Exit(cmd.ProcessState.ExitCode()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment