func record() { C.ttySave() defer C.ttyRestore() C.ttyRaw() master, slave, err := pty.Open() if err != nil { log.Fatalln("open:", err) } C.ttyFixWinsz(C.int(slave.Fd())) script, err := os.OpenFile("ttyrecord", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { log.Fatalln(err) } sh := os.Getenv("SHELL") if sh == "" { sh = "/bin/sh" } attr := &syscall.SysProcAttr{ Setsid: true, Setctty: true, Ctty: int(slave.Fd()), } shell := &exec.Cmd{ Path: sh, SysProcAttr: attr, Stdin: slave, Stdout: slave, Stderr: slave, } go io.Copy(master, os.Stdin) go io.Copy(io.MultiWriter(newGobWriter(script), os.Stdout), master) shell.Run() }
func replay() { C.ttySave() defer C.ttyRestore() C.ttyRaw() script, err := os.Open("ttyrecord") if err != nil { log.Fatalln(err) } var last time.Time dec := gob.NewDecoder(script) msg := &message{} for { if err := dec.Decode(msg); err != nil { break } if !last.IsZero() { wait := msg.T.Sub(last) <-time.After(wait) } last = msg.T os.Stdout.Write(msg.P) } }