Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lua/sshfs/lib/ssh.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ local function get_ssh_options(auth_type)

-- A config RemoteCommand cannot coexist with the command these paths append,
-- and sftp needs a plain session, so it is cleared for everything but a shell.
if auth_type == "batch" or auth_type == "socket" then table.insert(options, "RemoteCommand=none") end
if auth_type == "batch" or auth_type == "socket" then
table.insert(options, "RemoteCommand=none")
-- A forced tty closes the sftp channel and puts carriage returns in captured output.
table.insert(options, "RequestTTY=no")
end

-- Add ControlMaster options
local control_opts = Config.get_control_master_options()
Expand Down
20 changes: 20 additions & 0 deletions tests/remote_command_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ local function clears_remote_command(cmd)
return option_index(cmd, "RemoteCommand=none") ~= nil
end

describe("RequestTTY handling", function()
it("refuses a forced tty on the paths that carry sftp or captured output", function()
local Ssh = load_ssh()

expect.truthy(option_index(Ssh.build_batch_command("example.com"), "RequestTTY=no"))
expect.truthy(option_index(Ssh.build_home_command("example.com"), "RequestTTY=no"), "readlink output must be clean")
expect.contains(Ssh.build_command_string("socket"), "-o RequestTTY=no")
end)

it("leaves the interactive authentication terminal a tty", function()
local Ssh = load_ssh()
expect.is_nil(option_index(Ssh.build_auth_command("example.com"), "RequestTTY=no"), "a password prompt needs one")
end)

it("leaves a terminal session a tty", function()
local Ssh = load_ssh()
expect.is_nil(option_index(Ssh.build_command("example.com", "/srv/app"), "RequestTTY=no"))
end)
end)

describe("RemoteCommand handling", function()
it("clears it on every command that appends a remote command", function()
local Ssh = load_ssh()
Expand Down
2 changes: 1 addition & 1 deletion tests/ssh_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ end
describe("Ssh.build_command_string", function()
it("passes the control path and clears any RemoteCommand when reusing a socket", function()
local Ssh = load_ssh()
expect.eq(Ssh.build_command_string("socket"), "ssh -o RemoteCommand=none -o " .. CONTROL_PATH)
expect.eq(Ssh.build_command_string("socket"), "ssh -o RemoteCommand=none -o RequestTTY=no -o " .. CONTROL_PATH)
end)

it("forces a master and disables prompts for batch connections", function()
Expand Down
Loading