feat: implement semantically correct handling of shell/pty sessions across platforms #15
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR resolves 3 issues:
The issue was recognized when a friend reported
scp
andrsync
not working. I found the culprit to be not hooking up the session's/channel's I/O to spawned process, otherwise the new process assumed the null devices as its std{in,out,err}. In other words, the newly created process was not reading/writing to/from the client's shell, rather from, e.g., secondary tty device (pair of the pty device) 1. Thus the I/O was not channeled from the client to the process, rather to the PTY session. The PR hooks the client's I/O directly as the newly spawned process' std{in,out}. This means when issuing a command which expects to read bytes from stdin, the stdin of the remote process is fed from the local client, not the remote tty. Nowscp
et. al. can work.If you're on macOS, go look for your user in
/etc/passwd
. You will not find it. macOS uses Open Directory2 to manage the users, so the users' {meta,}data are stored in the DirectoryService(8) database. In Go, implementation of user lookup inos/user
pkg uses the native functiongetpwnam_r
with cgo; but only parses/etc/passwd
otherwise, except for lookups of current user which goes through syscall. Lookups return empty results for other users (see os/user: LookupUser() doesn't find users on macOS when compiled with CGO_ENABLED=0 golang/go#24383). To avoid cgo and still maintain robust and comprehensive offering, I had to shell out todscacheutil
on macOS to obtain full user details and parse /etc/passwd on other *nix platforms.Change the
Shell
field in theShell
struct toForceCommand
, and use the opportunity to line-up the semantics to match OpenSSH behavior. TheForceCommand
, if set, is executed using the user's shell, regardless of the command sent along the connection. The designated shell is always the user's default shell, which on *nix systems typically found in/etc/passwd
and$SHELL
.TODO:
Footnotes
https://dev.to/napicella/linux-terminals-tty-pty-and-shell-192e ↩
https://en.wikipedia.org/wiki/Apple_Open_Directory ↩