package sys import ( "fmt" "io" "os" "os/exec" "os/signal" "syscall" "golang.org/x/sys/unix" ) var TERM_WIDTH = 0 func RunCmd(cmd *exec.Cmd) int { cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return ManageStatusCmd(cmd, cmd.Run()) } func RunShellCmd(call string) int { cmd := exec.Command("sh", "-c", call) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return ManageStatusCmd(cmd, cmd.Run()) } func ManageStatusCmd(cmd *exec.Cmd, err error) int { if err == nil { return 0 } // Figure out the exit code if ws, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok { if ws.Exited() { return ws.ExitStatus() } if ws.Signaled() { return -int(ws.Signal()) } } return -1 } func RunInteractiveCmd(cmd string, withStderr bool) int { fmt.Printf(" == go before command : %s\n", cmd) icmd := exec.Command("bash", "-c", cmd) icmd.Stdin = os.Stdin icmd.Stdout = os.Stdout if withStderr { icmd.Stderr = os.Stderr } return ManageStatusCmd(icmd, icmd.Run()) } func PipeCmd(cmd1 *exec.Cmd, cmd2 *exec.Cmd, buffers ...io.Writer) { fmt.Println("> Pipe Commands") if len(buffers) > 0 { pr, pw := io.Pipe() cmd1.Stdout = pw cmd2.Stdin = pr cmd2.Stdout = buffers[0] if len(buffers) > 1 { cmd2.Stderr = buffers[1] } cmd1.Start() cmd2.Start() go func() { defer pw.Close() err1 := cmd1.Wait() if err1 != nil { fmt.Printf("error1 : %v\n", err1) } }() err2 := cmd2.Wait() if err2 != nil { fmt.Printf("error2 : %v\n", err2) } fmt.Println("< Pipe Commands") } } func UpdateTermSize() error { ws, err := unix.IoctlGetWinsize(syscall.Stdout, unix.TIOCGWINSZ) if err != nil { return err } TERM_WIDTH = int(ws.Col) return nil } func HandleTermChange() { // set signal handler sigwinch := make(chan os.Signal, 1) defer close(sigwinch) signal.Notify(sigwinch, syscall.SIGWINCH) go func() { for { if _, ok := <-sigwinch; !ok { return } _ = UpdateTermSize() fmt.Printf("TERM WIDTH : %d\n", TERM_WIDTH) } }() } func HandleSigKill() { done := make(chan os.Signal, 1) defer close(done) signal.Notify(done, syscall.SIGINT, syscall.SIGTERM) go func() { <-done // Will block here until user hits ctrl+c cmd := exec.Command("tput", "cnorm") RunCmd(cmd) cmd = exec.Command("tput", "-x", "clear") RunCmd(cmd) os.Exit(0) }() }