Fix tailssh pixels

This commit is contained in:
世界
2026-08-30 17:41:46 +08:00
parent 0a5078a848
commit ec497c7dda
8 changed files with 61 additions and 32 deletions
+2 -2
View File
@@ -25,7 +25,7 @@ func OpenNativeShellSession(
cwd,
int(uid), int(gid),
common.Map(iteratorToArray[int32](groups), func(g int32) int { return int(g) }),
uint16(rows), uint16(cols),
uint16(rows), uint16(cols), 0, 0,
)
if err != nil {
return nil, err
@@ -58,7 +58,7 @@ func (s *nativeShellSession) MasterFD() int32 {
}
func (s *nativeShellSession) Resize(rows, cols int32) error {
return s.shell.Resize(uint16(rows), uint16(cols))
return s.shell.Resize(uint16(rows), uint16(cols), 0, 0)
}
func (s *nativeShellSession) Signal(sig int32) error {
+17 -8
View File
@@ -582,11 +582,13 @@ func (s *Server) handleSession(session gliderssh.Session) {
session.DisablePTYEmulation()
command := session.RawCommand()
var term string
var rows, cols uint16
var rows, cols, widthPixels, heightPixels uint16
if isPty {
term = ptyReq.Term
rows = clampWindowDimension(ptyReq.Window.Height)
cols = clampWindowDimension(ptyReq.Window.Width)
widthPixels = clampWindowDimension(ptyReq.Window.WidthPixels)
heightPixels = clampWindowDimension(ptyReq.Window.HeightPixels)
}
var rec *recording
recorderList, onFailure := recorders(connInfo)
@@ -611,12 +613,14 @@ func (s *Server) handleSession(session gliderssh.Session) {
}
}
shellSession, err := s.backend.OpenSession(shellRequest{
User: localUser,
Command: command,
Env: env,
Term: term,
Rows: rows,
Cols: cols,
User: localUser,
Command: command,
Env: env,
Term: term,
Rows: rows,
Cols: cols,
WidthPixels: widthPixels,
HeightPixels: heightPixels,
})
if err != nil {
s.logger.Error("failed to open shell session: ", err)
@@ -661,7 +665,12 @@ func (s *Server) handleSession(session gliderssh.Session) {
for win := range winCh {
shellAccess.Lock()
if shellAlive {
shellSession.Resize(clampWindowDimension(win.Height), clampWindowDimension(win.Width))
shellSession.Resize(
clampWindowDimension(win.Height),
clampWindowDimension(win.Width),
clampWindowDimension(win.WidthPixels),
clampWindowDimension(win.HeightPixels),
)
}
shellAccess.Unlock()
}
+9 -7
View File
@@ -14,12 +14,14 @@ type shellBackend interface {
}
type shellRequest struct {
User *adapter.PlatformUser
Command string
Env []string
Term string
Rows uint16
Cols uint16
User *adapter.PlatformUser
Command string
Env []string
Term string
Rows uint16
Cols uint16
WidthPixels uint16
HeightPixels uint16
}
type shellSession interface {
@@ -27,7 +29,7 @@ type shellSession interface {
// CloseWrite signals EOF on the child's stdin without tearing down the
// session, so programs that read stdin to EOF can finish normally.
CloseWrite() error
Resize(rows, cols uint16) error
Resize(rows, cols, widthPixels, heightPixels uint16) error
Signal(sig int) error
Wait() (exitStatus uint32, err error)
}
+17 -4
View File
@@ -25,11 +25,15 @@ func (b *platformShellBackend) OpenSession(request shellRequest) (shellSession,
return nil, err
}
master := os.NewFile(uintptr(dupFd), "pty-master")
return &platformShellSession{
shellSession := &platformShellSession{
session: session,
master: master,
isPty: request.Term != "",
}, nil
}
if shellSession.isPty && (request.WidthPixels > 0 || request.HeightPixels > 0) {
_ = SetWinsize(int(master.Fd()), request.Rows, request.Cols, request.WidthPixels, request.HeightPixels)
}
return shellSession, nil
}
func (b *platformShellBackend) Close() error {
@@ -61,8 +65,17 @@ func (s *platformShellSession) CloseWrite() error {
return syscall.Shutdown(int(s.master.Fd()), syscall.SHUT_WR)
}
func (s *platformShellSession) Resize(rows, cols uint16) error {
return s.session.Resize(int32(rows), int32(cols))
func (s *platformShellSession) Resize(rows, cols, widthPixels, heightPixels uint16) error {
err := s.session.Resize(int32(rows), int32(cols))
if err != nil {
return err
}
// The platform interface carries no pixel dimensions; set them directly
// on the duplicated pty master.
if s.isPty && (widthPixels > 0 || heightPixels > 0) {
return SetWinsize(int(s.master.Fd()), rows, cols, widthPixels, heightPixels)
}
return nil
}
func (s *platformShellSession) Signal(sig int) error {
+1 -1
View File
@@ -45,7 +45,7 @@ func (b *directShellBackend) OpenSession(request shellRequest) (shellSession, er
args = []string{"-" + filepath.Base(shell)}
}
if request.Term != "" {
return OpenPtyShell(shell, args, request.Env, request.User.HomeDir, request.User.Uid, request.User.Gid, request.User.Groups, request.Rows, request.Cols)
return OpenPtyShell(shell, args, request.Env, request.User.HomeDir, request.User.Uid, request.User.Gid, request.User.Groups, request.Rows, request.Cols, request.WidthPixels, request.HeightPixels)
}
return OpenSocketpairShell(shell, args, request.Env, request.User.HomeDir, request.User.Uid, request.User.Gid, request.User.Groups)
}
@@ -325,7 +325,7 @@ func (s *conptyShellSession) Write(p []byte) (int, error) {
return s.input.Write(p)
}
func (s *conptyShellSession) Resize(rows, cols uint16) error {
func (s *conptyShellSession) Resize(rows, cols, _, _ uint16) error {
return s.console.Resize(windows.Coord{X: clampConsoleDimension(cols), Y: clampConsoleDimension(rows)})
}
@@ -451,7 +451,7 @@ func (s *pipeShellSession) Write(p []byte) (int, error) {
return s.stdin.Write(p)
}
func (s *pipeShellSession) Resize(_, _ uint16) error {
func (s *pipeShellSession) Resize(_, _, _, _ uint16) error {
return nil
}
+4 -4
View File
@@ -13,8 +13,8 @@ type Shell struct {
isPty bool
}
func OpenPtyShell(shell string, args, env []string, dir string, uid, gid int, groups []int, rows, cols uint16) (*Shell, error) {
master, process, err := StartPtyProcess(shell, args, env, dir, uid, gid, groups, rows, cols)
func OpenPtyShell(shell string, args, env []string, dir string, uid, gid int, groups []int, rows, cols, widthPixels, heightPixels uint16) (*Shell, error) {
master, process, err := StartPtyProcess(shell, args, env, dir, uid, gid, groups, rows, cols, widthPixels, heightPixels)
if err != nil {
return nil, err
}
@@ -52,11 +52,11 @@ func (s *Shell) Write(p []byte) (int, error) {
return s.master.Write(p)
}
func (s *Shell) Resize(rows, cols uint16) error {
func (s *Shell) Resize(rows, cols, widthPixels, heightPixels uint16) error {
if !s.isPty {
return nil
}
return SetWinsize(int(s.master.Fd()), rows, cols)
return SetWinsize(int(s.master.Fd()), rows, cols, widthPixels, heightPixels)
}
func (s *Shell) Signal(sig int) error {
@@ -14,7 +14,7 @@ import (
"golang.org/x/sys/unix"
)
func StartPtyProcess(shell string, args, env []string, dir string, uid, gid int, groups []int, rows, cols uint16) (*os.File, *os.Process, error) {
func StartPtyProcess(shell string, args, env []string, dir string, uid, gid int, groups []int, rows, cols, widthPixels, heightPixels uint16) (*os.File, *os.Process, error) {
cmd := exec.Command(shell)
cmd.Args = args
cmd.Dir = dir
@@ -27,7 +27,7 @@ func StartPtyProcess(shell string, args, env []string, dir string, uid, gid int,
setCredential(attrs, uid, gid, groups)
var size *pty.Winsize
if rows > 0 && cols > 0 {
size = &pty.Winsize{Rows: rows, Cols: cols}
size = &pty.Winsize{Rows: rows, Cols: cols, X: widthPixels, Y: heightPixels}
}
master, err := pty.StartWithAttrs(cmd, size, attrs)
if err != nil {
@@ -94,6 +94,11 @@ func setCredential(attr *syscall.SysProcAttr, uid, gid int, groups []int) {
attr.Credential = cred
}
func SetWinsize(fd int, rows, cols uint16) error {
return unix.IoctlSetWinsize(fd, unix.TIOCSWINSZ, &unix.Winsize{Row: rows, Col: cols})
func SetWinsize(fd int, rows, cols, widthPixels, heightPixels uint16) error {
return unix.IoctlSetWinsize(fd, unix.TIOCSWINSZ, &unix.Winsize{
Row: rows,
Col: cols,
Xpixel: widthPixels,
Ypixel: heightPixels,
})
}