//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package ssh

import (
	
	

	
	
	
	
)

type impl struct {
	// Master is the master PTY file descriptor.
	Master *os.File

	// Slave is the slave PTY file descriptor.
	Slave *os.File
}

func ( *impl) () bool {
	return .Master == nil && .Slave == nil
}

// Name returns the name of the slave PTY.
func ( *impl) () string {
	return .Slave.Name()
}

// Read implements ptyInterface.
func ( *impl) ( []byte) ( int,  error) {
	return .Master.Read()
}

// Write implements ptyInterface.
func ( *impl) ( []byte) ( int,  error) {
	return .Master.Write()
}

func ( *impl) () error {
	if  := .Master.Close();  != nil {
		return 
	}
	return .Slave.Close()
}

func ( *impl) ( int,  int) ( error) {
	,  := .Master.SyscallConn()
	if  != nil {
		return 
	}

	return .Control(func( uintptr) {
		 = termios.SetWinsize(int(), &unix.Winsize{
			Row: uint16(),
			Col: uint16(),
		})
	})
}

func ( *impl) ( *exec.Cmd) error {
	.Stdin, .Stdout, .Stderr = .Slave, .Slave, .Slave
	return .Start()
}

func newPty( Context,  string,  Window,  ssh.TerminalModes) ( impl,  error) {
	, ,  := pty.Open()
	if  != nil {
		return impl{}, 
	}

	,  := .SyscallConn()
	if  != nil {
		return impl{}, 
	}

	if  := .Control(func( uintptr) {
		 = applyTerminalModesToFd(, .Width, .Height, )
	});  != nil {
		return impl{}, 
	}

	return impl{Master: , Slave: }, 
}

func applyTerminalModesToFd( uintptr,  int,  int,  ssh.TerminalModes) error {
	var ,  uint32
	 := map[termios.CC]uint8{}
	 := map[termios.I]bool{}
	 := map[termios.O]bool{}
	 := map[termios.C]bool{}
	 := map[termios.L]bool{}

	for ,  := range  {
		switch  {
		case ssh.TTY_OP_ISPEED:
			 = 
		case ssh.TTY_OP_OSPEED:
			 = 
		default:
			,  := sshToCc[]
			if  {
				[] = uint8()
				continue
			}
			,  := sshToIflag[]
			if  {
				[] =  > 0
				continue
			}
			,  := sshToOflag[]
			if  {
				[] =  > 0
				continue
			}

			,  := sshToCflag[]
			if  {
				[] =  > 0
				continue
			}
			,  := sshToLflag[]
			if  {
				[] =  > 0
				continue
			}
		}
	}
	if  := termios.SetTermios(
		int(),
		,
		,
		,
		,
		,
		,
		,
	);  != nil {
		return 
	}
	return termios.SetWinsize(int(), &unix.Winsize{
		Row: uint16(),
		Col: uint16(),
	})
}

var sshToCc = map[uint8]termios.CC{
	ssh.VINTR:    termios.INTR,
	ssh.VQUIT:    termios.QUIT,
	ssh.VERASE:   termios.ERASE,
	ssh.VKILL:    termios.KILL,
	ssh.VEOF:     termios.EOF,
	ssh.VEOL:     termios.EOL,
	ssh.VEOL2:    termios.EOL2,
	ssh.VSTART:   termios.START,
	ssh.VSTOP:    termios.STOP,
	ssh.VSUSP:    termios.SUSP,
	ssh.VWERASE:  termios.WERASE,
	ssh.VREPRINT: termios.RPRNT,
	ssh.VLNEXT:   termios.LNEXT,
	ssh.VDISCARD: termios.DISCARD,
	ssh.VSTATUS:  termios.STATUS,
	ssh.VSWTCH:   termios.SWTCH,
	ssh.VFLUSH:   termios.FLUSH,
	ssh.VDSUSP:   termios.DSUSP,
}

var sshToIflag = map[uint8]termios.I{
	ssh.IGNPAR:  termios.IGNPAR,
	ssh.PARMRK:  termios.PARMRK,
	ssh.INPCK:   termios.INPCK,
	ssh.ISTRIP:  termios.ISTRIP,
	ssh.INLCR:   termios.INLCR,
	ssh.IGNCR:   termios.IGNCR,
	ssh.ICRNL:   termios.ICRNL,
	ssh.IUCLC:   termios.IUCLC,
	ssh.IXON:    termios.IXON,
	ssh.IXANY:   termios.IXANY,
	ssh.IXOFF:   termios.IXOFF,
	ssh.IMAXBEL: termios.IMAXBEL,
}

var sshToOflag = map[uint8]termios.O{
	ssh.OPOST:  termios.OPOST,
	ssh.OLCUC:  termios.OLCUC,
	ssh.ONLCR:  termios.ONLCR,
	ssh.OCRNL:  termios.OCRNL,
	ssh.ONOCR:  termios.ONOCR,
	ssh.ONLRET: termios.ONLRET,
}

var sshToCflag = map[uint8]termios.C{
	ssh.CS7:    termios.CS7,
	ssh.CS8:    termios.CS8,
	ssh.PARENB: termios.PARENB,
	ssh.PARODD: termios.PARODD,
}

var sshToLflag = map[uint8]termios.L{
	ssh.IUTF8:   termios.IUTF8,
	ssh.ISIG:    termios.ISIG,
	ssh.ICANON:  termios.ICANON,
	ssh.ECHO:    termios.ECHO,
	ssh.ECHOE:   termios.ECHOE,
	ssh.ECHOK:   termios.ECHOK,
	ssh.ECHONL:  termios.ECHONL,
	ssh.NOFLSH:  termios.NOFLSH,
	ssh.TOSTOP:  termios.TOSTOP,
	ssh.IEXTEN:  termios.IEXTEN,
	ssh.ECHOCTL: termios.ECHOCTL,
	ssh.ECHOKE:  termios.ECHOKE,
	ssh.PENDIN:  termios.PENDIN,
	ssh.XCASE:   termios.XCASE,
}