summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildPlugin.go3
-rw-r--r--install_linux.go6
-rw-r--r--run.go101
-rw-r--r--sudo.go7
-rw-r--r--sudo_darwin.go12
-rw-r--r--sudo_linux.go62
-rw-r--r--sudo_windows.go12
7 files changed, 198 insertions, 5 deletions
diff --git a/buildPlugin.go b/buildPlugin.go
index 6dbe187..c0c100e 100644
--- a/buildPlugin.go
+++ b/buildPlugin.go
@@ -1,7 +1,6 @@
package fhelp
import (
- "go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
@@ -28,7 +27,7 @@ func BuildPlugin(pname string) bool {
if !QuestionUser("Would you like to run that now?") {
return false
}
- r := shell.RunRealtime(cmd)
+ r := RunRealtime(cmd)
if r.Error == nil {
log.Info("build worked")
log.Info("You must copy that file to ~/go/lib/go-gui/")
diff --git a/install_linux.go b/install_linux.go
index 0ed600b..f86946a 100644
--- a/install_linux.go
+++ b/install_linux.go
@@ -8,7 +8,6 @@ import (
"os"
"strings"
- "go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
@@ -27,8 +26,9 @@ func osInstall(pkg string) error {
line = strings.ToLower(line)
switch line {
case "y":
- shell.Sudo(cmd)
- return nil
+ log.Info("todo: fix this")
+ Sudo(cmd)
+ return log.Errorf("user didn't install package %s", pkg)
default:
}
}
diff --git a/run.go b/run.go
new file mode 100644
index 0000000..5fbeb7c
--- /dev/null
+++ b/run.go
@@ -0,0 +1,101 @@
+package fhelp
+
+import (
+ "errors"
+ "time"
+
+ "github.com/go-cmd/cmd"
+ "go.wit.com/log"
+)
+
+func RunRealtime(args []string) cmd.Status {
+ return PathRunRealtime("", args)
+}
+
+// this is stuff from a long time ago that there must be a replacement for
+func RemoveFirstElement(slice []string) (string, []string) {
+ if len(slice) == 0 {
+ return "", slice // Return the original slice if it's empty
+ }
+ return slice[0], slice[1:] // Return the slice without the first element
+}
+
+// echos twice a second if anything sends to STDOUT or STDERR
+// not great, but it's really just for watching things run in real time anyway
+// TODO: fix \r handling for things like git-clone so the terminal doesn't
+// have to do a \n newline each time.
+// TODO: add timeouts and status of things hanging around forever
+func PathRunRealtime(pwd string, args []string) cmd.Status {
+ // Check if the slice has at least one element (the command name)
+ if len(args) == 0 {
+ var s cmd.Status
+ s.Error = errors.New("Error: Command slice is empty.")
+ return s
+ }
+
+ // Start a long-running process, capture stdout and stderr
+ a, b := RemoveFirstElement(args)
+ findCmd := cmd.NewCmd(a, b...)
+ if pwd != "" {
+ findCmd.Dir = pwd
+ }
+ statusChan := findCmd.Start() // non-blocking
+
+ ticker := time.NewTicker(100 * time.Microsecond)
+
+ // this is interesting, maybe useful, but wierd, but neat. interesting even
+ // Print last line of stdout every 2s
+ go func() {
+ // loop very quickly, but only print the line if it changes
+ var lastout string
+ var lasterr string
+ for range ticker.C {
+ status := findCmd.Status()
+ n := len(status.Stdout)
+ if n != 0 {
+ newline := status.Stdout[n-1]
+ if lastout != newline {
+ lastout = newline
+ log.Info(lastout)
+ }
+ }
+ n = len(status.Stderr)
+ if n != 0 {
+ newline := status.Stderr[n-1]
+ if lasterr != newline {
+ lasterr = newline
+ log.Info(lasterr)
+ }
+ }
+ if status.Complete {
+ return
+ }
+ }
+ }()
+
+ // Stop command after 1 hour
+ go func() {
+ <-time.After(1 * time.Hour)
+ findCmd.Stop()
+ }()
+
+ // Check if command is done
+ select {
+ case finalStatus := <-statusChan:
+ log.Info("finalStatus =", finalStatus.Exit, finalStatus.Error)
+ return finalStatus
+ // done
+ default:
+ // no, still running
+ }
+
+ // Block waiting for command to exit, be stopped, or be killed
+ // there are things being left around here. debug this
+ finalStatus := <-statusChan
+ if len(finalStatus.Cmd) != 0 {
+ if string(finalStatus.Cmd) != "go" {
+ log.Info("shell.Run() ok goroutine end?", finalStatus.Cmd, finalStatus.Exit)
+ }
+ }
+ return findCmd.Status()
+}
diff --git a/sudo.go b/sudo.go
new file mode 100644
index 0000000..450e680
--- /dev/null
+++ b/sudo.go
@@ -0,0 +1,7 @@
+package fhelp
+
+// auto run protoc with the correct args
+
+func Sudo(cmd []string) error {
+ return osSudo(cmd)
+}
diff --git a/sudo_darwin.go b/sudo_darwin.go
new file mode 100644
index 0000000..4e082ec
--- /dev/null
+++ b/sudo_darwin.go
@@ -0,0 +1,12 @@
+package fhelp
+
+// auto run protoc with the correct args
+
+import (
+ "go.wit.com/log"
+)
+
+func osSudo(cmd []string) error {
+ log.Info("todo: add instructions on macos to sudo")
+ return log.Errorf("no sudo")
+}
diff --git a/sudo_linux.go b/sudo_linux.go
new file mode 100644
index 0000000..0ef3995
--- /dev/null
+++ b/sudo_linux.go
@@ -0,0 +1,62 @@
+package fhelp
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "syscall"
+)
+
+func osSudoRaw(c []string) {
+ args := []string{"-S"}
+ args = append(args, c...)
+ cmd := exec.Command("sudo", args...)
+
+ // Assign the current process's standard input, output, and error
+ cmd.Stderr = os.Stderr
+ cmd.Stdout = os.Stdout
+ cmd.Stdin = os.Stdin
+
+ // Ensure the process has a terminal session
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Setsid: true, // Start a new session
+ }
+
+ err := cmd.Run()
+ if err != nil {
+ fmt.Println("Command execution failed:", err)
+ }
+}
+
+func osSudo(c []string) error {
+ args := []string{"-S"}
+ // args := []string{}
+ args = append(args, c...)
+ cmd := exec.Command("sudo", args...)
+
+ // Open the terminal device directly to preserve input/output control
+ tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
+ if err != nil {
+ fmt.Println("Failed to open /dev/tty:", err)
+ return err
+ }
+ defer tty.Close()
+
+ // Assign the TTY explicitly
+ cmd.Stdin = tty
+ cmd.Stdout = tty
+ cmd.Stderr = tty
+
+ // Ensure the new process gets its own session
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Setsid: true, // Start a new session
+ }
+
+ // Run the command
+ if err := cmd.Run(); err != nil {
+ fmt.Println("Command execution failed:", err)
+ }
+
+ fmt.Println("\nProcess finished. TTY restored.")
+ return nil
+}
diff --git a/sudo_windows.go b/sudo_windows.go
new file mode 100644
index 0000000..cad5936
--- /dev/null
+++ b/sudo_windows.go
@@ -0,0 +1,12 @@
+package fhelp
+
+// auto run protoc with the correct args
+
+import (
+ "go.wit.com/log"
+)
+
+func osSudo(cmd []string) error {
+ log.Info("todo: add instructions on windows to sudo")
+ return log.Errorf("user needs root")
+}