func GetPort(host, port string) (uint16, error) {
	p := port
	V("getPort(%q, %q)", host, port)
	if len(port) == 0 {
		if cp := config.Get(host, "Port"); len(cp) != 0 {
			V("config.Get(%q,%q): %q", host, port, cp)
			p = cp
		}
	}
	if len(p) == 0 || p == "22" {
		p = DefaultPort
		V("getPort: return default %q", p)
	}
	V("returns %q", p)
	pn, err := strconv.ParseUint(p, 0, 16)
	return uint16(pn), err
}
GetPort gets a port. It verifies that the port fits in 16-bit space.
The rules here are messy, since config.Get will return "22" if
there is no entry in .ssh/config. 22 is not allowed. So in the case
of "22", convert to defaultPort.
package cpu
import (
	"bytes"
	"crypto/rand"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	config "github.com/kevinburke/ssh_config"
	ssh "golang.org/x/crypto/ssh"
)
const (
	DefaultPort = "23"
)
var (
	DefaultKeyFile = filepath.Join(os.Getenv("HOME"), ".ssh/cpu_rsa")
	Debug9p bool
	Dump9p bool
	DumpWriter io.Writer = os.Stderr
)
type nonce [32]byte
func verbose(f string, a ...interface{}) {
	V("\r\n"+f+"\r\n", a...)
}
func generateNonce() (nonce, error) {
	var b [len(nonce{}) / 2]byte
	if _, err := rand.Read(b[:]); err != nil {
		return nonce{}, err
	}
	var n nonce
	copy(n[:], fmt.Sprintf("%02x", b))
	return n, nil
}
func (n nonce) String() string {
	return string(n[:])
}
func (c *Cmd) UserKeyConfig() error {
	keyFile := c.PrivateKeyFile
	key, err := ioutil.ReadFile(keyFile)
	if err != nil {
		return fmt.Errorf("unable to read private key %v: %v", keyFile, err)
	}
	signer, err := ssh.ParsePrivateKey(key)
	if err != nil {
		return fmt.Errorf("ParsePrivateKey %v: %v", keyFile, err)
	}
	c.config.Auth = append(c.config.Auth, ssh.PublicKeys(signer))
	return nil
}
func (c *Cmd) HostKeyConfig(hostKeyFile string) error {
	hk, err := ioutil.ReadFile(hostKeyFile)
	if err != nil {
		return fmt.Errorf("unable to read host key %v: %v", hostKeyFile, err)
	}
	pk, err := ssh.ParsePublicKey(hk)
	if err != nil {
		return fmt.Errorf("host key %v: %v", string(hk), err)
	}
	c.config.HostKeyCallback = ssh.FixedHostKey(pk)
	return nil
}
func (c *Cmd) SetEnv(envs ...string) error {
	for _, v := range append(os.Environ(), envs...) {
		env := strings.SplitN(v, "=", 2)
		if len(env) == 1 {
			env = append(env, "")
		}
		if err := c.session.Setenv(env[0], env[1]); err != nil {
			return fmt.Errorf("Warning: c.session.Setenv(%q, %q): %v", v, os.Getenv(v), err)
		}
	}
	return nil
}
func (c *Cmd) SSHStdin(w io.WriteCloser, r io.Reader) {
	var newLine, tilde bool
	var t = []byte{'~'}
	var b [1]byte
	for {
		if _, err := r.Read(b[:]); err != nil {
			break
		}
		switch b[0] {
		default:
			newLine = false
			if tilde {
				if _, err := w.Write(t[:]); err != nil {
					return
				}
				tilde = false
			}
			if _, err := w.Write(b[:]); err != nil {
				return
			}
		case '\n', '\r':
			newLine = true
			if _, err := w.Write(b[:]); err != nil {
				return
			}
		case '~':
			if newLine {
				newLine = false
				tilde = true
				break
			}
			if _, err := w.Write(t[:]); err != nil {
				return
			}
		case '.':
			if tilde {
				c.session.Close()
				return
			}
			if _, err := w.Write(b[:]); err != nil {
				return
			}
		}
	}
}
func GetKeyFile(host, kf string) string {
	V("getKeyFile for %q", kf)
	if len(kf) == 0 {
		kf = config.Get(host, "IdentityFile")
		V("key file from config is %q", kf)
		if len(kf) == 0 {
			kf = DefaultKeyFile
		}
	}
	if strings.HasPrefix(kf, "~") {
		kf = filepath.Join(os.Getenv("HOME"), kf[1:])
	}
	V("getKeyFile returns %q", kf)
	return kf
}
func GetHostName(host string) string {
	h := config.Get(host, "HostName")
	if len(h) != 0 {
		host = h
	}
	return host
}