description and source-codessh-exec = function (cmd, opts, cb) {
opts = parse(opts)
var stream = duplexify()
var client = new ssh2.Client()
var key = opts.key === false ? undefined : opts.key || path.join(HOME, '.ssh', 'id_rsa')
var fingerprint
client.on('error', function (err) {
stream.destroy(err)
})
var connect = function () {
if (key && key.toString().toLowerCase().indexOf('encrypted') > -1) key = null
var verifier = function (hash) {
fingerprint = hash
if (!opts.fingerprint) return true
if (fingerprint === opts.fingerprint) return true
client.destroy(new Error('Host could not be verified'))
return false
}
if (opts.password) {
client.on('keyboard-interactive', function (a, b, c, prompt, cb) {
cb([opts.password])
})
}
client.connect({
host: opts.host,
username: opts.user,
password: opts.password,
port: opts.port || 22,
tryKeyboard: !!opts.password,
privateKey: key,
agent: process.env.SSH_AUTH_SOCK,
hostHash: 'md5',
hostVerifier: verifier
})
}
var run = function () {
client.exec(cmd, function (err, stdio) {
if (err) return stream.destroy(err)
stream.setWritable(stdio)
stream.setReadable(stdio)
stream.emit('ready')
stdio.stderr.setEncoding('utf-8')
stdio.stderr.on('data', function (data) {
stream.emit('warn', data)
})
stdio.on('exit', function (code) {
if (code !== 0) {
var err = new Error('Non-zero exit code: ' + code)
err.code = code
stream.emit('error', err)
}
stream.emit('exit', code)
client.end()
})
})
}
var onverify = function (err) {
if (err) return stream.destroy(err)
run()
}
client.once('ready', function () {
if (fingerprint === opts.fingerprint) return run()
if (!stream.emit('verify', fingerprint, onverify)) return run()
})
stream.on('close', function () {
client.end()
})
if (!key || Buffer.isBuffer(key) || key.toString().indexOf('\n') > -1) {
connect()
} else {
fs.readFile(key, function (_, buffer) {
key = buffer
connect()
})
}
if (cb) oncallback(stream, cb)
return stream
}