66
func opensshOptions(options *Options, commandKind opensshCommandKind) []string {
67
args := append([]string{}, opensshCommonOptions...)
66
func opensshOptions(options *Options, commandKind opensshCommandKind) map[string][]string {
67
args := make(map[string][]string)
68
for k, v := range opensshCommonOptions {
68
71
if options == nil {
69
72
options = &Options{}
71
74
if !options.passwordAuthAllowed {
72
args = append(args, "-o", "PasswordAuthentication no")
75
args["-o"] = append(args["-o"], "PasswordAuthentication no")
74
77
if options.allocatePTY {
75
args = append(args, "-t")
78
args["-t"] = []string{}
77
80
identities := append([]string{}, options.identities...)
78
81
if pk := PrivateKeyFiles(); len(pk) > 0 {
96
99
for _, identity := range identities {
97
args = append(args, "-i", identity)
100
args["-i"] = append(args["-i"], identity)
99
102
if options.port != 0 {
103
port := fmt.Sprint(options.port)
100
104
if commandKind == scpKind {
101
105
// scp uses -P instead of -p (-p means preserve).
102
args = append(args, "-P")
106
args["-P"] = []string{port}
104
args = append(args, "-p")
108
args["-p"] = []string{port}
106
args = append(args, fmt.Sprint(options.port))
114
func expandArgs(args map[string][]string, quote bool) []string {
116
for opt, vals := range args {
118
list = append(list, opt)
120
// In order to force a PTY to be allocated, we need to
122
list = append(list, opt)
125
for _, val := range vals {
126
list = append(list, opt)
128
val = fmt.Sprintf("%q", val)
130
list = append(list, val)
111
136
// Command implements Client.Command.
112
137
func (c *OpenSSHClient) Command(host string, command []string, options *Options) *Cmd {
113
args := opensshOptions(options, sshKind)
138
opts := opensshOptions(options, sshKind)
139
args := expandArgs(opts, false)
114
140
args = append(args, host)
115
141
if len(command) > 0 {
116
args = append(args, "--")
117
142
args = append(args, command...)
119
144
bin, args := sshpassWrap("ssh", args)
145
optsList := strings.Join(expandArgs(opts, true), " ")
146
fullCommand := strings.Join(command, " ")
147
logger.Debugf("running: %s %s %q '%s'", bin, optsList, host, fullCommand)
120
148
return &Cmd{impl: &opensshCmd{exec.Command(bin, args...)}}
123
151
// Copy implements Client.Copy.
124
func (c *OpenSSHClient) Copy(source, dest string, userOptions *Options) error {
152
func (c *OpenSSHClient) Copy(targets, extraArgs []string, userOptions *Options) error {
125
153
var options Options
126
154
if userOptions != nil {
127
155
options = *userOptions
128
156
options.allocatePTY = false // doesn't make sense for scp
130
args := opensshOptions(&options, scpKind)
131
args = append(args, source, dest)
158
opts := opensshOptions(&options, scpKind)
159
args := expandArgs(opts, false)
160
args = append(args, extraArgs...)
161
args = append(args, targets...)
132
162
bin, args := sshpassWrap("scp", args)
133
163
cmd := exec.Command(bin, args...)
134
164
var stderr bytes.Buffer
135
165
cmd.Stderr = &stderr
166
allOpts := append(expandArgs(opts, true), extraArgs...)
167
optsList := strings.Join(allOpts, " ")
168
targetList := `"` + strings.Join(targets, `" "`) + `"`
169
logger.Debugf("running: %s %s %s", bin, optsList, targetList)
136
170
if err := cmd.Run(); err != nil {
137
171
stderr := strings.TrimSpace(stderr.String())
138
172
if len(stderr) > 0 {