and have a function to pass in a new one. (Well, actually several
back ends don't actually bother to do this because they need nothing
out of Config after the initial setup phase, but they could if they
wanted to.)
git-svn-id: svn://svn.tartarus.org/sgt/putty@2561
cda61777-01e9-0310-a592-
d414129be87e
12 files changed:
int nodelay = cfg.tcp_nodelay &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
int nodelay = cfg.tcp_nodelay &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
- error = back->init(NULL, &backhandle, cfg.host, cfg.port,
+ error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
&realhost, nodelay);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
&realhost, nodelay);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
- err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0);
+ err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0);
if (err != NULL) {
fprintf(stderr, "ssh_init: %s\n", err);
return 1;
if (err != NULL) {
fprintf(stderr, "ssh_init: %s\n", err);
return 1;
- char *(*init) (void *frontend_handle, void **backend_handle,
+ char *(*init) (void *frontend_handle, void **backend_handle, Config *cfg,
char *host, int port, char **realhost, int nodelay);
char *host, int port, char **realhost, int nodelay);
+ /* back->reconfig() passes in a replacement configuration. */
+ void (*reconfig) (void *handle, Config *cfg);
/* back->send() returns the current amount of buffered data. */
int (*send) (void *handle, char *buf, int len);
/* back->sendbuffer() does the same thing but without attempting a send */
/* back->send() returns the current amount of buffered data. */
int (*send) (void *handle, char *buf, int len);
/* back->sendbuffer() does the same thing but without attempting a send */
* freed by the caller.
*/
static char *raw_init(void *frontend_handle, void **backend_handle,
* freed by the caller.
*/
static char *raw_init(void *frontend_handle, void **backend_handle,
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
+ * Stub routine (we don't have any need to reconfigure this backend).
+ */
+static void raw_reconfig(void *handle, Config *cfg)
+{
+}
+
+/*
* Called to send data down the raw connection.
*/
static int raw_send(void *handle, char *buf, int len)
* Called to send data down the raw connection.
*/
static int raw_send(void *handle, char *buf, int len)
Backend raw_backend = {
raw_init,
Backend raw_backend = {
raw_init,
raw_send,
raw_sendbuffer,
raw_size,
raw_send,
raw_sendbuffer,
raw_size,
* freed by the caller.
*/
static char *rlogin_init(void *frontend_handle, void **backend_handle,
* freed by the caller.
*/
static char *rlogin_init(void *frontend_handle, void **backend_handle,
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
rlogin->fn = &fn_table;
rlogin->s = NULL;
rlogin->frontend = frontend_handle;
rlogin->fn = &fn_table;
rlogin->s = NULL;
rlogin->frontend = frontend_handle;
- rlogin->term_width = cfg.width;
- rlogin->term_height = cfg.height;
+ rlogin->term_width = cfg->width;
+ rlogin->term_height = cfg->height;
*backend_handle = rlogin;
/*
*backend_handle = rlogin;
/*
char z = 0;
char *p;
sk_write(rlogin->s, &z, 1);
char z = 0;
char *p;
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, cfg.localusername, strlen(cfg.localusername));
+ sk_write(rlogin->s, cfg->localusername,
+ strlen(cfg->localusername));
sk_write(rlogin->s, &z, 1);
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, cfg.username, strlen(cfg.username));
+ sk_write(rlogin->s, cfg->username,
+ strlen(cfg->username));
sk_write(rlogin->s, &z, 1);
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, cfg.termtype, strlen(cfg.termtype));
+ sk_write(rlogin->s, cfg->termtype,
+ strlen(cfg->termtype));
sk_write(rlogin->s, "/", 1);
sk_write(rlogin->s, "/", 1);
- for (p = cfg.termspeed; isdigit(*p); p++) continue;
- sk_write(rlogin->s, cfg.termspeed, p - cfg.termspeed);
+ for (p = cfg->termspeed; isdigit(*p); p++) continue;
+ sk_write(rlogin->s, cfg->termspeed, p - cfg->termspeed);
rlogin->bufsize = sk_write(rlogin->s, &z, 1);
}
rlogin->bufsize = sk_write(rlogin->s, &z, 1);
}
+ * Stub routine (we don't have any need to reconfigure this backend).
+ */
+static void rlogin_reconfig(void *handle, Config *cfg)
+{
+}
+
+/*
* Called to send data down the rlogin connection.
*/
static int rlogin_send(void *handle, char *buf, int len)
* Called to send data down the rlogin connection.
*/
static int rlogin_send(void *handle, char *buf, int len)
Backend rlogin_backend = {
rlogin_init,
Backend rlogin_backend = {
rlogin_init,
rlogin_send,
rlogin_sendbuffer,
rlogin_size,
rlogin_send,
rlogin_sendbuffer,
rlogin_size,
- err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0);
+ err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0);
if (err != NULL)
bump("ssh_init: %s", err);
logctx = log_init(NULL);
if (err != NULL)
bump("ssh_init: %s", err);
logctx = log_init(NULL);
void (*protocol) (Ssh ssh, unsigned char *in, int inlen, int ispkt);
int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
void (*protocol) (Ssh ssh, unsigned char *in, int inlen, int ispkt);
int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
+
+ /*
+ * We maintain a full _copy_ of a Config structure here, not
+ * merely a pointer to it. That way, when we're passed a new
+ * one for reconfiguration, we can check the differences and
+ * potentially reconfigure port forwardings etc in mid-session.
+ */
+ Config cfg;
};
#define logevent(s) logevent(ssh->frontend, s)
};
#define logevent(s) logevent(ssh->frontend, s)
- if (cfg.sshbug_ignore1 == BUG_ON ||
- (cfg.sshbug_ignore1 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_ignore1 == BUG_ON ||
+ (ssh->cfg.sshbug_ignore1 == BUG_AUTO &&
(!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
!strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
!strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) {
(!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
!strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
!strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) {
logevent("We believe remote version has SSH1 ignore bug");
}
logevent("We believe remote version has SSH1 ignore bug");
}
- if (cfg.sshbug_plainpw1 == BUG_ON ||
- (cfg.sshbug_plainpw1 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_plainpw1 == BUG_ON ||
+ (ssh->cfg.sshbug_plainpw1 == BUG_AUTO &&
(!strcmp(imp, "Cisco-1.25")))) {
/*
* These versions need a plain password sent; they can't
(!strcmp(imp, "Cisco-1.25")))) {
/*
* These versions need a plain password sent; they can't
logevent("We believe remote version needs a plain SSH1 password");
}
logevent("We believe remote version needs a plain SSH1 password");
}
- if (cfg.sshbug_rsa1 == BUG_ON ||
- (cfg.sshbug_rsa1 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_rsa1 == BUG_ON ||
+ (ssh->cfg.sshbug_rsa1 == BUG_AUTO &&
(!strcmp(imp, "Cisco-1.25")))) {
/*
* These versions apparently have no clue whatever about
(!strcmp(imp, "Cisco-1.25")))) {
/*
* These versions apparently have no clue whatever about
logevent("We believe remote version can't handle RSA authentication");
}
logevent("We believe remote version can't handle RSA authentication");
}
- if (cfg.sshbug_hmac2 == BUG_ON ||
- (cfg.sshbug_hmac2 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_hmac2 == BUG_ON ||
+ (ssh->cfg.sshbug_hmac2 == BUG_AUTO &&
(wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
wc_match("2.1 *", imp)))) {
(wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
wc_match("2.1 *", imp)))) {
logevent("We believe remote version has SSH2 HMAC bug");
}
logevent("We believe remote version has SSH2 HMAC bug");
}
- if (cfg.sshbug_derivekey2 == BUG_ON ||
- (cfg.sshbug_derivekey2 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_derivekey2 == BUG_ON ||
+ (ssh->cfg.sshbug_derivekey2 == BUG_AUTO &&
(wc_match("2.0.0*", imp) || wc_match("2.0.1[01]*", imp) ))) {
/*
* These versions have the key-derivation bug (failing to
(wc_match("2.0.0*", imp) || wc_match("2.0.1[01]*", imp) ))) {
/*
* These versions have the key-derivation bug (failing to
logevent("We believe remote version has SSH2 key-derivation bug");
}
logevent("We believe remote version has SSH2 key-derivation bug");
}
- if (cfg.sshbug_rsapad2 == BUG_ON ||
- (cfg.sshbug_rsapad2 == BUG_AUTO &&
+ if (ssh->cfg.sshbug_rsapad2 == BUG_ON ||
+ (ssh->cfg.sshbug_rsapad2 == BUG_AUTO &&
(wc_match("OpenSSH_2.[5-9]*", imp) ||
wc_match("OpenSSH_3.[0-2]*", imp)))) {
/*
(wc_match("OpenSSH_2.[5-9]*", imp) ||
wc_match("OpenSSH_3.[0-2]*", imp)))) {
/*
logevent("We believe remote version has SSH2 RSA padding bug");
}
logevent("We believe remote version has SSH2 RSA padding bug");
}
- if (cfg.sshbug_dhgex2 == BUG_ON) {
+ if (ssh->cfg.sshbug_dhgex2 == BUG_ON) {
/*
* User specified the SSH2 DH GEX bug.
*/
/*
* User specified the SSH2 DH GEX bug.
*/
/* Anything greater or equal to "1.99" means protocol 2 is supported. */
s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
/* Anything greater or equal to "1.99" means protocol 2 is supported. */
s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
- if (cfg.sshprot == 0 && !s->proto1) {
+ if (ssh->cfg.sshprot == 0 && !s->proto1) {
bombout((ssh,"SSH protocol version 1 required by user but not provided by server"));
crReturn(0);
}
bombout((ssh,"SSH protocol version 1 required by user but not provided by server"));
crReturn(0);
}
- if (cfg.sshprot == 3 && !s->proto2) {
+ if (ssh->cfg.sshprot == 3 && !s->proto2) {
bombout((ssh,"SSH protocol version 2 required by user but not provided by server"));
crReturn(0);
}
bombout((ssh,"SSH protocol version 2 required by user but not provided by server"));
crReturn(0);
}
- if (s->proto2 && (cfg.sshprot >= 2 || !s->proto1)) {
+ if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1)) {
char *cipher_string = NULL;
int i;
for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
char *cipher_string = NULL;
int i;
for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
- int next_cipher = cfg.ssh_cipherlist[i];
+ int next_cipher = ssh->cfg.ssh_cipherlist[i];
if (next_cipher == CIPHER_WARN) {
/* If/when we choose a cipher, warn about it */
warn = 1;
if (next_cipher == CIPHER_WARN) {
/* If/when we choose a cipher, warn about it */
warn = 1;
- if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
+ if ((flags & FLAG_INTERACTIVE) && !*ssh->cfg.username) {
if (ssh_get_line && !ssh_getline_pw_only) {
if (!ssh_get_line("login as: ",
s->username, sizeof(s->username), FALSE)) {
if (ssh_get_line && !ssh_getline_pw_only) {
if (!ssh_get_line("login as: ",
s->username, sizeof(s->username), FALSE)) {
c_write_str(ssh, "\r\n");
}
} else {
c_write_str(ssh, "\r\n");
}
} else {
- strncpy(s->username, cfg.username, sizeof(s->username));
+ strncpy(s->username, ssh->cfg.username, sizeof(s->username));
s->username[sizeof(s->username)-1] = '\0';
}
s->username[sizeof(s->username)-1] = '\0';
}
s->tried_publickey = s->tried_agent = 0;
}
s->tis_auth_refused = s->ccard_auth_refused = 0;
s->tried_publickey = s->tried_agent = 0;
}
s->tis_auth_refused = s->ccard_auth_refused = 0;
- /* Load the public half of cfg.keyfile so we notice if it's in Pageant */
- if (*cfg.keyfile) {
- if (!rsakey_pubblob(cfg.keyfile,
+ /* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */
+ if (*ssh->cfg.keyfile) {
+ if (!rsakey_pubblob(ssh->cfg.keyfile,
&s->publickey_blob, &s->publickey_bloblen))
s->publickey_blob = NULL;
} else
&s->publickey_blob, &s->publickey_bloblen))
s->publickey_blob = NULL;
} else
- if (*cfg.keyfile && !s->tried_publickey)
+ if (*ssh->cfg.keyfile && !s->tried_publickey)
s->pwpkt_type = SSH1_CMSG_AUTH_RSA;
s->pwpkt_type = SSH1_CMSG_AUTH_RSA;
- if (cfg.try_tis_auth &&
+ if (ssh->cfg.try_tis_auth &&
(s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
!s->tis_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
(s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
!s->tis_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
s->prompt[(sizeof s->prompt) - 1] = '\0';
}
}
s->prompt[(sizeof s->prompt) - 1] = '\0';
}
}
- if (cfg.try_tis_auth &&
+ if (ssh->cfg.try_tis_auth &&
(s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
!s->ccard_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
(s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
!s->ccard_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
char msgbuf[256];
if (flags & FLAG_VERBOSE)
c_write_str(ssh, "Trying public key authentication.\r\n");
char msgbuf[256];
if (flags & FLAG_VERBOSE)
c_write_str(ssh, "Trying public key authentication.\r\n");
- logeventf(ssh, "Trying public key \"%s\"", cfg.keyfile);
- type = key_type(cfg.keyfile);
+ logeventf(ssh, "Trying public key \"%s\"", ssh->cfg.keyfile);
+ type = key_type(ssh->cfg.keyfile);
if (type != SSH_KEYTYPE_SSH1) {
sprintf(msgbuf, "Key is of wrong type (%s)",
key_type_to_str(type));
if (type != SSH_KEYTYPE_SSH1) {
sprintf(msgbuf, "Key is of wrong type (%s)",
key_type_to_str(type));
s->tried_publickey = 1;
continue;
}
s->tried_publickey = 1;
continue;
}
- if (!rsakey_encrypted(cfg.keyfile, &comment)) {
+ if (!rsakey_encrypted(ssh->cfg.keyfile, &comment)) {
if (flags & FLAG_VERBOSE)
c_write_str(ssh, "No passphrase required.\r\n");
goto tryauth;
if (flags & FLAG_VERBOSE)
c_write_str(ssh, "No passphrase required.\r\n");
goto tryauth;
s->tried_publickey = 1;
{
s->tried_publickey = 1;
{
- int ret = loadrsakey(cfg.keyfile, &s->key, s->password);
+ int ret = loadrsakey(ssh->cfg.keyfile, &s->key, s->password);
if (ret == 0) {
c_write_str(ssh, "Couldn't load private key from ");
if (ret == 0) {
c_write_str(ssh, "Couldn't load private key from ");
- c_write_str(ssh, cfg.keyfile);
+ c_write_str(ssh, ssh->cfg.keyfile);
c_write_str(ssh, ".\r\n");
continue; /* go and try password */
}
c_write_str(ssh, ".\r\n");
continue; /* go and try password */
}
if (ssh->state == SSH_STATE_CLOSED)
crReturnV;
if (ssh->state == SSH_STATE_CLOSED)
crReturnV;
- if (cfg.agentfwd && agent_exists()) {
+ if (ssh->cfg.agentfwd && agent_exists()) {
logevent("Requesting agent forwarding");
send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do {
logevent("Requesting agent forwarding");
send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do {
+ if (ssh->cfg.x11_forward) {
char proto[20], data[64];
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
char proto[20], data[64];
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
- data, sizeof(data), cfg.x11_auth);
- x11_get_real_auth(ssh->x11auth, cfg.x11_display);
+ data, sizeof(data), ssh->cfg.x11_auth);
+ x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display);
if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
PKT_STR, proto, PKT_STR, data,
if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
PKT_STR, proto, PKT_STR, data,
- PKT_INT, x11_get_screen_number(cfg.x11_display),
+ PKT_INT, x11_get_screen_number(ssh->cfg.x11_display),
PKT_END);
} else {
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
PKT_END);
} else {
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);
/* Add port forwardings. */
ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);
/* Add port forwardings. */
- ssh->portfwd_strptr = cfg.portfwd;
+ ssh->portfwd_strptr = ssh->cfg.portfwd;
while (*ssh->portfwd_strptr) {
type = *ssh->portfwd_strptr++;
saddr[0] = '\0';
while (*ssh->portfwd_strptr) {
type = *ssh->portfwd_strptr++;
saddr[0] = '\0';
send_packet(ssh, SSH1_CMSG_REQUEST_PTY,
send_packet(ssh, SSH1_CMSG_REQUEST_PTY,
+ PKT_STR, ssh->cfg.termtype,
PKT_INT, ssh->term_height,
PKT_INT, ssh->term_width,
PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END);
PKT_INT, ssh->term_height,
PKT_INT, ssh->term_width,
PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END);
ssh->editing = ssh->echoing = 1;
}
ssh->editing = ssh->echoing = 1;
}
+ if (ssh->cfg.compression) {
send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
do {
crReturnV;
send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
do {
crReturnV;
* exists, we fall straight back to that.
*/
{
* exists, we fall straight back to that.
*/
{
- char *cmd = cfg.remote_cmd_ptr;
+ char *cmd = ssh->cfg.remote_cmd_ptr;
- if (cfg.ssh_subsys && cfg.remote_cmd_ptr2) {
- cmd = cfg.remote_cmd_ptr2;
+ if (ssh->cfg.ssh_subsys && ssh->cfg.remote_cmd_ptr2) {
+ cmd = ssh->cfg.remote_cmd_ptr2;
ssh->fallback_cmd = TRUE;
}
if (*cmd)
ssh->fallback_cmd = TRUE;
}
if (*cmd)
c = smalloc(sizeof(struct ssh_channel));
c->ssh = ssh;
c = smalloc(sizeof(struct ssh_channel));
c->ssh = ssh;
- if (x11_init(&c->u.x11.s, cfg.x11_display, c,
+ if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
ssh->x11auth, NULL, -1) != NULL) {
logevent("opening X11 forward connection failed");
sfree(c);
ssh->x11auth, NULL, -1) != NULL) {
logevent("opening X11 forward connection failed");
sfree(c);
*/
s->n_preferred_ciphers = 0;
for (i = 0; i < CIPHER_MAX; i++) {
*/
s->n_preferred_ciphers = 0;
for (i = 0; i < CIPHER_MAX; i++) {
- switch (cfg.ssh_cipherlist[i]) {
+ switch (ssh->cfg.ssh_cipherlist[i]) {
case CIPHER_BLOWFISH:
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;
break;
case CIPHER_DES:
case CIPHER_BLOWFISH:
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;
break;
case CIPHER_DES:
- if (cfg.ssh2_des_cbc) {
+ if (ssh->cfg.ssh2_des_cbc) {
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;
}
break;
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;
}
break;
/*
* Set up preferred compression.
*/
/*
* Set up preferred compression.
*/
+ if (ssh->cfg.compression)
s->preferred_comp = &ssh_zlib;
else
s->preferred_comp = &ssh_comp_none;
s->preferred_comp = &ssh_zlib;
else
s->preferred_comp = &ssh_comp_none;
- if (s->got_username && !cfg.change_username) {
+ if (s->got_username && !ssh->cfg.change_username) {
/*
* We got a username last time round this loop, and
* with change_username turned off we don't try to get
* it again.
*/
/*
* We got a username last time round this loop, and
* with change_username turned off we don't try to get
* it again.
*/
- } else if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
+ } else if ((flags & FLAG_INTERACTIVE) && !*ssh->cfg.username) {
if (ssh_get_line && !ssh_getline_pw_only) {
if (!ssh_get_line("login as: ",
s->username, sizeof(s->username), FALSE)) {
if (ssh_get_line && !ssh_getline_pw_only) {
if (!ssh_get_line("login as: ",
s->username, sizeof(s->username), FALSE)) {
s->username[strcspn(s->username, "\n\r")] = '\0';
} else {
char *stuff;
s->username[strcspn(s->username, "\n\r")] = '\0';
} else {
char *stuff;
- strncpy(s->username, cfg.username, sizeof(s->username));
+ strncpy(s->username, ssh->cfg.username, sizeof(s->username));
s->username[sizeof(s->username)-1] = '\0';
if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
stuff = dupprintf("Using username \"%s\".\r\n", s->username);
s->username[sizeof(s->username)-1] = '\0';
if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
stuff = dupprintf("Using username \"%s\".\r\n", s->username);
s->tried_agent = FALSE;
s->tried_keyb_inter = FALSE;
s->kbd_inter_running = FALSE;
s->tried_agent = FALSE;
s->tried_keyb_inter = FALSE;
s->kbd_inter_running = FALSE;
- /* Load the pub half of cfg.keyfile so we notice if it's in Pageant */
- if (*cfg.keyfile) {
+ /* Load the pub half of ssh->cfg.keyfile so we notice if it's in Pageant */
+ if (*ssh->cfg.keyfile) {
- logeventf(ssh, "Reading private key file \"%.150s\"", cfg.keyfile);
- keytype = key_type(cfg.keyfile);
+ logeventf(ssh, "Reading private key file \"%.150s\"", ssh->cfg.keyfile);
+ keytype = key_type(ssh->cfg.keyfile);
if (keytype == SSH_KEYTYPE_SSH2) {
s->publickey_blob =
if (keytype == SSH_KEYTYPE_SSH2) {
s->publickey_blob =
- ssh2_userkey_loadpub(cfg.keyfile, NULL,
+ ssh2_userkey_loadpub(ssh->cfg.keyfile, NULL,
&s->publickey_bloblen);
} else {
char *msgbuf;
logeventf(ssh, "Unable to use this key file (%s)",
key_type_to_str(keytype));
msgbuf = dupprintf("Unable to use key file \"%.150s\""
&s->publickey_bloblen);
} else {
char *msgbuf;
logeventf(ssh, "Unable to use this key file (%s)",
key_type_to_str(keytype));
msgbuf = dupprintf("Unable to use key file \"%.150s\""
- " (%s)\r\n", cfg.keyfile,
+ " (%s)\r\n", ssh->cfg.keyfile,
key_type_to_str(keytype));
c_write_str(ssh, msgbuf);
sfree(msgbuf);
key_type_to_str(keytype));
c_write_str(ssh, msgbuf);
sfree(msgbuf);
in_commasep_string("publickey", methods, methlen);
s->can_passwd =
in_commasep_string("password", methods, methlen);
in_commasep_string("publickey", methods, methlen);
s->can_passwd =
in_commasep_string("password", methods, methlen);
- s->can_keyb_inter = cfg.try_ki_auth &&
+ s->can_keyb_inter = ssh->cfg.try_ki_auth &&
in_commasep_string("keyboard-interactive", methods, methlen);
}
in_commasep_string("keyboard-interactive", methods, methlen);
}
* willing to accept it.
*/
pub_blob =
* willing to accept it.
*/
pub_blob =
- (unsigned char *)ssh2_userkey_loadpub(cfg.keyfile,
+ (unsigned char *)ssh2_userkey_loadpub(ssh->cfg.keyfile,
&algorithm,
&pub_blob_len);
if (pub_blob) {
&algorithm,
&pub_blob_len);
if (pub_blob) {
* Actually attempt a serious authentication using
* the key.
*/
* Actually attempt a serious authentication using
* the key.
*/
- if (ssh2_userkey_encrypted(cfg.keyfile, &comment)) {
+ if (ssh2_userkey_encrypted(ssh->cfg.keyfile, &comment)) {
sprintf(s->pwprompt,
"Passphrase for key \"%.100s\": ",
comment);
sprintf(s->pwprompt,
"Passphrase for key \"%.100s\": ",
comment);
*/
struct ssh2_userkey *key;
*/
struct ssh2_userkey *key;
- key = ssh2_load_userkey(cfg.keyfile, s->password);
+ key = ssh2_load_userkey(ssh->cfg.keyfile, s->password);
if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
if (key == SSH2_WRONG_PASSPHRASE) {
c_write_str(ssh, "Wrong passphrase\r\n");
if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
if (key == SSH2_WRONG_PASSPHRASE) {
c_write_str(ssh, "Wrong passphrase\r\n");
/*
* Potentially enable X11 forwarding.
*/
/*
* Potentially enable X11 forwarding.
*/
+ if (ssh->cfg.x11_forward) {
char proto[20], data[64];
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
char proto[20], data[64];
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
- data, sizeof(data), cfg.x11_auth);
- x11_get_real_auth(ssh->x11auth, cfg.x11_display);
+ data, sizeof(data), ssh->cfg.x11_auth);
+ x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display);
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
ssh2_pkt_addstring(ssh, "x11-req");
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
ssh2_pkt_addstring(ssh, "x11-req");
ssh2_pkt_addbool(ssh, 0); /* many connections */
ssh2_pkt_addstring(ssh, proto);
ssh2_pkt_addstring(ssh, data);
ssh2_pkt_addbool(ssh, 0); /* many connections */
ssh2_pkt_addstring(ssh, proto);
ssh2_pkt_addstring(ssh, data);
- ssh2_pkt_adduint32(ssh, x11_get_screen_number(cfg.x11_display));
+ ssh2_pkt_adduint32(ssh, x11_get_screen_number(ssh->cfg.x11_display));
ssh->rportfwds = newtree234(ssh_rportcmp_ssh2);
/* Add port forwardings. */
ssh->rportfwds = newtree234(ssh_rportcmp_ssh2);
/* Add port forwardings. */
- ssh->portfwd_strptr = cfg.portfwd;
+ ssh->portfwd_strptr = ssh->cfg.portfwd;
while (*ssh->portfwd_strptr) {
type = *ssh->portfwd_strptr++;
saddr[0] = '\0';
while (*ssh->portfwd_strptr) {
type = *ssh->portfwd_strptr++;
saddr[0] = '\0';
ssh2_pkt_addbool(ssh, 1);/* want reply */
if (*saddr)
ssh2_pkt_addstring(ssh, saddr);
ssh2_pkt_addbool(ssh, 1);/* want reply */
if (*saddr)
ssh2_pkt_addstring(ssh, saddr);
- if (cfg.rport_acceptall)
+ if (ssh->cfg.rport_acceptall)
ssh2_pkt_addstring(ssh, "0.0.0.0");
else
ssh2_pkt_addstring(ssh, "127.0.0.1");
ssh2_pkt_addstring(ssh, "0.0.0.0");
else
ssh2_pkt_addstring(ssh, "127.0.0.1");
/*
* Potentially enable agent forwarding.
*/
/*
* Potentially enable agent forwarding.
*/
- if (cfg.agentfwd && agent_exists()) {
+ if (ssh->cfg.agentfwd && agent_exists()) {
logevent("Requesting OpenSSH-style agent forwarding");
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
logevent("Requesting OpenSSH-style agent forwarding");
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
/*
* Now allocate a pty for the session.
*/
/*
* Now allocate a pty for the session.
*/
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); /* recipient channel */
ssh2_pkt_addstring(ssh, "pty-req");
ssh2_pkt_addbool(ssh, 1); /* want reply */
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); /* recipient channel */
ssh2_pkt_addstring(ssh, "pty-req");
ssh2_pkt_addbool(ssh, 1); /* want reply */
- ssh2_pkt_addstring(ssh, cfg.termtype);
+ ssh2_pkt_addstring(ssh, ssh->cfg.termtype);
ssh2_pkt_adduint32(ssh, ssh->term_width);
ssh2_pkt_adduint32(ssh, ssh->term_height);
ssh2_pkt_adduint32(ssh, 0); /* pixel width */
ssh2_pkt_adduint32(ssh, ssh->term_width);
ssh2_pkt_adduint32(ssh, ssh->term_height);
ssh2_pkt_adduint32(ssh, 0); /* pixel width */
char *cmd;
if (ssh->fallback_cmd) {
char *cmd;
if (ssh->fallback_cmd) {
- subsys = cfg.ssh_subsys2;
- cmd = cfg.remote_cmd_ptr2;
+ subsys = ssh->cfg.ssh_subsys2;
+ cmd = ssh->cfg.remote_cmd_ptr2;
- subsys = cfg.ssh_subsys;
- cmd = cfg.remote_cmd_ptr;
+ subsys = ssh->cfg.ssh_subsys;
+ cmd = ssh->cfg.remote_cmd_ptr;
}
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
}
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
* not, and if the fallback command exists, try falling
* back to it before complaining.
*/
* not, and if the fallback command exists, try falling
* back to it before complaining.
*/
- if (!ssh->fallback_cmd && cfg.remote_cmd_ptr2 != NULL) {
+ if (!ssh->fallback_cmd && ssh->cfg.remote_cmd_ptr2 != NULL) {
logevent("Primary command failed; attempting fallback");
ssh->fallback_cmd = TRUE;
continue;
logevent("Primary command failed; attempting fallback");
ssh->fallback_cmd = TRUE;
continue;
if (!ssh->X11_fwd_enabled)
error = "X11 forwarding is not enabled";
if (!ssh->X11_fwd_enabled)
error = "X11 forwarding is not enabled";
- else if (x11_init(&c->u.x11.s, cfg.x11_display, c,
+ else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
ssh->x11auth, addrstr, port) != NULL) {
error = "Unable to open an X11 connection";
} else {
ssh->x11auth, addrstr, port) != NULL) {
error = "Unable to open an X11 connection";
} else {
* Returns an error message, or NULL on success.
*/
static char *ssh_init(void *frontend_handle, void **backend_handle,
* Returns an error message, or NULL on success.
*/
static char *ssh_init(void *frontend_handle, void **backend_handle,
char *host, int port, char **realhost, int nodelay)
{
char *p;
Ssh ssh;
ssh = smalloc(sizeof(*ssh));
char *host, int port, char **realhost, int nodelay)
{
char *p;
Ssh ssh;
ssh = smalloc(sizeof(*ssh));
+ ssh->cfg = *cfg; /* STRUCTURE COPY */
ssh->s = NULL;
ssh->cipher = NULL;
ssh->v1_cipher_ctx = NULL;
ssh->s = NULL;
ssh->cipher = NULL;
ssh->v1_cipher_ctx = NULL;
#endif
ssh->frontend = frontend_handle;
#endif
ssh->frontend = frontend_handle;
- ssh->term_width = cfg.width;
- ssh->term_height = cfg.height;
+ ssh->term_width = ssh->cfg.width;
+ ssh->term_height = ssh->cfg.height;
ssh->send_ok = 0;
ssh->editing = 0;
ssh->send_ok = 0;
ssh->editing = 0;
+ * Reconfigure the SSH backend.
+ *
+ * Currently, this function does nothing very useful. In future,
+ * however, we could do some handy things with it. For example, we
+ * could make the port forwarding configurer active in the Change
+ * Settings box, and this routine could close down existing
+ * forwardings and open up new ones in response to changes.
+ */
+static void ssh_reconfig(void *handle, Config *cfg)
+{
+ Ssh ssh = (Ssh) handle;
+ ssh->cfg = *cfg; /* STRUCTURE COPY */
+}
+
+/*
* Called to send data down the Telnet connection.
*/
static int ssh_send(void *handle, char *buf, int len)
* Called to send data down the Telnet connection.
*/
static int ssh_send(void *handle, char *buf, int len)
ssh->size_needed = TRUE; /* buffer for later */
break;
case SSH_STATE_SESSION:
ssh->size_needed = TRUE; /* buffer for later */
break;
case SSH_STATE_SESSION:
if (ssh->version == 1) {
send_packet(ssh, SSH1_CMSG_WINDOW_SIZE,
PKT_INT, ssh->term_height,
if (ssh->version == 1) {
send_packet(ssh, SSH1_CMSG_WINDOW_SIZE,
PKT_INT, ssh->term_height,
Backend ssh_backend = {
ssh_init,
Backend ssh_backend = {
ssh_init,
ssh_send,
ssh_sendbuffer,
ssh_size,
ssh_send,
ssh_sendbuffer,
ssh_size,
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} state;
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} state;
} *Telnet;
#define TELNET_MAX_BACKLOG 4096
} *Telnet;
#define TELNET_MAX_BACKLOG 4096
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
- strcpy((char *)(b + 4), cfg.termspeed);
- n = 4 + strlen(cfg.termspeed);
+ strcpy((char *)(b + 4), telnet->cfg.termspeed);
+ n = 4 + strlen(telnet->cfg.termspeed);
b[n] = IAC;
b[n + 1] = SE;
telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2);
logevent(telnet->frontend, "server:\tSB TSPEED SEND");
b[n] = IAC;
b[n + 1] = SE;
telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2);
logevent(telnet->frontend, "server:\tSB TSPEED SEND");
- logbuf = dupprintf("client:\tSB TSPEED IS %s", cfg.termspeed);
+ logbuf = dupprintf("client:\tSB TSPEED IS %s", telnet->cfg.termspeed);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
} else
logevent(telnet->frontend, logbuf);
sfree(logbuf);
} else
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
- for (n = 0; cfg.termtype[n]; n++)
- b[n + 4] = (cfg.termtype[n] >= 'a'
- && cfg.termtype[n] <=
- 'z' ? cfg.termtype[n] + 'A' -
- 'a' : cfg.termtype[n]);
+ for (n = 0; telnet->cfg.termtype[n]; n++)
+ b[n + 4] = (telnet->cfg.termtype[n] >= 'a'
+ && telnet->cfg.termtype[n] <=
+ 'z' ? telnet->cfg.termtype[n] + 'A' -
+ 'a' : telnet->cfg.termtype[n]);
b[n + 4] = IAC;
b[n + 5] = SE;
telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6);
b[n + 4] = IAC;
b[n + 5] = SE;
telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
logevent(telnet->frontend, logbuf);
sfree(logbuf);
if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
+ if (telnet->cfg.rfc_environ) {
value = RFC_VALUE;
var = RFC_VAR;
} else {
value = RFC_VALUE;
var = RFC_VAR;
} else {
b[2] = telnet->sb_opt;
b[3] = TELQUAL_IS;
n = 4;
b[2] = telnet->sb_opt;
b[3] = TELQUAL_IS;
n = 4;
+ e = telnet->cfg.environmt;
while (*e) {
b[n++] = var;
while (*e && *e != '\t')
while (*e) {
b[n++] = var;
while (*e && *e != '\t')
+ if (*telnet->cfg.username) {
b[n++] = var;
b[n++] = 'U';
b[n++] = 'S';
b[n++] = 'E';
b[n++] = 'R';
b[n++] = value;
b[n++] = var;
b[n++] = 'U';
b[n++] = 'S';
b[n++] = 'E';
b[n++] = 'R';
b[n++] = value;
+ e = telnet->cfg.username;
while (*e)
b[n++] = *e++;
}
while (*e)
b[n++] = *e++;
}
* freed by the caller.
*/
static char *telnet_init(void *frontend_handle, void **backend_handle,
* freed by the caller.
*/
static char *telnet_init(void *frontend_handle, void **backend_handle,
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
telnet = smalloc(sizeof(*telnet));
telnet->fn = &fn_table;
telnet = smalloc(sizeof(*telnet));
telnet->fn = &fn_table;
+ telnet->cfg = *cfg; /* STRUCTURE COPY */
telnet->s = NULL;
telnet->echoing = TRUE;
telnet->editing = TRUE;
telnet->s = NULL;
telnet->echoing = TRUE;
telnet->editing = TRUE;
telnet->sb_buf = NULL;
telnet->sb_size = 0;
telnet->frontend = frontend_handle;
telnet->sb_buf = NULL;
telnet->sb_size = 0;
telnet->frontend = frontend_handle;
- telnet->term_width = cfg.width;
- telnet->term_height = cfg.height;
+ telnet->term_width = telnet->cfg.width;
+ telnet->term_height = telnet->cfg.height;
telnet->state = TOP_LEVEL;
*backend_handle = telnet;
telnet->state = TOP_LEVEL;
*backend_handle = telnet;
/*
* Initialise option states.
*/
/*
* Initialise option states.
*/
- if (cfg.passive_telnet) {
+ if (telnet->cfg.passive_telnet) {
const struct Opt *const *o;
for (o = opts; *o; o++)
const struct Opt *const *o;
for (o = opts; *o; o++)
+ * Reconfigure the Telnet backend. There's no immediate action
+ * necessary, in this backend: we just save the fresh config for
+ * any subsequent negotiations.
+ */
+static void telnet_reconfig(void *handle, Config *cfg)
+{
+ Telnet telnet = (Telnet) handle;
+ telnet->cfg = *cfg; /* STRUCTURE COPY */
+}
+
+/*
* Called to send data down the Telnet connection.
*/
static int telnet_send(void *handle, char *buf, int len)
* Called to send data down the Telnet connection.
*/
static int telnet_send(void *handle, char *buf, int len)
Backend telnet_backend = {
telnet_init,
Backend telnet_backend = {
telnet_init,
telnet_send,
telnet_sendbuffer,
telnet_size,
telnet_send,
telnet_sendbuffer,
telnet_size,
term_provide_logctx(inst->term, inst->logctx);
inst->back = &pty_backend;
term_provide_logctx(inst->term, inst->logctx);
inst->back = &pty_backend;
- inst->back->init((void *)inst->term, &inst->backhandle, NULL, 0, NULL, 0);
+ inst->back->init((void *)inst->term, &inst->backhandle, &cfg,
+ NULL, 0, NULL, 0);
inst->back->provide_logctx(inst->backhandle, inst->logctx);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
inst->back->provide_logctx(inst->backhandle, inst->logctx);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
-static char *pty_init(void *frontend, void **backend_handle,
+static char *pty_init(void *frontend, void **backend_handle, Config *cfg,
char *host, int port, char **realhost, int nodelay)
{
int slavefd;
char *host, int port, char **realhost, int nodelay)
{
int slavefd;
pty_frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */
pty_frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */
- pty_term_width = cfg.width;
- pty_term_height = cfg.height;
+ pty_term_width = cfg->width;
+ pty_term_height = cfg->height;
if (pty_master_fd < 0)
pty_open_master();
if (pty_master_fd < 0)
pty_open_master();
{
struct termios attrs;
tcgetattr(pty_master_fd, &attrs);
{
struct termios attrs;
tcgetattr(pty_master_fd, &attrs);
- attrs.c_cc[VERASE] = cfg.bksp_is_delete ? '\177' : '\010';
+ attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010';
tcsetattr(pty_master_fd, TCSANOW, &attrs);
}
tcsetattr(pty_master_fd, TCSANOW, &attrs);
}
* Stamp utmp (that is, tell the utmp helper process to do so),
* or not.
*/
* Stamp utmp (that is, tell the utmp helper process to do so),
* or not.
*/
close(pty_utmp_helper_pipe); /* just let the child process die */
else {
char *location = get_x_display(pty_frontend);
close(pty_utmp_helper_pipe); /* just let the child process die */
else {
char *location = get_x_display(pty_frontend);
for (i = 3; i < 1024; i++)
close(i);
{
for (i = 3; i < 1024; i++)
close(i);
{
- char term_env_var[10 + sizeof(cfg.termtype)];
- sprintf(term_env_var, "TERM=%s", cfg.termtype);
+ char term_env_var[10 + sizeof(cfg->termtype)];
+ sprintf(term_env_var, "TERM=%s", cfg->termtype);
putenv(term_env_var);
}
/*
putenv(term_env_var);
}
/*
else {
char *shell = getenv("SHELL");
char *shellname;
else {
char *shell = getenv("SHELL");
char *shellname;
+ if (cfg->login_shell) {
char *p = strrchr(shell, '/');
shellname = smalloc(2+strlen(shell));
p = p ? p+1 : shell;
char *p = strrchr(shell, '/');
shellname = smalloc(2+strlen(shell));
p = p ? p+1 : shell;
+ * Stub routine (we don't have any need to reconfigure this backend).
+ */
+static void pty_reconfig(void *handle, Config *cfg)
+{
+}
+
+/*
* Called to send data down the pty.
*/
static int pty_send(void *handle, char *buf, int len)
* Called to send data down the pty.
*/
static int pty_send(void *handle, char *buf, int len)
Backend pty_backend = {
pty_init,
Backend pty_backend = {
pty_init,
pty_send,
pty_sendbuffer,
pty_size,
pty_send,
pty_sendbuffer,
pty_size,
/* nodelay is only useful if stdin is a terminal device */
int nodelay = cfg.tcp_nodelay && isatty(0);
/* nodelay is only useful if stdin is a terminal device */
int nodelay = cfg.tcp_nodelay && isatty(0);
- error = back->init(NULL, &backhandle, cfg.host, cfg.port,
+ error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
&realhost, nodelay);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s\n", error);
&realhost, nodelay);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s\n", error);
char msg[1024], *title;
char *realhost;
char msg[1024], *title;
char *realhost;
- error = back->init((void *)term, &backhandle,
+ error = back->init((void *)term, &backhandle, &cfg,
cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
back->provide_logctx(backhandle, logctx);
if (error) {
cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
back->provide_logctx(backhandle, logctx);
if (error) {
/* Pass new config data to the terminal */
term_reconfig(term, &cfg);
/* Pass new config data to the terminal */
term_reconfig(term, &cfg);
+ /* Pass new config data to the back end */
+ back->reconfig(back, &cfg);
+
/* Screen size changed ? */
if (cfg.height != prev_cfg.height ||
cfg.width != prev_cfg.width ||
/* Screen size changed ? */
if (cfg.height != prev_cfg.height ||
cfg.width != prev_cfg.width ||