Support PORTAGE_SSH_OPTS, bug #470002.

Additional ssh options to be used when portage executes ssh or sftp.
This variable supports use of embedded quote characters to quote
whitespace or special shell characters within arguments (embedded
quotes must be escaped in make.conf settings).
diff --git a/cnf/make.globals b/cnf/make.globals
index 5f5098b..1f07df3 100644
--- a/cnf/make.globals
+++ b/cnf/make.globals
@@ -46,10 +46,12 @@
 FETCHCOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\""
 RESUMECOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\""
 
-FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec rsync --rsh=\\\"ssh -p\\\${port}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
+# NOTE: rsync will evaluate quotes embedded inside PORTAGE_SSH_OPTS
+FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec rsync --rsh=\\\"ssh -p\\\${port} \\\${3}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\""
 RESUMECOMMAND_SSH=${FETCHCOMMAND_SSH}
 
-FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec sftp -P \\\${port} \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
+# NOTE: bash eval is used to evaluate quotes embedded inside PORTAGE_SSH_OPTS
+FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; eval \\\"declare -a ssh_opts=(\\\${3})\\\" ; exec sftp -P \\\${port} \\\"\\\${ssh_opts[@]}\\\" \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\""
 
 # Default user options
 FEATURES="assume-digests binpkg-logs
diff --git a/man/make.conf.5 b/man/make.conf.5
index 9b4121c..fed71f5 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -854,6 +854,14 @@
 .br
 Defaults to -1.
 .TP
+\fBPORTAGE_SSH_OPTS\fR = \fI[list of ssh options]\fR
+Additional ssh options to be used when portage executes ssh or sftp.
+This variable supports use of embedded quote characters to quote
+whitespace or special shell characters within arguments (embedded
+quotes must be escaped in make.conf settings).
+.br
+Defaults to no value.
+.TP
 \fBPORTAGE_SYNC_STALE\fR = \fI[NUMBER]\fR
 Defines the number of days after the last `emerge \-\-sync` that a warning
 message should be produced. A value of 0 will disable warnings.
diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py
index 099d3c4..543881e 100644
--- a/pym/_emerge/BinpkgFetcher.py
+++ b/pym/_emerge/BinpkgFetcher.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2012 Gentoo Foundation
+# Copyright 1999-2013 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.AsynchronousLock import AsynchronousLock
@@ -80,6 +80,12 @@
 			"FILE"    : os.path.basename(pkg_path)
 		}
 
+		for k in ("PORTAGE_SSH_OPTS",):
+			try:
+				fcmd_vars[k] = settings[k]
+			except KeyError:
+				pass
+
 		fetch_env = dict(settings.items())
 		fetch_args = [portage.util.varexpand(x, mydict=fcmd_vars) \
 			for x in portage.util.shlex_split(fcmd)]
diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
index 3982eb3..a46f565 100644
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@ -2253,6 +2253,9 @@
 			writemsg_level("!!! SYNC is invalid: %s\n" % syncuri,
 				noiselevel=-1, level=logging.ERROR)
 			return 1
+
+		ssh_opts = settings.get("PORTAGE_SSH_OPTS")
+
 		if port is None:
 			port=""
 		if user_name is None:
@@ -2370,6 +2373,9 @@
 
 			rsynccommand = [rsync_binary] + rsync_opts + extra_rsync_opts
 
+			if proto == 'ssh' and ssh_opts:
+				rsynccommand.append("--rsh=ssh " + ssh_opts)
+
 			if "--debug" in myopts:
 				print(rsynccommand)
 
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index 14d05ad..77b2886 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -915,10 +915,18 @@
 						# Use a pipe so that we can terminate the download
 						# early if we detect that the TIMESTAMP header
 						# matches that of the cached Packages file.
+						ssh_args = ['ssh']
 						if port is not None:
