@@ -698,63 +698,24 @@ func (s *Server) sftpHandler(logger slog.Logger, session ssh.Session) {
698698 _ = session .Exit (1 )
699699}
700700
701- // EnvInfoer encapsulates external information required by CreateCommand.
702- type EnvInfoer interface {
703- // CurrentUser returns the current user.
704- CurrentUser () (* user.User , error )
705- // Environ returns the environment variables of the current process.
706- Environ () []string
707- // UserHomeDir returns the home directory of the current user.
708- UserHomeDir () (string , error )
709- // UserShell returns the shell of the given user.
710- UserShell (username string ) (string , error )
711- }
712-
713- type systemEnvInfoer struct {}
714-
715- var defaultEnvInfoer EnvInfoer = & systemEnvInfoer {}
716-
717- // DefaultEnvInfoer returns a default implementation of
718- // EnvInfoer. This reads information using the default Go
719- // implementations.
720- func DefaultEnvInfoer () EnvInfoer {
721- return defaultEnvInfoer
722- }
723-
724- func (systemEnvInfoer ) CurrentUser () (* user.User , error ) {
725- return user .Current ()
726- }
727-
728- func (systemEnvInfoer ) Environ () []string {
729- return os .Environ ()
730- }
731-
732- func (systemEnvInfoer ) UserHomeDir () (string , error ) {
733- return userHomeDir ()
734- }
735-
736- func (systemEnvInfoer ) UserShell (username string ) (string , error ) {
737- return usershell .Get (username )
738- }
739-
740701// CreateCommand processes raw command input with OpenSSH-like behavior.
741702// If the script provided is empty, it will default to the users shell.
742703// This injects environment variables specified by the user at launch too.
743704// The final argument is an interface that allows the caller to provide
744705// alternative implementations for the dependencies of CreateCommand.
745706// This is useful when creating a command to be run in a separate environment
746707// (for example, a Docker container). Pass in nil to use the default.
747- func (s * Server ) CreateCommand (ctx context.Context , script string , env []string , deps EnvInfoer ) (* pty.Cmd , error ) {
748- if deps == nil {
749- deps = DefaultEnvInfoer ()
708+ func (s * Server ) CreateCommand (ctx context.Context , script string , env []string , ei usershell. EnvInfoer ) (* pty.Cmd , error ) {
709+ if ei == nil {
710+ ei = & usershell. SystemEnvInfo {}
750711 }
751- currentUser , err := deps . CurrentUser ()
712+ currentUser , err := ei . User ()
752713 if err != nil {
753714 return nil , xerrors .Errorf ("get current user: %w" , err )
754715 }
755716 username := currentUser .Username
756717
757- shell , err := deps . UserShell (username )
718+ shell , err := ei . Shell (username )
758719 if err != nil {
759720 return nil , xerrors .Errorf ("get user shell: %w" , err )
760721 }
@@ -802,21 +763,32 @@ func (s *Server) CreateCommand(ctx context.Context, script string, env []string,
802763 }
803764 }
804765
805- cmd := s .Execer .PTYCommandContext (ctx , name , args ... )
766+ // Modify command prior to execution. This will usually be a no-op, but not
767+ // always. For example, to run a command in a Docker container, we need to
768+ // modify the command to be `docker exec -it <container> <command>`.
769+ modifiedName , modifiedArgs := ei .ModifyCommand (name , args ... )
770+ // Log if the command was modified.
771+ if modifiedName != name && slices .Compare (modifiedArgs , args ) != 0 {
772+ s .logger .Debug (ctx , "modified command" ,
773+ slog .F ("before" , append ([]string {name }, args ... )),
774+ slog .F ("after" , append ([]string {modifiedName }, modifiedArgs ... )),
775+ )
776+ }
777+ cmd := s .Execer .PTYCommandContext (ctx , modifiedName , modifiedArgs ... )
806778 cmd .Dir = s .config .WorkingDirectory ()
807779
808780 // If the metadata directory doesn't exist, we run the command
809781 // in the users home directory.
810782 _ , err = os .Stat (cmd .Dir )
811783 if cmd .Dir == "" || err != nil {
812784 // Default to user home if a directory is not set.
813- homedir , err := deps . UserHomeDir ()
785+ homedir , err := ei . HomeDir ()
814786 if err != nil {
815787 return nil , xerrors .Errorf ("get home dir: %w" , err )
816788 }
817789 cmd .Dir = homedir
818790 }
819- cmd .Env = append (deps .Environ (), env ... )
791+ cmd .Env = append (ei .Environ (), env ... )
820792 cmd .Env = append (cmd .Env , fmt .Sprintf ("USER=%s" , username ))
821793
822794 // Set SSH connection environment variables (these are also set by OpenSSH
0 commit comments