title: Interactive secure shell in Golang not capturing all keyboard
body: <p>I am trying to start an interactive SSH session with a remote computer using Golang. I was able to get that without any problems, but the pseudo terminal doesn't seem to be capturing all of the keyboard i/o correctly.</p>
  
  <p>For example, if I run a regular SSH command like,</p>
  
  <pre><code>ssh -i ~/.ssh/some-key.pem username@1.1.1.1
  </code></pre>
  
  <p>I can exit with a simple <code>Ctrl+d</code>, but for some reason when I run the interactive shell started with Golang it's not working and only prints the actual key characters <code>^D</code>. Same goes for trying to use the arrow keys. If I run a <code>Ctrl+c</code> it exits the original Golang process and kills the interactive shell rather than executing on the remote machine.</p>
  
  <p>Below is my code for setting up the shell,</p>
  
  <pre><code>func StartInteractiveShell(sshConfig *ssh.ClientConfig, network string, host string, port string) error {
      var (
          session *ssh.Session
          conn    *ssh.Client
          err     error
      )    
      if conn, err = getSshConnection(sshConfig, network, host, port); err != nil {
          fmt.Printf("Failed to dial: %s", err)
          return err   
      }
  
      if session, err = getSshSession(conn); err != nil {
          fmt.Printf("Failed to create session: %s", err)
          return err
      }
      defer session.Close()
  
      if err = setupPty(session); err != nil {
          fmt.Printf("Failed to set up pseudo terminal: %s", err)
          return err
      }
  
      session.Stdout = os.Stdout
      session.Stdin  = os.Stdin
      session.Stderr = os.Stderr
  
      if err = session.Shell(); err != nil {
          fmt.Printf("Failed to start interactive shell: %s", err)
          return err
      }
      return session.Wait()
  }
  
  func getSshConnection(config *ssh.ClientConfig, network string, host string, port string) (*ssh.Client, error) {
      addr := host + ":" + port
      return ssh.Dial(network, addr, config)
  }
  
  func getSshSession(clientConnection *ssh.Client) (*ssh.Session, error) {
      return clientConnection.NewSession()
  }
  
  // pty = pseudo terminal
  func setupPty(session *ssh.Session) error {
      modes := ssh.TerminalModes{
          ssh.ECHO:          0,     // disable echoing
          ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
          ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
      }
  
      if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
          session.Close()
          fmt.Printf("request for pseudo terminal failed: %s", err)
          return err
      }
      return nil
  }
  </code></pre>
  
  <p>Am I missing something there?</p>