[PATCH v2] Add a ssh_config Term option to override TERM

Omar Sandoval osandov at osandov.com
Sat Aug 15 13:35:45 AEST 2015


This is useful when a server is missing the necessary terminfo and
avoids having to manually set TERM before invoking ssh every time.

Signed-off-by: Omar Sandoval <osandov at osandov.com>
---

Changes from v1:

- Allow ``none'' to force using TERM from the environment

I'll elaborate on my use case. I use suckless's st terminal, so I install the
st terminfo on the machines I frequent. On other machines, though, I end up
having to set TERM to xterm manually on the command line, e.g.,

TERM=xterm-256color ssh foo

Instead, it'd be much more convenient to do the following:

Host machine_i_use_alot
	Term none

Host *
	Term xterm-256color

So ssh will default to using xterm-256color, but on hosts that I whitelist, it
will use TERM from the environment.

 mux.c        |  2 +-
 readconf.c   | 10 +++++++++-
 readconf.h   |  2 ++
 ssh.c        |  7 +++++--
 ssh_config.5 | 10 ++++++++++
 5 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/mux.c b/mux.c
index cdc01bd4fff5..1aa21f8eee27 100644
--- a/mux.c
+++ b/mux.c
@@ -1814,7 +1814,7 @@ mux_client_request_session(int fd)
 			close(devnull);
 	}
 
-	term = getenv("TERM");
+	term = options.term;
 
 	buffer_init(&m);
 	buffer_put_int(&m, MUX_C_NEW_SESSION);
diff --git a/readconf.c b/readconf.c
index 1d03bdf72d92..27169a8e9094 100644
--- a/readconf.c
+++ b/readconf.c
@@ -148,7 +148,7 @@ typedef enum {
 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
-	oSendEnv, oControlPath, oControlMaster, oControlPersist,
+	oSendEnv, oTerm, oControlPath, oControlMaster, oControlPersist,
 	oHashKnownHosts,
 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
 	oVisualHostKey, oUseRoaming,
@@ -251,6 +251,7 @@ static struct {
 	{ "serveraliveinterval", oServerAliveInterval },
 	{ "serveralivecountmax", oServerAliveCountMax },
 	{ "sendenv", oSendEnv },
+	{ "term", oTerm },
 	{ "controlpath", oControlPath },
 	{ "controlmaster", oControlMaster },
 	{ "controlpersist", oControlPersist },
@@ -1294,6 +1295,10 @@ parse_keytypes:
 		}
 		break;
 
+	case oTerm:
+		charptr = &options->term;
+		goto parse_string;
+
 	case oControlPath:
 		charptr = &options->control_path;
 		goto parse_string;
@@ -1650,6 +1655,7 @@ initialize_options(Options * options)
 	options->server_alive_interval = -1;
 	options->server_alive_count_max = -1;
 	options->num_send_env = 0;
+	options->term = NULL;
 	options->control_path = NULL;
 	options->control_master = -1;
 	options->control_persist = -1;
@@ -1879,6 +1885,7 @@ fill_default_options(Options * options)
 	/* options->hostname will be set in the main program if appropriate */
 	/* options->host_key_alias should not be set by default */
 	/* options->preferred_authentications will be set in ssh */
+	/* options->term will be set in ssh */
 }
 
 struct fwdarg {
@@ -2302,6 +2309,7 @@ dump_client_config(Options *o, const char *host)
 	/* String options */
 	dump_cfg_string(oBindAddress, o->bind_address);
 	dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
+	dump_cfg_string(oTerm, o->term);
 	dump_cfg_string(oControlPath, o->control_path);
 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
diff --git a/readconf.h b/readconf.h
index bb2d55283dd0..17e02f24ae4e 100644
--- a/readconf.h
+++ b/readconf.h
@@ -115,6 +115,8 @@ typedef struct {
 	int     num_send_env;
 	char   *send_env[MAX_SEND_ENV];
 
+	char   *term;
+
 	char	*control_path;
 	int	control_master;
 	int     control_persist; /* ControlPersist flag */
diff --git a/ssh.c b/ssh.c
index 59c1f931cb0a..db8bfd2d32eb 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1117,6 +1117,9 @@ main(int ac, char **av)
 	if (options.user == NULL)
 		options.user = xstrdup(pw->pw_name);
 
+	if (option_clear_or_none(options.term))
+		options.term = getenv("TERM");
+
 	if (gethostname(thishost, sizeof(thishost)) == -1)
 		fatal("gethostname: %s", strerror(errno));
 	strlcpy(shorthost, thishost, sizeof(shorthost));
@@ -1638,7 +1641,7 @@ ssh_session(void)
 
 		/* Store TERM in the packet.  There is no limit on the
 		   length of the string. */
-		cp = getenv("TERM");
+		cp = options.term;
 		if (!cp)
 			cp = "";
 		packet_put_cstring(cp);
@@ -1804,7 +1807,7 @@ ssh_session2_setup(int id, int success, void *arg)
 	packet_set_interactive(interactive,
 	    options.ip_qos_interactive, options.ip_qos_bulk);
 
-	client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
+	client_session2_setup(id, tty_flag, subsystem_flag, options.term,
 	    NULL, fileno(stdin), &command, environ);
 }
 
diff --git a/ssh_config.5 b/ssh_config.5
index 5b0975f87e2f..b0441f1c4dda 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1521,6 +1521,16 @@ This is important in scripts, and many users want it too.
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm Term
+Specifies the
+.Ev TERM
+environment variable which is sent to the server. This can be useful when the
+server does not have the proper terminfo installed. By default, or if set to
+.Dq none ,
+the server gets the
+.Ev TERM
+variable from the local
+.Xr environ 7 .
 .It Cm Tunnel
 Request
 .Xr tun 4
-- 
2.5.0



More information about the openssh-unix-dev mailing list