runWithPTY runs cmd attached to a pseudo-terminal.
(sess ssh.Session, cmd *exec.Cmd, ptyReq ssh.Pty, winCh <-chan ssh.Window)
| 108 | |
| 109 | // runWithPTY runs cmd attached to a pseudo-terminal. |
| 110 | func runWithPTY(sess ssh.Session, cmd *exec.Cmd, ptyReq ssh.Pty, winCh <-chan ssh.Window) { |
| 111 | ptmx, tty, err := pty.Open() |
| 112 | if err != nil { |
| 113 | fmt.Fprintf(sess.Stderr(), "pty open: %v\r\n", err) |
| 114 | sess.Exit(1) |
| 115 | return |
| 116 | } |
| 117 | defer ptmx.Close() |
| 118 | defer tty.Close() |
| 119 | |
| 120 | // Configure terminal modes from the SSH request. |
| 121 | if rc, err := tty.SyscallConn(); err == nil { |
| 122 | rc.Control(func(fd uintptr) { |
| 123 | tios, err := termios.GTTY(int(fd)) |
| 124 | if err != nil { |
| 125 | return |
| 126 | } |
| 127 | tios.Row = int(ptyReq.Window.Height) |
| 128 | tios.Col = int(ptyReq.Window.Width) |
| 129 | for c, v := range ptyReq.Modes { |
| 130 | if c == gossh.TTY_OP_ISPEED { |
| 131 | tios.Ispeed = int(v) |
| 132 | continue |
| 133 | } |
| 134 | if c == gossh.TTY_OP_OSPEED { |
| 135 | tios.Ospeed = int(v) |
| 136 | continue |
| 137 | } |
| 138 | k, ok := opcodeShortName[c] |
| 139 | if !ok { |
| 140 | continue |
| 141 | } |
| 142 | if _, ok := tios.CC[k]; ok { |
| 143 | tios.CC[k] = uint8(v) |
| 144 | continue |
| 145 | } |
| 146 | if _, ok := tios.Opts[k]; ok { |
| 147 | tios.Opts[k] = v > 0 |
| 148 | continue |
| 149 | } |
| 150 | } |
| 151 | tios.STTY(int(fd)) |
| 152 | }) |
| 153 | } |
| 154 | |
| 155 | if ptyReq.Term != "" { |
| 156 | cmd.Env = append(cmd.Env, "TERM="+ptyReq.Term) |
| 157 | } |
| 158 | |
| 159 | cmd.SysProcAttr = &syscall.SysProcAttr{ |
| 160 | Setctty: true, |
| 161 | Setsid: true, |
| 162 | } |
| 163 | cmd.Stdin = tty |
| 164 | cmd.Stdout = tty |
| 165 | cmd.Stderr = tty |
| 166 | |
| 167 | if err := cmd.Start(); err != nil { |
no test coverage detected