// +build !windows package code import ( "os" "syscall" ) // POSIX terminal mode flags as listed in RFC 4254 Section 8. const ( tty_OP_END = 0 VINTR = 1 VQUIT = 2 VERASE = 3 VKILL = 4 VEOF = 5 VEOL = 6 VEOL2 = 7 VSTART = 8 VSTOP = 9 VSUSP = 10 VDSUSP = 11 VREPRINT = 12 VWERASE = 13 VLNEXT = 14 VFLUSH = 15 VSWTCH = 16 VSTATUS = 17 VDISCARD = 18 IGNPAR = 30 PARMRK = 31 INPCK = 32 ISTRIP = 33 INLCR = 34 IGNCR = 35 ICRNL = 36 IUCLC = 37 IXON = 38 IXANY = 39 IXOFF = 40 IMAXBEL = 41 IUTF8 = 42 ISIG = 50 ICANON = 51 XCASE = 52 ECHO = 53 ECHOE = 54 ECHOK = 55 ECHONL = 56 NOFLSH = 57 TOSTOP = 58 IEXTEN = 59 ECHOCTL = 60 ECHOKE = 61 PENDIN = 62 OPOST = 70 OLCUC = 71 ONLCR = 72 OCRNL = 73 ONOCR = 74 ONLRET = 75 CS7 = 90 CS8 = 91 PARENB = 92 PARODD = 93 TTY_OP_ISPEED = 128 TTY_OP_OSPEED = 129 ) // struct termios { // tcflag_t c_iflag; /* input modes */ // tcflag_t c_oflag; /* output modes */ // tcflag_t c_cflag; /* control modes */ // tcflag_t c_lflag; /* local modes */ // cc_t c_cc[NCCS]; /* special characters */ // speed_t c_ispeed; // speed_t c_ospeed; // }; type Setter interface { Set(pty *os.File, termios *syscall.Termios, value uint32) error } var TermAttrSetters = map[uint8]Setter{ VINTR: &ccSetter{Character: syscall.VINTR}, VQUIT: &ccSetter{Character: syscall.VQUIT}, VERASE: &ccSetter{Character: syscall.VERASE}, VKILL: &ccSetter{Character: syscall.VKILL}, VEOF: &ccSetter{Character: syscall.VEOF}, VEOL: &ccSetter{Character: syscall.VEOL}, VEOL2: &ccSetter{Character: syscall.VEOL2}, VSTART: &ccSetter{Character: syscall.VSTART}, VSTOP: &ccSetter{Character: syscall.VSTOP}, VSUSP: &ccSetter{Character: syscall.VSUSP}, VDSUSP: &nopSetter{}, VREPRINT: &ccSetter{Character: syscall.VREPRINT}, VWERASE: &ccSetter{Character: syscall.VWERASE}, VLNEXT: &ccSetter{Character: syscall.VLNEXT}, VFLUSH: &nopSetter{}, VSWTCH: &nopSetter{}, VSTATUS: &nopSetter{}, VDISCARD: &ccSetter{Character: syscall.VDISCARD}, // Input modes IGNPAR: &iflagSetter{Flag: syscall.IGNPAR}, PARMRK: &iflagSetter{Flag: syscall.PARMRK}, INPCK: &iflagSetter{Flag: syscall.INPCK}, ISTRIP: &iflagSetter{Flag: syscall.ISTRIP}, INLCR: &iflagSetter{Flag: syscall.INLCR}, IGNCR: &iflagSetter{Flag: syscall.IGNCR}, ICRNL: &iflagSetter{Flag: syscall.ICRNL}, IUCLC: &nopSetter{}, IXON: &iflagSetter{Flag: syscall.IXON}, IXANY: &iflagSetter{Flag: syscall.IXANY}, IXOFF: &iflagSetter{Flag: syscall.IXOFF}, IMAXBEL: &iflagSetter{Flag: syscall.IMAXBEL}, IUTF8: &iflagSetter{Flag: syscall.IUTF8}, //IUTF8 // Local modes ISIG: &lflagSetter{Flag: syscall.ISIG}, ICANON: &lflagSetter{Flag: syscall.ICANON}, XCASE: &nopSetter{}, ECHO: &lflagSetter{Flag: syscall.ECHO}, ECHOE: &lflagSetter{Flag: syscall.ECHOE}, ECHOK: &lflagSetter{Flag: syscall.ECHOK}, ECHONL: &lflagSetter{Flag: syscall.ECHONL}, NOFLSH: &lflagSetter{Flag: syscall.NOFLSH}, TOSTOP: &lflagSetter{Flag: syscall.TOSTOP}, IEXTEN: &lflagSetter{Flag: syscall.IEXTEN}, ECHOCTL: &lflagSetter{Flag: syscall.ECHOCTL}, ECHOKE: &lflagSetter{Flag: syscall.ECHOKE}, PENDIN: &lflagSetter{Flag: syscall.PENDIN}, // Output modes OPOST: &oflagSetter{Flag: syscall.OPOST}, OLCUC: &nopSetter{}, ONLCR: &oflagSetter{Flag: syscall.ONLCR}, OCRNL: &oflagSetter{Flag: syscall.OCRNL}, ONOCR: &oflagSetter{Flag: syscall.ONOCR}, ONLRET: &oflagSetter{Flag: syscall.ONLRET}, // Control modes CS7: &cflagSetter{Flag: syscall.CS7}, CS8: &cflagSetter{Flag: syscall.CS8}, PARENB: &cflagSetter{Flag: syscall.PARENB}, PARODD: &cflagSetter{Flag: syscall.PARODD}, // Baud rates (ignore) TTY_OP_ISPEED: &nopSetter{}, TTY_OP_OSPEED: &nopSetter{}, } type nopSetter struct{} type ccSetter struct { Character uint8 } func (cc *ccSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { termios.Cc[cc.Character] = byte(value) return SetAttr(pty, termios) } func (i *iflagSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { if value == 0 { termios.Iflag &^= i.Flag } else { termios.Iflag |= i.Flag } return SetAttr(pty, termios) } func (l *lflagSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { if value == 0 { termios.Lflag &^= l.Flag } else { termios.Lflag |= l.Flag } return SetAttr(pty, termios) } func (o *oflagSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { if value == 0 { termios.Oflag &^= o.Flag } else { termios.Oflag |= o.Flag } return SetAttr(pty, termios) } func (c *cflagSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { switch c.Flag { // CSIZE is a field case syscall.CS7, syscall.CS8: termios.Cflag &^= syscall.CSIZE termios.Cflag |= c.Flag default: if value == 0 { termios.Cflag &^= c.Flag } else { termios.Cflag |= c.Flag } } return SetAttr(pty, termios) } func (n *nopSetter) Set(pty *os.File, termios *syscall.Termios, value uint32) error { return nil }