wip

Ayman Bagabas created

Change summary

go.mod             |  4 +-
go.sum             |  8 ++--
pkg/shell/shell.go | 10 ++----
pkg/ssh/shell.go   | 71 +++++++++++++++++++++++++----------------------
4 files changed, 48 insertions(+), 45 deletions(-)

Detailed changes

go.mod 🔗

@@ -20,14 +20,14 @@ require (
 require (
 	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
 	github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2
-	github.com/aymanbagabas/go-pty v0.2.0
+	github.com/aymanbagabas/go-pty v0.2.1
 	github.com/caarlos0/duration v0.0.0-20220103233809-8df7c22fe305
 	github.com/caarlos0/env/v10 v10.0.0
 	github.com/caarlos0/tablewriter v0.1.0
 	github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20231027181609-f7ff6baf2ed0
 	github.com/charmbracelet/keygen v0.5.0
 	github.com/charmbracelet/log v0.3.1
-	github.com/charmbracelet/ssh v0.0.0-20231129225614-669b249ca6ee
+	github.com/charmbracelet/ssh v0.0.0-20231203183338-c29875a2932c
 	github.com/go-jose/go-jose/v3 v3.0.1
 	github.com/gobwas/glob v0.2.3
 	github.com/golang-jwt/jwt/v5 v5.1.0

go.sum 🔗

@@ -16,8 +16,8 @@ github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2/go.mod h
 github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
-github.com/aymanbagabas/go-pty v0.2.0 h1:fC2ATGqFG+zH0Hr0Ks46h0lrRU2ExmQxR7iHUjBG1Do=
-github.com/aymanbagabas/go-pty v0.2.0/go.mod h1:Ul2Zd4Z3Cby9ByGdurtjlAafh6pjgrjiHNAsx4LC5yE=
+github.com/aymanbagabas/go-pty v0.2.1 h1:bqnC0bCkr4OAQ1fZdqqriRzGnZTHC71wogGNOPjSNHQ=
+github.com/aymanbagabas/go-pty v0.2.1/go.mod h1:1EXZe9k53iaw8QnevpvYenkDazponD+qtcp1s1E7CsQ=
 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
 github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
 github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
@@ -51,8 +51,8 @@ github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1
 github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
 github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
 github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
-github.com/charmbracelet/ssh v0.0.0-20231129225614-669b249ca6ee h1:r0yd6qZE8iLT2smnxiYre41b9/atj4kFxsfuIXW0Oqs=
-github.com/charmbracelet/ssh v0.0.0-20231129225614-669b249ca6ee/go.mod h1:Lq6b5f587hn2S27yNPgSB4Nei+iqOkghe9Ep7syGuQY=
+github.com/charmbracelet/ssh v0.0.0-20231203183338-c29875a2932c h1:ylmTNGYtwoe8Dfl5piAxQOrzBOnYtjnY4C+aAHXcoVU=
+github.com/charmbracelet/ssh v0.0.0-20231203183338-c29875a2932c/go.mod h1:PzGIpBYAWrMVea9T6tpJiIHm7Z/Hpnm7WTfOTkZ63xc=
 github.com/charmbracelet/wish v1.2.0 h1:h5Wj9pr97IQz/l4gM5Xep2lXcY/YM+6O2RC2o3x0JIQ=
 github.com/charmbracelet/wish v1.2.0/go.mod h1:JX3fC+178xadJYAhPu6qWtVDpJTwpnFvpdjz9RKJlUE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=

pkg/shell/shell.go 🔗

@@ -2,11 +2,8 @@ package shell
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"io"
-	"io/fs"
-	"os"
 	"os/exec"
 	"path/filepath"
 
@@ -141,9 +138,10 @@ func startCommand(co *cobra.Command, args []string) error {
 
 	cmdPath := filepath.Join(cmdsDir, args[0])
 
-	if stat, err := os.Stat(cmdPath); errors.Is(err, fs.ErrNotExist) || stat.Mode()&0111 == 0 {
-		return fmt.Errorf("command not found: %s", args[0])
-	}
+	// if stat, err := os.Stat(cmdPath); errors.Is(err, fs.ErrNotExist) || stat.Mode()&0111 == 0 {
+	// 	log.Printf("command mode %s", stat.Mode().String())
+	// 	return fmt.Errorf("command not found: %s", args[0])
+	// }
 
 	cmdPath, err := filepath.Abs(cmdPath)
 	if err != nil {

pkg/ssh/shell.go 🔗

@@ -2,55 +2,60 @@ package ssh
 
 import (
 	"fmt"
-	"io"
+	"os"
+	"os/exec"
+	"strings"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/pkg/shell"
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
 )
 
 // ShellMiddleware is a middleware for the SSH shell.
 func ShellMiddleware(sh ssh.Handler) ssh.Handler {
+	softBin, err := os.Executable()
+	if err != nil {
+		// TODO: handle this better
+		panic(err)
+	}
+
 	return func(s ssh.Session) {
 		ctx := s.Context()
 		logger := log.FromContext(ctx).WithPrefix("ssh")
-		envs := &sessionEnv{s}
-
-		ppty, _, isInteractive := s.Pty()
-
-		var (
-			in  io.Reader = s
-			out io.Writer = s
-			er  io.Writer = s.Stderr()
-			err error
-		)
-
-		if isInteractive {
-			in, out, er, err = ptyNew(ppty.Pty)
-			if err != nil {
-				logger.Errorf("could not create pty: %v", err)
-				// TODO: replace this err with a declared error
-				wish.Fatalln(s, fmt.Errorf("internal server error"))
-				return
-			}
-		}
 
 		args := s.Command()
-		if len(args) == 0 {
-			// XXX: args cannot be nil, otherwise cobra will use os.Args[1:]
-			args = []string{}
+		ppty, winch, isInteractive := s.Pty()
+
+		envs := s.Environ()
+		if len(args) > 0 {
+			envs = append(envs, "SSH_ORIGINAL_COMMAND="+strings.Join(args, " "))
 		}
 
-		cmd := shell.Command(ctx, envs, isInteractive)
-		cmd.SetArgs(args)
-		cmd.SetIn(in)
-		cmd.SetOut(out)
-		cmd.SetErr(er)
-		cmd.SetContext(ctx)
+		var cmd interface {
+			Run() error
+		}
+		cmdArgs := []string{"shell", "-c", fmt.Sprintf("'%s'", strings.Join(args, " "))}
+		if isInteractive && ppty.Pty != nil {
+			ppty.Pty.Resize(ppty.Window.Width, ppty.Window.Height)
+			go func() {
+				for win := range winch {
+					log.Printf("resizing to %d x %d", win.Width, win.Height)
+					ppty.Pty.Resize(win.Width, win.Height)
+				}
+			}()
+
+			c := ppty.Pty.CommandContext(ctx, softBin, cmdArgs...)
+			c.Env = append(envs, "PATH="+os.Getenv("PATH"))
+			cmd = c
+		} else {
+			c := exec.CommandContext(ctx, softBin, cmdArgs...)
+			c.Env = append(envs, "PATH="+os.Getenv("PATH"))
+			cmd = c
+		}
 
-		if err := cmd.ExecuteContext(ctx); err != nil {
-			wish.Fatalln(s, err)
+		if err := cmd.Run(); err != nil {
+			logger.Errorf("error running command: %s", err)
+			wish.Fatal(s, "internal server error")
 			return
 		}