-							port_args = ['-p', "%s" % (port,)]
-						proc = subprocess.Popen(['ssh'] + port_args + \
-							[user_passwd + host, '--', 'cat', path],
+							ssh_args.append("-p%s" % (port,))
+						# NOTE: shlex evaluates embedded quotes
+						ssh_args.extend(portage.util.shlex_split(
+							self.settings.get("PORTAGE_SSH_OPTS", "")))
+						ssh_args.append(user_passwd + host)
+						ssh_args.append('--')
+						ssh_args.append('cat')
+						ssh_args.append(path)
+
+						proc = subprocess.Popen(ssh_args,
 							stdout=subprocess.PIPE)
 						f = proc.stdout
 					else:
@@ -932,8 +940,21 @@
 						fd, tmp_filename = tempfile.mkstemp()
 						tmp_dirname, tmp_basename = os.path.split(tmp_filename)
 						os.close(fd)
-						success = portage.getbinpkg.file_get(url,
-						     tmp_dirname, fcmd=fcmd, filename=tmp_basename)
+
+						fcmd_vars = {
+							"DISTDIR": tmp_dirname,
+							"FILE": tmp_basename,
+							"URI": url
+						}
+
+						for k in ("PORTAGE_SSH_OPTS",):
+							try:
+								fcmd_vars[k] = self.settings[k]
+							except KeyError:
+								pass
+
+						success = portage.getbinpkg.file_get(
+							fcmd=fcmd, fcmd_vars=fcmd_vars)
 						if not success:
 							raise EnvironmentError("%s failed" % (setting,))
 						f = open(tmp_filename, 'rb')
diff --git a/pym/portage/getbinpkg.py b/pym/portage/getbinpkg.py
index 77c1c8f..ff656ba 100644
--- a/pym/portage/getbinpkg.py
+++ b/pym/portage/getbinpkg.py
@@ -477,7 +477,8 @@
 	return myid
 
 
-def file_get(baseurl,dest,conn=None,fcmd=None,filename=None):
+def file_get(baseurl=None, dest=None, conn=None, fcmd=None, filename=None,
+	fcmd_vars=None):
 	"""(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
 	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""
 
@@ -487,14 +488,30 @@
 			"parameter is deprecated", DeprecationWarning, stacklevel=2)
 
 		return file_get_lib(baseurl,dest,conn)
-	if not filename:
-		filename = os.path.basename(baseurl)
 
-	variables = {
-		"DISTDIR": dest,
-		"URI":     baseurl,
-		"FILE":    filename
-	}
+	variables = {}
+
+	if fcmd_vars is not None:
+		variables.update(fcmd_vars)
+
+	if "DISTDIR" not in variables:
+		if dest is None:
+			raise portage.exception.MissingParameter(
+				_("%s is missing required '%s' key") %
+				("fcmd_vars", "DISTDIR"))
+		variables["DISTDIR"] = dest
+
+	if "URI" not in variables:
+		if baseurl is None:
+			raise portage.exception.MissingParameter(
+				_("%s is missing required '%s' key") %
+				("fcmd_vars", "URI"))
+		variables["URI"] = baseurl
+
+	if "FILE" not in variables:
+		if filename is None:
+			filename = os.path.basename(variables["URI"])
+		variables["FILE"] = filename
 
 	from portage.util import varexpand
 	from portage.process import spawn
diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py
index 9662571..8b9cac1 100644
--- a/pym/portage/package/ebuild/_config/special_env_vars.py
+++ b/pym/portage/package/ebuild/_config/special_env_vars.py
@@ -171,7 +171,7 @@
 	"PORTAGE_REPO_DUPLICATE_WARN",
 	"PORTAGE_RO_DISTDIRS",
 	"PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS",
-	"PORTAGE_RSYNC_RETRIES", "PORTAGE_SYNC_STALE",
+	"PORTAGE_RSYNC_RETRIES", "PORTAGE_SSH_OPTS", "PORTAGE_SYNC_STALE",
 	"PORTAGE_USE", "PORTAGE_XATTR_EXCLUDE",
 	"PORT_LOGDIR", "PORT_LOGDIR_CLEAN",
 	"QUICKPKG_DEFAULT_OPTS", "REPOMAN_DEFAULT_OPTS",
diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py
index 0a7bf10..162c7c2 100644
--- a/pym/portage/package/ebuild/fetch.py
+++ b/pym/portage/package/ebuild/fetch.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Gentoo Foundation
+# Copyright 2010-2013 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import print_function
@@ -964,11 +964,16 @@
 					writemsg_stdout(_(">>> Downloading '%s'\n") % \
 						_hide_url_passwd(loc))
 					variables = {
-						"DISTDIR": mysettings["DISTDIR"],
 						"URI":     loc,
 						"FILE":    myfile
 					}
 
+					for k in ("DISTDIR", "PORTAGE_SSH_OPTS"):
+						try:
+							variables[k] = mysettings[k]
+						except KeyError:
+							pass
+
 					myfetch = shlex_split(locfetch)
 					myfetch = [varexpand(x, mydict=variables) for x in myfetch]
 					myret = -1