Skip to content

Instantly share code, notes, and snippets.

@fd0
Created January 17, 2018 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fd0/368f7139d43726a39b1046e49ba0e847 to your computer and use it in GitHub Desktop.
Save fd0/368f7139d43726a39b1046e49ba0e847 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"syscall"
"time"
"unsafe"
)
func Tcsetpgrp(fd int, pid int) error {
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(fd),
uintptr(syscall.TIOCSPGRP), uintptr(unsafe.Pointer(&pid)))
if errno == 0 {
return nil
}
return errno
}
func main() {
var err error
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0600)
if err != nil {
panic(err)
}
fmt.Printf("tty fd is %d\n", int(tty.Fd()))
pid := syscall.Getpid()
group := syscall.Getpgrp()
fmt.Printf("pid is %d, group is %d\n", pid, group)
cmd := exec.Command("ssh", "localhost", "echo 'remote: start'; sleep 20; echo 'remote: done'")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT)
signal.Ignore(syscall.SIGTTIN)
signal.Ignore(syscall.SIGTTOU)
go func() {
for sig := range ch {
fmt.Printf("main: signal received: %v\n", sig)
}
}()
err = cmd.Start()
if err != nil {
fmt.Printf("main: start returned err: %v\n", err)
}
fmt.Printf("switching foreground process group to %d\n", cmd.Process.Pid)
err = Tcsetpgrp(int(tty.Fd()), cmd.Process.Pid)
if err != nil {
panic(err)
}
time.Sleep(5 * time.Second)
err = Tcsetpgrp(int(tty.Fd()), group)
if err != nil {
panic(err)
}
fmt.Printf("switched foreground process group back to %d\n", group)
err = cmd.Wait()
if err != nil {
fmt.Printf("main: wait returned err: %v\n", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment