package shell import ( "errors" "fmt" "os" "os/exec" "syscall" "go.wit.com/log" ) func Exec(args []string) error { if len(args) == 0 { return errors.New("Error: Command slice is empty.") } // Start a long-running process, capture stdout and stderr a, b := RemoveFirstElement(args) process := exec.Command(a, b...) process.Stderr = os.Stderr process.Stdin = os.Stdin process.Stdout = os.Stdout process.Start() err := process.Wait() log.Log(INFO, "shell.Exec() err =", err) return nil } func ExecCheck(args []string) error { if len(args) == 0 { return errors.New("Error: Command slice is empty.") } // Start a long-running process, capture stdout and stderr a, b := RemoveFirstElement(args) process := exec.Command(a, b...) process.Stderr = os.Stderr process.Stdin = os.Stdin process.Stdout = os.Stdout err := process.Run() if err != nil { log.Info("ExecCheck() err", err) return err } // log.Info("ExecCheck() nil") return nil } func PathExecVerbose(path string, args []string) error { if len(args) == 0 { return errors.New("Error: Command slice is empty.") } // Start a long-running process, capture stdout and stderr a, b := RemoveFirstElement(args) process := exec.Command(a, b...) process.Dir = path process.Stderr = os.Stderr process.Stdin = os.Stdin process.Stdout = os.Stdout err := process.Run() if err != nil { log.Info("ExecCheck() err", err) return err } // log.Info("ExecCheck() nil") return nil } func SudoRaw(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 Sudo(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 }