From c9df5a7aceaecd7d2f022a6ebccc7b8a9909059b Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Thu, 15 Feb 2024 22:52:11 -0600 Subject: [PATCH] start deprecating and modernizing this code --- Makefile | 1 + openBrowser.go | 18 ------- proc.go | 57 ++++++++++++++++++++ run.go | 58 +++++++++++++++++--- structs.go | 9 ++-- xterm.go | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 253 insertions(+), 30 deletions(-) create mode 100644 proc.go create mode 100644 xterm.go diff --git a/Makefile b/Makefile index b4b840c..77b1bcb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ all: + GO111MODULE=off go build goimports: goimports -w *.go diff --git a/openBrowser.go b/openBrowser.go index 2977cef..23dbbf6 100644 --- a/openBrowser.go +++ b/openBrowser.go @@ -3,8 +3,6 @@ package shell import ( "os/exec" "runtime" - - "go.wit.com/log" ) // openBrowser opens the specified URL in the default browser of the user. @@ -24,19 +22,3 @@ func OpenBrowser(url string) error { args = append(args, url) return exec.Command(cmd, args...).Start() } - -func Xterm(cmd string) { - var tmp []string - var argsXterm = []string{"nohup", "xterm", "-geometry", "120x40"} - /* - if xtermHold.Checked() { - log.Println("hold = true") - argsXterm = append(argsXterm, "-hold") - } else { - log.Println("hold = false") - } - */ - tmp = append(argsXterm, "-e", cmd) - log.Info("xterm cmd=", tmp) - go Run(tmp) -} diff --git a/proc.go b/proc.go new file mode 100644 index 0000000..d78fbcf --- /dev/null +++ b/proc.go @@ -0,0 +1,57 @@ +package shell + +import ( + "fmt" + "io/ioutil" + "strconv" + "strings" +) + +// get your parent PID +func GetPPID(pid int) (int, error) { + data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) + if err != nil { + return 0, err + } + + parts := strings.Fields(string(data)) + if len(parts) < 4 { + return 0, fmt.Errorf("unexpected format of /proc/%d/stat", pid) + } + + ppid, err := strconv.Atoi(parts[3]) + if err != nil { + return 0, err + } + + return ppid, nil +} + +// get comm from proc +func GetComm(pid int) (string, error) { + data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/comm", pid)) + if err != nil { + return "", err + } + + return strings.TrimSpace(string(data)), nil +} + +/* +func main() { + pid := os.Getpid() + ppid, err := getPPID(pid) + if err != nil { + fmt.Println("Error getting PPID:", err) + return + } + + comm, err := getComm(ppid) + if err != nil { + fmt.Println("Error getting comm:", err) + return + } + + fmt.Println(comm) +} +*/ diff --git a/run.go b/run.go index a239d88..79f1214 100644 --- a/run.go +++ b/run.go @@ -30,7 +30,7 @@ func RunCapture(cmdline string) string { return Chomp(test.Buffer) } -func RunWait(args []string) *Shell { +func RunWait(args []string) *OldShell { test := New() cmdline := strings.Join(args, " ") test.Exec(cmdline) @@ -86,7 +86,7 @@ func RunPath(path string, args []string) bool { return true } -func (cmd *Shell) Run(cmdline string) string { +func (cmd *OldShell) Run(cmdline string) string { cmd.InitProcess(cmdline) if cmd.Error != nil { return "" @@ -95,7 +95,7 @@ func (cmd *Shell) Run(cmdline string) string { return Chomp(cmd.Buffer) } -func (cmd *Shell) InitProcess(cmdline string) { +func (cmd *OldShell) InitProcess(cmdline string) { log.Log(RUN, "shell.InitProcess() START "+cmdline) cmd.Cmdline = Chomp(cmdline) // this is like 'chomp' in perl @@ -118,7 +118,7 @@ func (cmd *Shell) InitProcess(cmdline string) { cmd.Process = exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) } -func (cmd *Shell) FileCreate(out string) { +func (cmd *OldShell) FileCreate(out string) { var newfile File var iof io.ReadCloser @@ -141,7 +141,7 @@ func (cmd *Shell) FileCreate(out string) { // NOTE: this might cause problems: // always remove the newlines at the end ? -func (cmd *Shell) Exec(cmdline string) { +func (cmd *OldShell) Exec(cmdline string) { log.Log(RUN, "shell.Run() START "+cmdline) cmd.InitProcess(cmdline) @@ -179,7 +179,7 @@ func (cmd *Shell) Exec(cmdline string) { } // nonblocking read until file errors -func (cmd *Shell) Capture(f *File) { +func (cmd *OldShell) Capture(f *File) { log.Log(RUN, "nbrREADER() START") if cmd.Buffer == nil { @@ -211,7 +211,7 @@ func (cmd *Shell) Capture(f *File) { } // returns true if filehandle buffer is empty -func (cmd *Shell) ReadToBuffer(f *File) bool { +func (cmd *OldShell) ReadToBuffer(f *File) bool { log.Log(RUN, "ReadToBuffer() START") nbr := f.Fnbreader oneByte := make([]byte, 1024) @@ -282,7 +282,6 @@ func RunCmd(workingpath string, parts []string) (error, bool, string) { log.Warn("output was", string(output)) log.Warn("cmd exited with error", err) // panic("fucknuts") - return err, false, string(output) // The command failed (non-zero exit status) if exitErr, ok := err.(*exec.ExitError); ok { @@ -293,6 +292,7 @@ func RunCmd(workingpath string, parts []string) (error, bool, string) { } else { log.Warn("cmd.Run() failed with %s\n", err) } + return err, false, string(output) } tmp := string(output) @@ -301,3 +301,45 @@ func RunCmd(workingpath string, parts []string) (error, bool, string) { // Print the output return nil, true, tmp } + +// send the path and the command +func RunCmdRun(workingpath string, parts []string) error { + if len(parts) == 0 { + log.Warn("command line was empty") + return errors.New("empty") + } + if parts[0] == "" { + log.Warn("command line was empty") + return errors.New("empty") + } + thing := parts[0] + parts = parts[1:] + log.Log(INFO, "working path =", workingpath, "thing =", thing, "cmdline =", parts) + + // Create the command + cmd := exec.Command(thing, parts...) + + // Set the working directory + cmd.Dir = workingpath + + // Execute the command + err := cmd.Run() + if err != nil { + log.Warn("ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts) + log.Error(err) + log.Warn("cmd exited with error", err) + // panic("fucknuts") + + // The command failed (non-zero exit status) + if exitErr, ok := err.(*exec.ExitError); ok { + // Assert that it is an exec.ExitError and get the exit code + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { + log.Warn("Exit Status: %d\n", status.ExitStatus()) + } + } else { + log.Warn("cmd.Run() failed with %s\n", err) + } + return err + } + return nil +} diff --git a/structs.go b/structs.go index c250fcf..bf31186 100644 --- a/structs.go +++ b/structs.go @@ -27,7 +27,8 @@ type File struct { Fnbreader *nbreader.NBReader // := nbreader.NewNBReader(readOUT, 1024) } -type Shell struct { +// early code playground +type OldShell struct { Cmdline string Process *exec.Cmd Done bool @@ -45,9 +46,9 @@ type Shell struct { Stderr *File } -// default values for Shell -func New() *Shell { - var tmp Shell +// default values for OldShell +func New() *OldShell { + var tmp OldShell tmp.Done = false tmp.Fail = false diff --git a/xterm.go b/xterm.go new file mode 100644 index 0000000..d51cc96 --- /dev/null +++ b/xterm.go @@ -0,0 +1,140 @@ +package shell + +import ( + "fmt" + "os" + "strings" + + "go.wit.com/log" +) + +func scanToParent(pid int) (bool, string) { + ppid, err := GetPPID(pid) + if err != nil { + fmt.Println("Error getting PPID:", err) + return true, "" + } + + comm, err := GetComm(ppid) + if err != nil { + fmt.Println("Error getting comm:", err) + return true, "" + } + + log.Info("scanToParent() found:", comm) + + // if this is an xterm + switch comm { + case "xterm": + return true, "xterm" + case "mate-terminal": + return true, "mate-terminal" + case "bash": + // keep digging for the parent xterm + return scanToParent(ppid) + case "make": + // keep digging for the parent xterm + return scanToParent(ppid) + default: + return false, comm + } + if comm == "bash" { + } + + ok, better := scanToParent(ppid) + if ok { + return ok, better + } + if better == "" { + // if the parent was blank, at least return the something that we have + // since something is better than nothing + return false, comm + } + return ok, better +} + +// returns a string of the xterm the user is using +// for example, "xterm" or "mate-terminal" +func Terminal() string { + pid := os.Getpid() + _, comm := scanToParent(pid) + /* + ppid, err := GetPPID(pid) + if err != nil { + fmt.Println("Error getting PPID:", err) + return "" + } + + comm, err := GetComm(ppid) + if err != nil { + fmt.Println("Error getting comm:", err) + return "" + } + */ + + return comm +} + +// returns a string of the shell the user is using +func Shell() string { + envsh := os.Getenv("SHELL") + switch envsh { + case "/bin/bash": + return "bash" + default: + return envsh + } + return envsh +} + +func getXtermCmd(cmd []string) []string { + var term string + // doesn't work yet + // term = Terminal() + term = "xterm" + switch term { + case "mate-terminal": + newcmd := []string{"mate-terminal", "-e"} + newcmd = append(newcmd, cmd...) + return newcmd + default: + // unknown terminal. use xterm + newcmd := []string{"xterm", "-geometry", "140x32", "-e", "bash", "-c"} + // fix/shell escape sequence this for quote chars, etc + // tmp := "\"" + strings.Join(cmd, " ") + ";bash\"" + newcmd = append(newcmd, cmd...) + // newcmd = append(newcmd, cmd...) + return newcmd + } +} + +// spawns an xterm with something you can run at a command line +func XtermCmd(path string, cmd []string) { + go XtermCmdWait(path, cmd) +} + +// runs an xterm +// waits until xterm exits +func XtermCmdWait(path string, cmd []string) { + var argsXterm = getXtermCmd(cmd) + + log.Info("XtermCmd() path =", path, "cmd =", argsXterm) + + // keeps git diff from exiting on small diffs + os.Setenv("LESS", "-+F -+X -R") + + RunCmdRun(path, argsXterm) +} + +// spawns an xterm with something you can run at a command line +// then executes bash +func XtermCmdBash(path string, cmd []string) { + var tmp []string + var argsXterm = getXtermCmd(cmd) + bash := "\"-c '" + bash += strings.Join(cmd, " ") + bash += "'; bash\"" + tmp = append(argsXterm, "bash", bash) + log.Info("XtermCmd() path =", path, "cmd =", tmp) + go RunCmd(path, tmp) +}