| 193 | } |
| 194 | |
| 195 | func HandlePTY(sess ssh.Session, ptyReq ssh.Pty, winCh <-chan ssh.Window, cmd *exec.Cmd, decorateReader func(reader io.Reader) io.Reader) (err error) { |
| 196 | cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term)) |
| 197 | f, err := startPTY(cmd) |
| 198 | if err != nil { |
| 199 | return errors.Wrap(err, "start pty") |
| 200 | } |
| 201 | defer f.Close() |
| 202 | |
| 203 | go func() { |
| 204 | for win := range winCh { |
| 205 | setWinSize(f, win.Width, win.Height) |
| 206 | } |
| 207 | }() |
| 208 | |
| 209 | go func() { |
| 210 | defer f.Close() |
| 211 | |
| 212 | // copy stdin |
| 213 | _, _ = io.Copy(f, sess) |
| 214 | }() |
| 215 | |
| 216 | stdoutDoneChan := make(chan struct{}) |
| 217 | go func() { |
| 218 | defer f.Close() |
| 219 | defer close(stdoutDoneChan) |
| 220 | |
| 221 | var reader io.Reader = f |
| 222 | if decorateReader != nil { |
| 223 | reader = decorateReader(f) |
| 224 | } |
| 225 | |
| 226 | // copy stdout |
| 227 | _, _ = io.Copy(sess, reader) |
| 228 | }() |
| 229 | |
| 230 | err = cmd.Wait() |
| 231 | if err != nil { |
| 232 | return err |
| 233 | } |
| 234 | |
| 235 | select { |
| 236 | case <-stdoutDoneChan: |
| 237 | case <-time.After(time.Second): |
| 238 | } |
| 239 | return nil |
| 240 | } |
| 241 | |
| 242 | func (s *Server) getCommand(sess ssh.Session) *exec.Cmd { |
| 243 | var cmd *exec.Cmd |