Skip to content

Commit

Permalink
document behavior of NL to CRNL translation in Write and add a way to…
Browse files Browse the repository at this point in the history
… disable it.

Updates tailscale/tailscale#4146

Signed-off-by: Maisem Ali <maisem@tailscale.com>
  • Loading branch information
maisem committed Mar 13, 2022
1 parent c9fc441 commit 8209995
Showing 1 changed file with 41 additions and 17 deletions.
58 changes: 41 additions & 17 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ type Session interface {
// the request handling loop. Registering nil will unregister the channel.
// During the time that no channel is registered, breaks are ignored.
Break(c chan<- bool)

// DisablePTYEmulation disables the session's default minimal PTY emulation.
// If you're setting the pty's termios settings from the Pty request, use
// this method to avoid corruption.
// Currently (2022-03-12) the only emulation implemented is NL-to-CRNL translation (`\n`=>`\r\n`).
// A call of DisablePTYEmulation must precede any call to Write.
DisablePTYEmulation() error
}

// maxSigBufSize is how many signals will be buffered
Expand All @@ -103,33 +110,50 @@ func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.Ne
sessReqCb: srv.SessionRequestCallback,
subsystemHandlers: srv.SubsystemHandlers,
ctx: ctx,
wroteCh: make(chan interface{}),
}
sess.handleRequests(reqs)
}

type session struct {
sync.Mutex
gossh.Channel
conn *gossh.ServerConn
handler Handler
subsystemHandlers map[string]SubsystemHandler
handled bool
exited bool
pty *Pty
winch chan Window
env []string
ptyCb PtyCallback
sessReqCb SessionRequestCallback
rawCmd string
subsystem string
ctx Context
sigCh chan<- Signal
sigBuf []Signal
breakCh chan<- bool
conn *gossh.ServerConn
handler Handler
subsystemHandlers map[string]SubsystemHandler
handled bool
exited bool
pty *Pty
winch chan Window
env []string
ptyCb PtyCallback
sessReqCb SessionRequestCallback
rawCmd string
subsystem string
ctx Context
sigCh chan<- Signal
sigBuf []Signal
breakCh chan<- bool
disablePtyEmulation bool

// wroteCh is closed after the first call to Write.
wroteCh chan interface{}
wroteChCloseOnce sync.Once
}

func (sess *session) DisablePTYEmulation() error {
select {
case <-sess.wroteCh:
return errors.New("DisablePTYEmulation must be called before calls to Write")
default:
}
sess.disablePtyEmulation = true
return nil
}

func (sess *session) Write(p []byte) (n int, err error) {
if sess.pty != nil {
sess.wroteChCloseOnce.Do(func() { close(sess.wroteCh) })
if sess.pty != nil && !sess.disablePtyEmulation {
m := len(p)
// normalize \n to \r\n when pty is accepted.
// this is a hardcoded shortcut since we don't support terminal modes.
Expand Down

0 comments on commit 8209995

Please sign in to comment.