# Terminal emulator and its (platform-independent) dependencies.
TERMINAL = terminal wcwidth ldiscucs logging tree234 minibidi
- + config dialog
+ + config dialog conf
# GUI front end and terminal emulator (putty, puttytel).
GUITERM = TERMINAL window windlg winctrls sizetip winucs winprint
# Miscellaneous objects appearing in all the network utilities (not
# Pageant or PuTTYgen).
-MISC = timing misc version settings tree234 proxy
+MISC = timing misc version settings tree234 proxy conf
WINMISC = MISC winstore winnet winhandl cmdline windefs winmisc winproxy
+ wintime
UXMISC = MISC uxstore uxsel uxnet cmdline uxmisc uxproxy time
pageant : [G] winpgnt sshrsa sshpubk sshdes sshbn sshmd5 version tree234
+ misc sshaes sshsha winpgntc sshdss sshsh256 sshsh512 winutils
- + winmisc winhelp pageant.res LIBS
+ + winmisc winhelp conf pageant.res LIBS
puttygen : [G] winpgen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
+ sshrand winnoise sshsha winstore misc winctrls sshrsa sshdss winmisc
+ sshpubk sshaes sshsh256 sshsh512 import winutils puttygen.res
- + tree234 notiming winhelp winnojmp LIBS wintime
+ + tree234 notiming winhelp winnojmp conf LIBS wintime
pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
+ uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg
puttygen : [U] cmdgen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
+ sshrand uxnoise sshsha misc sshrsa sshdss uxcons uxstore uxmisc
+ sshpubk sshaes sshsh256 sshsh512 import puttygen.res time tree234
- + uxgen notiming
+ + uxgen notiming conf
pscp : [U] pscp uxsftp uxcons UXSSH BE_SSH SFTP wildcard UXMISC
psftp : [U] psftp uxsftp uxcons UXSSH BE_SSH SFTP wildcard UXMISC
if (need_save < 0) return x; \
} while (0)
-int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
+int cmdline_process_param(char *p, char *value, int need_save, Conf *conf)
{
int ret = 0;
RETURN(2);
/* This parameter must be processed immediately rather than being
* saved. */
- do_defaults(value, cfg);
+ do_defaults(value, conf);
loaded_session = TRUE;
cmdline_session_name = dupstr(value);
return 2;
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- default_protocol = cfg->protocol = PROT_SSH;
- default_port = cfg->port = 22;
+ default_protocol = PROT_SSH;
+ default_port = 22;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
return 1;
}
if (!strcmp(p, "-telnet")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- default_protocol = cfg->protocol = PROT_TELNET;
- default_port = cfg->port = 23;
+ default_protocol = PROT_TELNET;
+ default_port = 23;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
return 1;
}
if (!strcmp(p, "-rlogin")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- default_protocol = cfg->protocol = PROT_RLOGIN;
- default_port = cfg->port = 513;
+ default_protocol = PROT_RLOGIN;
+ default_port = 513;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
return 1;
}
if (!strcmp(p, "-raw")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- default_protocol = cfg->protocol = PROT_RAW;
+ default_protocol = PROT_RAW;
+ conf_set_int(conf, CONF_protocol, default_protocol);
}
if (!strcmp(p, "-serial")) {
RETURN(1);
/* Serial is not NONNETWORK in an odd sense of the word */
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- default_protocol = cfg->protocol = PROT_SERIAL;
- /* The host parameter will already be loaded into cfg->host, so copy it across */
- strncpy(cfg->serline, cfg->host, sizeof(cfg->serline) - 1);
- cfg->serline[sizeof(cfg->serline) - 1] = '\0';
+ default_protocol = PROT_SERIAL;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ /* The host parameter will already be loaded into CONF_host,
+ * so copy it across */
+ conf_set_str(conf, CONF_serline, conf_get_str(conf, CONF_host));
}
if (!strcmp(p, "-v")) {
RETURN(1);
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- strncpy(cfg->username, value, sizeof(cfg->username));
- cfg->username[sizeof(cfg->username) - 1] = '\0';
+ conf_set_str(conf, CONF_username, value);
}
if (!strcmp(p, "-loghost")) {
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- strncpy(cfg->loghost, value, sizeof(cfg->loghost));
- cfg->loghost[sizeof(cfg->loghost) - 1] = '\0';
+ conf_set_str(conf, CONF_loghost, value);
}
if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) {
- char *fwd, *ptr, *q, *qq;
- int dynamic, i=0;
+ char type, *q, *qq, *key, *val;
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- dynamic = !strcmp(p, "-D");
- fwd = value;
- ptr = cfg->portfwd;
- /* if existing forwards, find end of list */
- while (*ptr) {
- while (*ptr)
- ptr++;
- ptr++;
- }
- i = ptr - cfg->portfwd;
- ptr[0] = p[1]; /* insert a 'L', 'R' or 'D' at the start */
- ptr++;
- if (1 + strlen(fwd) + 2 > sizeof(cfg->portfwd) - i) {
- cmdline_error("out of space for port forwardings");
- return ret;
- }
- strncpy(ptr, fwd, sizeof(cfg->portfwd) - i - 2);
- if (!dynamic) {
+ if (strcmp(p, "-D")) {
/*
+ * For -L or -R forwarding types:
+ *
* We expect _at least_ two colons in this string. The
* possible formats are `sourceport:desthost:destport',
* or `sourceip:sourceport:desthost:destport' if you're
* replace the one between source and dest with a \t;
* this means we must find the second-to-last colon in
* the string.
+ *
+ * (This looks like a foolish way of doing it given the
+ * existence of strrchr, but it's more efficient than
+ * two strrchrs - not to mention that the second strrchr
+ * would require us to modify the input string!)
*/
- q = qq = strchr(ptr, ':');
+
+ type = p[1]; /* 'L' or 'R' */
+
+ q = qq = strchr(value, ':');
while (qq) {
char *qqq = strchr(qq+1, ':');
if (qqq)
q = qq;
qq = qqq;
}
- if (q) *q = '\t'; /* replace second-last colon with \t */
+
+ if (!q) {
+ cmdline_error("-%c expects at least two colons in its"
+ " argument", type);
+ return ret;
+ }
+
+ key = dupprintf("%c%.*s", type, q - value, value);
+ val = dupstr(q+1);
+ } else {
+ /*
+ * Dynamic port forwardings are entered under the same key
+ * as if they were local (because they occupy the same
+ * port space - a local and a dynamic forwarding on the
+ * same local port are mutually exclusive), with the
+ * special value "D" (which can be distinguished from
+ * anything in the ordinary -L case by containing no
+ * colon).
+ */
+ key = dupprintf("L%s", value);
+ val = dupstr("D");
}
- cfg->portfwd[sizeof(cfg->portfwd) - 1] = '\0';
- cfg->portfwd[sizeof(cfg->portfwd) - 2] = '\0';
- ptr[strlen(ptr)+1] = '\000'; /* append 2nd '\000' */
+ conf_set_str_str(conf, CONF_portfwd, key, val);
+ sfree(key);
+ sfree(val);
}
if ((!strcmp(p, "-nc"))) {
char *host, *portp;
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- host = portp = value;
- while (*portp && *portp != ':')
- portp++;
- if (*portp) {
- unsigned len = portp - host;
- if (len >= sizeof(cfg->ssh_nc_host))
- len = sizeof(cfg->ssh_nc_host) - 1;
- memcpy(cfg->ssh_nc_host, value, len);
- cfg->ssh_nc_host[len] = '\0';
- cfg->ssh_nc_port = atoi(portp+1);
- } else {
+ portp = strchr(value, ':');
+ if (!portp) {
cmdline_error("-nc expects argument of form 'host:port'");
return ret;
}
+
+ host = dupprintf("%.*s", portp - value, value);
+ conf_set_str(conf, CONF_ssh_nc_host, host);
+ conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1));
}
if (!strcmp(p, "-m")) {
char *filename, *command;
command = NULL;
fp = fopen(filename, "r");
if (!fp) {
- cmdline_error("unable to open command "
- "file \"%s\"", filename);
+ cmdline_error("unable to open command file \"%s\"", filename);
return ret;
}
do {
}
command[cmdlen++] = d;
} while (c != EOF);
- cfg->remote_cmd_ptr = command;
- cfg->remote_cmd_ptr2 = NULL;
- cfg->nopty = TRUE; /* command => no terminal */
fclose(fp);
+ conf_set_str(conf, CONF_remote_cmd, command);
+ conf_set_str(conf, CONF_remote_cmd2, "");
+ conf_set_int(conf, CONF_nopty, TRUE); /* command => no terminal */
+ sfree(command);
}
if (!strcmp(p, "-P")) {
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(1); /* lower priority than -ssh,-telnet */
- cfg->port = atoi(value);
+ conf_set_int(conf, CONF_port, atoi(value));
}
if (!strcmp(p, "-pw")) {
RETURN(2);
SAVEABLE(1);
/* We delay evaluating this until after the protocol is decided,
* so that we can warn if it's of no use with the selected protocol */
- if (cfg->protocol != PROT_SSH)
+ if (conf_get_int(conf, CONF_protocol) != PROT_SSH)
cmdline_error("the -pw option can only be used with the "
"SSH protocol");
else {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->tryagent = TRUE;
+ conf_set_int(conf, CONF_tryagent, TRUE);
}
if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") ||
!strcmp(p, "-nopageant")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->tryagent = FALSE;
+ conf_set_int(conf, CONF_tryagent, FALSE);
}
if (!strcmp(p, "-A")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->agentfwd = 1;
+ conf_set_int(conf, CONF_agentfwd, 1);
}
if (!strcmp(p, "-a")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->agentfwd = 0;
+ conf_set_int(conf, CONF_agentfwd, 0);
}
if (!strcmp(p, "-X")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->x11_forward = 1;
+ conf_set_int(conf, CONF_x11_forward, 1);
}
if (!strcmp(p, "-x")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->x11_forward = 0;
+ conf_set_int(conf, CONF_x11_forward, 0);
}
if (!strcmp(p, "-t")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(1); /* lower priority than -m */
- cfg->nopty = 0;
+ conf_set_int(conf, CONF_nopty, 0);
}
if (!strcmp(p, "-T")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(1);
- cfg->nopty = 1;
+ conf_set_int(conf, CONF_nopty, 1);
}
if (!strcmp(p, "-N")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->ssh_no_shell = 1;
+ conf_set_int(conf, CONF_ssh_no_shell, 1);
}
if (!strcmp(p, "-C")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->compression = 1;
+ conf_set_int(conf, CONF_compression, 1);
}
if (!strcmp(p, "-1")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->sshprot = 0; /* ssh protocol 1 only */
+ conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */
}
if (!strcmp(p, "-2")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->sshprot = 3; /* ssh protocol 2 only */
+ conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */
}
if (!strcmp(p, "-i")) {
+ Filename fn;
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0);
- cfg->keyfile = filename_from_str(value);
+ fn = filename_from_str(value);
+ conf_set_filename(conf, CONF_keyfile, &fn);
}
if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) {
RETURN(1);
SAVEABLE(1);
- cfg->addressfamily = ADDRTYPE_IPV4;
+ conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4);
}
if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) {
RETURN(1);
SAVEABLE(1);
- cfg->addressfamily = ADDRTYPE_IPV6;
+ conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6);
}
if (!strcmp(p, "-sercfg")) {
char* nextitem;
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(1);
- if (cfg->protocol != PROT_SERIAL)
+ if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL)
cmdline_error("the -sercfg option can only be used with the "
"serial protocol");
/* Value[0] contains one or more , separated values, like 19200,8,n,1,X */
if (length == 1) {
switch (*nextitem) {
case '1':
- cfg->serstopbits = 2;
- break;
case '2':
- cfg->serstopbits = 4;
+ conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0'));
break;
case '5':
- cfg->serdatabits = 5;
- break;
- case '6':
- cfg->serdatabits = 6;
- break;
- case '7':
- cfg->serdatabits = 7;
- break;
- case '8':
- cfg->serdatabits = 8;
- break;
- case '9':
- cfg->serdatabits = 9;
+ conf_set_int(conf, CONF_serdatabits, *nextitem-'0');
break;
case 'n':
- cfg->serparity = SER_PAR_NONE;
+ conf_set_int(conf, CONF_serparity, SER_PAR_NONE);
break;
case 'o':
- cfg->serparity = SER_PAR_ODD;
+ conf_set_int(conf, CONF_serparity, SER_PAR_ODD);
break;
case 'e':
- cfg->serparity = SER_PAR_EVEN;
+ conf_set_int(conf, CONF_serparity, SER_PAR_EVEN);
break;
case 'm':
- cfg->serparity = SER_PAR_MARK;
+ conf_set_int(conf, CONF_serparity, SER_PAR_MARK);
break;
case 's':
- cfg->serparity = SER_PAR_SPACE;
+ conf_set_int(conf, CONF_serparity, SER_PAR_SPACE);
break;
case 'N':
- cfg->serflow = SER_FLOW_NONE;
+ conf_set_int(conf, CONF_serflow, SER_FLOW_NONE);
break;
case 'X':
- cfg->serflow = SER_FLOW_XONXOFF;
+ conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF);
break;
case 'R':
- cfg->serflow = SER_FLOW_RTSCTS;
+ conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS);
break;
case 'D':
- cfg->serflow = SER_FLOW_DSRDTR;
+ conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR);
break;
default:
}
} else if (length == 3 && !strncmp(nextitem,"1.5",3)) {
/* Messy special case */
- cfg->serstopbits = 3;
+ conf_set_int(conf, CONF_serstopbits, 3);
} else {
int serspeed = atoi(nextitem);
if (serspeed != 0) {
- cfg->serspeed = serspeed;
+ conf_set_int(conf, CONF_serspeed, serspeed);
} else {
cmdline_error("Unrecognised suboption \"-sercfg %s\"",
nextitem);
return ret; /* unrecognised */
}
-void cmdline_run_saved(Config *cfg)
+void cmdline_run_saved(Conf *conf)
{
int pri, i;
for (pri = 0; pri < NPRIORITIES; pri++)
for (i = 0; i < saves[pri].nsaved; i++)
cmdline_process_param(saves[pri].params[i].p,
- saves[pri].params[i].value, 0, cfg);
+ saves[pri].params[i].value, 0, conf);
}
--- /dev/null
+/*
+ * conf.c: implementation of the internal storage format used for
+ * the configuration of a PuTTY session.
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <assert.h>
+
+#include "tree234.h"
+#include "putty.h"
+
+/*
+ * Enumeration of types used in keys and values.
+ */
+typedef enum { TYPE_NONE, TYPE_INT, TYPE_STR, TYPE_FILENAME, TYPE_FONT } Type;
+
+/*
+ * Arrays which allow us to look up the subkey and value types for a
+ * given primary key id.
+ */
+#define CONF_SUBKEYTYPE_DEF(valtype, keytype, keyword) TYPE_ ## keytype,
+static int subkeytypes[] = { CONFIG_OPTIONS(CONF_SUBKEYTYPE_DEF) };
+#define CONF_VALUETYPE_DEF(valtype, keytype, keyword) TYPE_ ## valtype,
+static int valuetypes[] = { CONFIG_OPTIONS(CONF_VALUETYPE_DEF) };
+
+/*
+ * Configuration keys are primarily integers (big enum of all the
+ * different configurable options); some keys have string-designated
+ * subkeys, such as the list of environment variables (subkeys
+ * defined by the variable names); some have integer-designated
+ * subkeys (wordness, colours, preference lists).
+ */
+struct key {
+ int primary;
+ union {
+ int i;
+ char *s;
+ } secondary;
+};
+
+struct value {
+ union {
+ int intval;
+ char *stringval;
+ Filename fileval;
+ FontSpec fontval;
+ } u;
+};
+
+struct conf_entry {
+ struct key key;
+ struct value value;
+};
+
+struct conf_tag {
+ tree234 *tree;
+};
+
+/*
+ * Because 'struct key' is the first element in 'struct conf_entry',
+ * it's safe (guaranteed by the C standard) to cast arbitrarily back
+ * and forth between the two types. Therefore, we only need one
+ * comparison function, which can double as a main sort function for
+ * the tree (comparing two conf_entry structures with each other)
+ * and a search function (looking up an externally supplied key).
+ */
+static int conf_cmp(void *av, void *bv)
+{
+ struct key *a = (struct key *)av;
+ struct key *b = (struct key *)bv;
+
+ if (a->primary < b->primary)
+ return -1;
+ else if (a->primary > b->primary)
+ return +1;
+ switch (subkeytypes[a->primary]) {
+ case TYPE_INT:
+ if (a->secondary.i < b->secondary.i)
+ return -1;
+ else if (a->secondary.i > b->secondary.i)
+ return +1;
+ return 0;
+ case TYPE_STR:
+ return strcmp(a->secondary.s, b->secondary.s);
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Free any dynamic data items pointed to by a 'struct key'. We
+ * don't free the structure itself, since it's probably part of a
+ * larger allocated block.
+ */
+static void free_key(struct key *key)
+{
+ if (subkeytypes[key->primary] == TYPE_STR)
+ sfree(key->secondary.s);
+}
+
+/*
+ * Copy a 'struct key' into another one, copying its dynamic data
+ * if necessary.
+ */
+static void copy_key(struct key *to, struct key *from)
+{
+ to->primary = from->primary;
+ switch (subkeytypes[to->primary]) {
+ case TYPE_INT:
+ to->secondary.i = from->secondary.i;
+ break;
+ case TYPE_STR:
+ to->secondary.s = dupstr(from->secondary.s);
+ break;
+ }
+}
+
+/*
+ * Free any dynamic data items pointed to by a 'struct value'. We
+ * don't free the value itself, since it's probably part of a larger
+ * allocated block.
+ */
+static void free_value(struct value *val, int type)
+{
+ if (type == TYPE_STR)
+ sfree(val->u.stringval);
+}
+
+/*
+ * Copy a 'struct value' into another one, copying its dynamic data
+ * if necessary.
+ */
+static void copy_value(struct value *to, struct value *from, int type)
+{
+ switch (type) {
+ case TYPE_INT:
+ to->u.intval = from->u.intval;
+ break;
+ case TYPE_STR:
+ to->u.stringval = dupstr(from->u.stringval);
+ break;
+ case TYPE_FILENAME:
+ to->u.fileval = from->u.fileval;
+ break;
+ case TYPE_FONT:
+ to->u.fontval = from->u.fontval;
+ break;
+ }
+}
+
+/*
+ * Free an entire 'struct conf_entry' and its dynamic data.
+ */
+static void free_entry(struct conf_entry *entry)
+{
+ free_key(&entry->key);
+ free_value(&entry->value, valuetypes[entry->key.primary]);
+ sfree(entry);
+}
+
+Conf *conf_new(void)
+{
+ Conf *conf = snew(struct conf_tag);
+
+ conf->tree = newtree234(conf_cmp);
+
+ return conf;
+}
+
+static void conf_clear(Conf *conf)
+{
+ struct conf_entry *entry;
+
+ while ((entry = delpos234(conf->tree, 0)) != NULL)
+ free_entry(entry);
+}
+
+void conf_free(Conf *conf)
+{
+ conf_clear(conf);
+ freetree234(conf->tree);
+ sfree(conf);
+}
+
+static void conf_insert(Conf *conf, struct conf_entry *entry)
+{
+ struct conf_entry *oldentry = add234(conf->tree, entry);
+ if (oldentry && oldentry != entry) {
+ del234(conf->tree, oldentry);
+ free_entry(oldentry);
+ oldentry = add234(conf->tree, entry);
+ assert(oldentry == entry);
+ }
+}
+
+void conf_copy_into(Conf *newconf, Conf *oldconf)
+{
+ struct conf_entry *entry, *entry2;
+ int i;
+
+ for (i = 0; (entry = index234(oldconf->tree, i)) != NULL; i++) {
+ entry2 = snew(struct conf_entry);
+ copy_key(&entry2->key, &entry->key);
+ copy_value(&entry2->value, &entry->value,
+ valuetypes[entry->key.primary]);
+ add234(newconf->tree, entry2);
+ }
+}
+
+Conf *conf_copy(Conf *oldconf)
+{
+ Conf *newconf = conf_new();
+
+ conf_copy_into(newconf, oldconf);
+
+ return newconf;
+}
+
+int conf_get_int(Conf *conf, int primary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_INT);
+ key.primary = primary;
+ entry = find234(conf->tree, &key, NULL);
+ assert(entry);
+ return entry->value.u.intval;
+}
+
+int conf_get_int_int(Conf *conf, int primary, int secondary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_INT);
+ assert(valuetypes[primary] == TYPE_INT);
+ key.primary = primary;
+ key.secondary.i = secondary;
+ entry = find234(conf->tree, &key, NULL);
+ assert(entry);
+ return entry->value.u.intval;
+}
+
+char *conf_get_str(Conf *conf, int primary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_STR);
+ key.primary = primary;
+ entry = find234(conf->tree, &key, NULL);
+ assert(entry);
+ return entry->value.u.stringval;
+}
+
+char *conf_get_str_str_opt(Conf *conf, int primary, const char *secondary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_STR);
+ assert(valuetypes[primary] == TYPE_STR);
+ key.primary = primary;
+ key.secondary.s = (char *)secondary;
+ entry = find234(conf->tree, &key, NULL);
+ return entry ? entry->value.u.stringval : NULL;
+}
+
+char *conf_get_str_str(Conf *conf, int primary, const char *secondary)
+{
+ char *ret = conf_get_str_str_opt(conf, primary, secondary);
+ assert(ret);
+ return ret;
+}
+
+char *conf_get_str_strs(Conf *conf, int primary,
+ char *subkeyin, char **subkeyout)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_STR);
+ assert(valuetypes[primary] == TYPE_STR);
+ key.primary = primary;
+ if (subkeyin) {
+ key.secondary.s = subkeyin;
+ entry = findrel234(conf->tree, &key, NULL, REL234_GT);
+ } else {
+ key.secondary.s = "";
+ entry = findrel234(conf->tree, &key, NULL, REL234_GE);
+ }
+ if (!entry || entry->key.primary != primary)
+ return NULL;
+ *subkeyout = entry->key.secondary.s;
+ return entry->value.u.stringval;
+}
+
+char *conf_get_str_nthstrkey(Conf *conf, int primary, int n)
+{
+ struct key key;
+ struct conf_entry *entry;
+ int index;
+
+ assert(subkeytypes[primary] == TYPE_STR);
+ assert(valuetypes[primary] == TYPE_STR);
+ key.primary = primary;
+ key.secondary.s = "";
+ entry = findrelpos234(conf->tree, &key, NULL, REL234_GE, &index);
+ if (!entry || entry->key.primary != primary)
+ return NULL;
+ entry = index234(conf->tree, index + n);
+ if (!entry || entry->key.primary != primary)
+ return NULL;
+ return entry->key.secondary.s;
+}
+
+Filename *conf_get_filename(Conf *conf, int primary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_FILENAME);
+ key.primary = primary;
+ entry = find234(conf->tree, &key, NULL);
+ assert(entry);
+ return &entry->value.u.fileval;
+}
+
+FontSpec *conf_get_fontspec(Conf *conf, int primary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_FONT);
+ key.primary = primary;
+ entry = find234(conf->tree, &key, NULL);
+ assert(entry);
+ return &entry->value.u.fontval;
+}
+
+void conf_set_int(Conf *conf, int primary, int value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_INT);
+ entry->key.primary = primary;
+ entry->value.u.intval = value;
+ conf_insert(conf, entry);
+}
+
+void conf_set_int_int(Conf *conf, int primary, int secondary, int value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_INT);
+ assert(valuetypes[primary] == TYPE_INT);
+ entry->key.primary = primary;
+ entry->key.secondary.i = secondary;
+ entry->value.u.intval = value;
+ conf_insert(conf, entry);
+}
+
+void conf_set_str(Conf *conf, int primary, const char *value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_STR);
+ entry->key.primary = primary;
+ entry->value.u.stringval = dupstr(value);
+ conf_insert(conf, entry);
+}
+
+void conf_set_str_str(Conf *conf, int primary, const char *secondary,
+ const char *value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_STR);
+ assert(valuetypes[primary] == TYPE_STR);
+ entry->key.primary = primary;
+ entry->key.secondary.s = dupstr(secondary);
+ entry->value.u.stringval = dupstr(value);
+ conf_insert(conf, entry);
+}
+
+void conf_del_str_str(Conf *conf, int primary, const char *secondary)
+{
+ struct key key;
+ struct conf_entry *entry;
+
+ assert(subkeytypes[primary] == TYPE_STR);
+ assert(valuetypes[primary] == TYPE_STR);
+ key.primary = primary;
+ key.secondary.s = (char *)secondary;
+ entry = find234(conf->tree, &key, NULL);
+ if (entry) {
+ del234(conf->tree, entry);
+ free_entry(entry);
+ }
+ }
+
+void conf_set_filename(Conf *conf, int primary, const Filename *value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_FILENAME);
+ entry->key.primary = primary;
+ entry->value.u.fileval = *value; /* structure copy */
+ conf_insert(conf, entry);
+}
+
+void conf_set_fontspec(Conf *conf, int primary, const FontSpec *value)
+{
+ struct conf_entry *entry = snew(struct conf_entry);
+
+ assert(subkeytypes[primary] == TYPE_NONE);
+ assert(valuetypes[primary] == TYPE_FONT);
+ entry->key.primary = primary;
+ entry->value.u.fontval = *value; /* structure copy */
+ conf_insert(conf, entry);
+}
+
+int conf_serialised_size(Conf *conf)
+{
+ int i;
+ struct conf_entry *entry;
+ int size = 0;
+
+ for (i = 0; (entry = index234(conf->tree, i)) != NULL; i++) {
+ size += 4; /* primary key */
+ switch (subkeytypes[entry->key.primary]) {
+ case TYPE_INT:
+ size += 4;
+ break;
+ case TYPE_STR:
+ size += 1 + strlen(entry->key.secondary.s);
+ break;
+ }
+ switch (valuetypes[entry->key.primary]) {
+ case TYPE_INT:
+ size += 4;
+ break;
+ case TYPE_STR:
+ size += 1 + strlen(entry->value.u.stringval);
+ break;
+ case TYPE_FILENAME:
+ size += sizeof(entry->value.u.fileval);
+ break;
+ case TYPE_FONT:
+ size += sizeof(entry->value.u.fontval);
+ break;
+ }
+ }
+
+ size += 4; /* terminator value */
+
+ return size;
+}
+
+void conf_serialise(Conf *conf, void *vdata)
+{
+ unsigned char *data = (unsigned char *)vdata;
+ int i, len;
+ struct conf_entry *entry;
+
+ for (i = 0; (entry = index234(conf->tree, i)) != NULL; i++) {
+ PUT_32BIT_MSB_FIRST(data, entry->key.primary);
+ data += 4;
+
+ switch (subkeytypes[entry->key.primary]) {
+ case TYPE_INT:
+ PUT_32BIT_MSB_FIRST(data, entry->key.secondary.i);
+ data += 4;
+ break;
+ case TYPE_STR:
+ len = strlen(entry->key.secondary.s);
+ memcpy(data, entry->key.secondary.s, len);
+ data += len;
+ *data++ = 0;
+ break;
+ }
+ switch (valuetypes[entry->key.primary]) {
+ case TYPE_INT:
+ PUT_32BIT_MSB_FIRST(data, entry->value.u.intval);
+ data += 4;
+ break;
+ case TYPE_STR:
+ len = strlen(entry->value.u.stringval);
+ memcpy(data, entry->value.u.stringval, len);
+ data += len;
+ *data++ = 0;
+ break;
+ case TYPE_FILENAME:
+ memcpy(data, &entry->value.u.fileval,
+ sizeof(entry->value.u.fileval));
+ data += sizeof(entry->value.u.fileval);
+ break;
+ case TYPE_FONT:
+ memcpy(data, &entry->value.u.fontval,
+ sizeof(entry->value.u.fontval));
+ data += sizeof(entry->value.u.fontval);
+ break;
+ }
+ }
+
+ PUT_32BIT_MSB_FIRST(data, 0xFFFFFFFFU);
+}
+
+int conf_deserialise(Conf *conf, void *vdata, int maxsize)
+{
+ unsigned char *data = (unsigned char *)vdata;
+ unsigned char *start = data;
+ struct conf_entry *entry;
+ int primary;
+ unsigned char *zero;
+
+ while (maxsize >= 4) {
+ primary = GET_32BIT_MSB_FIRST(data);
+ data += 4, maxsize -= 4;
+
+ if ((unsigned)primary >= N_CONFIG_OPTIONS)
+ break;
+
+ entry = snew(struct conf_entry);
+ entry->key.primary = primary;
+
+ switch (subkeytypes[entry->key.primary]) {
+ case TYPE_INT:
+ if (maxsize < 4) {
+ sfree(entry);
+ goto done;
+ }
+ entry->key.secondary.i = GET_32BIT_MSB_FIRST(data);
+ data += 4, maxsize -= 4;
+ break;
+ case TYPE_STR:
+ zero = memchr(data, 0, maxsize);
+ if (!zero) {
+ sfree(entry);
+ goto done;
+ }
+ entry->key.secondary.s = dupstr((char *)data);
+ maxsize -= (zero + 1 - data);
+ data = zero + 1;
+ break;
+ }
+
+ switch (valuetypes[entry->key.primary]) {
+ case TYPE_INT:
+ if (maxsize < 4) {
+ if (subkeytypes[entry->key.primary] == TYPE_STR)
+ sfree(entry->key.secondary.s);
+ sfree(entry);
+ goto done;
+ }
+ entry->value.u.intval = GET_32BIT_MSB_FIRST(data);
+ data += 4, maxsize -= 4;
+ break;
+ case TYPE_STR:
+ zero = memchr(data, 0, maxsize);
+ if (!zero) {
+ if (subkeytypes[entry->key.primary] == TYPE_STR)
+ sfree(entry->key.secondary.s);
+ sfree(entry);
+ goto done;
+ }
+ entry->value.u.stringval = dupstr((char *)data);
+ maxsize -= (zero + 1 - data);
+ data = zero + 1;
+ break;
+ case TYPE_FILENAME:
+ if (maxsize < sizeof(entry->value.u.fileval)) {
+ if (subkeytypes[entry->key.primary] == TYPE_STR)
+ sfree(entry->key.secondary.s);
+ sfree(entry);
+ goto done;
+ }
+ memcpy(&entry->value.u.fileval, data,
+ sizeof(entry->value.u.fileval));
+ data += sizeof(entry->value.u.fileval);
+ maxsize -= sizeof(entry->value.u.fileval);
+ break;
+ case TYPE_FONT:
+ if (maxsize < sizeof(entry->value.u.fontval)) {
+ if (subkeytypes[entry->key.primary] == TYPE_STR)
+ sfree(entry->key.secondary.s);
+ sfree(entry);
+ goto done;
+ }
+ memcpy(&entry->value.u.fontval, data,
+ sizeof(entry->value.u.fontval));
+ data += sizeof(entry->value.u.fontval);
+ maxsize -= sizeof(entry->value.u.fontval);
+ break;
+ }
+ conf_insert(conf, entry);
+ }
+
+ done:
+ return (int)(data - start);
+}
#define HOST_BOX_TITLE "Host Name (or IP address)"
#define PORT_BOX_TITLE "Port"
+void conf_radiobutton_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ int button;
+ Conf *conf = (Conf *)data;
+
+ /*
+ * For a standard radio button set, the context parameter gives
+ * the primary key (CONF_foo), and the extra data per button
+ * gives the value the target field should take if that button
+ * is the one selected.
+ */
+ if (event == EVENT_REFRESH) {
+ int val = conf_get_int(conf, ctrl->radio.context.i);
+ for (button = 0; button < ctrl->radio.nbuttons; button++)
+ if (val == ctrl->radio.buttondata[button].i)
+ break;
+ /* We expected that `break' to happen, in all circumstances. */
+ assert(button < ctrl->radio.nbuttons);
+ dlg_radiobutton_set(ctrl, dlg, button);
+ } else if (event == EVENT_VALCHANGE) {
+ button = dlg_radiobutton_get(ctrl, dlg);
+ assert(button >= 0 && button < ctrl->radio.nbuttons);
+ conf_set_int(conf, ctrl->radio.context.i,
+ ctrl->radio.buttondata[button].i);
+ }
+}
+
+#define CHECKBOX_INVERT (1<<30)
+void conf_checkbox_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ int key, invert;
+ Conf *conf = (Conf *)data;
+
+ /*
+ * For a standard checkbox, the context parameter gives the
+ * primary key (CONF_foo), optionally ORed with CHECKBOX_INVERT.
+ */
+ key = ctrl->checkbox.context.i;
+ if (key & CHECKBOX_INVERT) {
+ key &= ~CHECKBOX_INVERT;
+ invert = 1;
+ } else
+ invert = 0;
+
+ /*
+ * C lacks a logical XOR, so the following code uses the idiom
+ * (!a ^ !b) to obtain the logical XOR of a and b. (That is, 1
+ * iff exactly one of a and b is nonzero, otherwise 0.)
+ */
+
+ if (event == EVENT_REFRESH) {
+ int val = conf_get_int(conf, key);
+ dlg_checkbox_set(ctrl, dlg, (!val ^ !invert));
+ } else if (event == EVENT_VALCHANGE) {
+ conf_set_int(conf, key, !dlg_checkbox_get(ctrl,dlg) ^ !invert);
+ }
+}
+
+void conf_editbox_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ /*
+ * The standard edit-box handler expects the main `context'
+ * field to contain the primary key. The secondary `context2'
+ * field indicates the type of this field:
+ *
+ * - if context2 > 0, the field is a string.
+ * - if context2 == -1, the field is an int and the edit box
+ * is numeric.
+ * - if context2 < -1, the field is an int and the edit box is
+ * _floating_, and (-context2) gives the scale. (E.g. if
+ * context2 == -1000, then typing 1.2 into the box will set
+ * the field to 1200.)
+ */
+ int key = ctrl->editbox.context.i;
+ int length = ctrl->editbox.context2.i;
+ Conf *conf = (Conf *)data;
+
+ if (length > 0) {
+ if (event == EVENT_REFRESH) {
+ char *field = conf_get_str(conf, key);
+ dlg_editbox_set(ctrl, dlg, field);
+ } else if (event == EVENT_VALCHANGE) {
+ char *field = dlg_editbox_get(ctrl, dlg);
+ conf_set_str(conf, key, field);
+ sfree(field);
+ }
+ } else if (length < 0) {
+ if (event == EVENT_REFRESH) {
+ char str[80];
+ int value = conf_get_int(conf, key);
+ if (length == -1)
+ sprintf(str, "%d", value);
+ else
+ sprintf(str, "%g", (double)value / (double)(-length));
+ dlg_editbox_set(ctrl, dlg, str);
+ } else if (event == EVENT_VALCHANGE) {
+ char *str = dlg_editbox_get(ctrl, dlg);
+ if (length == -1)
+ conf_set_int(conf, key, atoi(str));
+ else
+ conf_set_int(conf, key, (int)((-length) * atof(str)));
+ sfree(str);
+ }
+ }
+}
+
+void conf_filesel_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ int key = ctrl->fileselect.context.i;
+ Conf *conf = (Conf *)data;
+
+ if (event == EVENT_REFRESH) {
+ dlg_filesel_set(ctrl, dlg, *conf_get_filename(conf, key));
+ } else if (event == EVENT_VALCHANGE) {
+ Filename filename;
+ dlg_filesel_get(ctrl, dlg, &filename);
+ conf_set_filename(conf, key, &filename);
+ /* If Filenames ever become dynamic, free this one. */
+ }
+}
+
+void conf_fontsel_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ int key = ctrl->fontselect.context.i;
+ Conf *conf = (Conf *)data;
+
+ if (event == EVENT_REFRESH) {
+ dlg_fontsel_set(ctrl, dlg, *conf_get_fontspec(conf, key));
+ } else if (event == EVENT_VALCHANGE) {
+ FontSpec fontspec;
+ dlg_fontsel_get(ctrl, dlg, &fontspec);
+ conf_set_fontspec(conf, key, &fontspec);
+ /* If FontSpecs ever become dynamic, free this one. */
+ }
+}
+
static void config_host_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
/*
* This function works just like the standard edit box handler,
* different places depending on the protocol.
*/
if (event == EVENT_REFRESH) {
- if (cfg->protocol == PROT_SERIAL) {
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL) {
/*
* This label text is carefully chosen to contain an n,
* since that's the shortcut for the host name control.
*/
dlg_label_change(ctrl, dlg, "Serial line");
- dlg_editbox_set(ctrl, dlg, cfg->serline);
+ dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_serline));
} else {
dlg_label_change(ctrl, dlg, HOST_BOX_TITLE);
- dlg_editbox_set(ctrl, dlg, cfg->host);
+ dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_host));
}
} else if (event == EVENT_VALCHANGE) {
- if (cfg->protocol == PROT_SERIAL)
- dlg_editbox_get(ctrl, dlg, cfg->serline, lenof(cfg->serline));
+ char *s = dlg_editbox_get(ctrl, dlg);
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
+ conf_set_str(conf, CONF_serline, s);
else
- dlg_editbox_get(ctrl, dlg, cfg->host, lenof(cfg->host));
+ conf_set_str(conf, CONF_host, s);
+ sfree(s);
}
}
static void config_port_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
char buf[80];
/*
* different places depending on the protocol.
*/
if (event == EVENT_REFRESH) {
- if (cfg->protocol == PROT_SERIAL) {
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL) {
/*
* This label text is carefully chosen to contain a p,
* since that's the shortcut for the port control.
*/
dlg_label_change(ctrl, dlg, "Speed");
- sprintf(buf, "%d", cfg->serspeed);
+ sprintf(buf, "%d", conf_get_int(conf, CONF_serspeed));
} else {
dlg_label_change(ctrl, dlg, PORT_BOX_TITLE);
- if (cfg->port != 0)
- sprintf(buf, "%d", cfg->port);
+ if (conf_get_int(conf, CONF_port) != 0)
+ sprintf(buf, "%d", conf_get_int(conf, CONF_port));
else
/* Display an (invalid) port of 0 as blank */
buf[0] = '\0';
}
dlg_editbox_set(ctrl, dlg, buf);
} else if (event == EVENT_VALCHANGE) {
- dlg_editbox_get(ctrl, dlg, buf, lenof(buf));
- if (cfg->protocol == PROT_SERIAL)
- cfg->serspeed = atoi(buf);
+ char *s = dlg_editbox_get(ctrl, dlg);
+ int i = atoi(s);
+ sfree(s);
+
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
+ conf_set_int(conf, CONF_serspeed, i);
else
- cfg->port = atoi(buf);
+ conf_set_int(conf, CONF_port, i);
}
}
void *data, int event)
{
int button;
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct hostport *hp = (struct hostport *)ctrl->radio.context.p;
/*
* structure giving the `union control's for both.
*/
if (event == EVENT_REFRESH) {
+ int protocol = conf_get_int(conf, CONF_protocol);
for (button = 0; button < ctrl->radio.nbuttons; button++)
- if (cfg->protocol == ctrl->radio.buttondata[button].i)
+ if (protocol == ctrl->radio.buttondata[button].i)
break;
/* We expected that `break' to happen, in all circumstances. */
assert(button < ctrl->radio.nbuttons);
dlg_radiobutton_set(ctrl, dlg, button);
} else if (event == EVENT_VALCHANGE) {
- int oldproto = cfg->protocol;
+ int oldproto = conf_get_int(conf, CONF_protocol);
+ int newproto, port;
+
button = dlg_radiobutton_get(ctrl, dlg);
assert(button >= 0 && button < ctrl->radio.nbuttons);
- cfg->protocol = ctrl->radio.buttondata[button].i;
- if (oldproto != cfg->protocol) {
+ newproto = ctrl->radio.buttondata[button].i;
+ conf_set_int(conf, CONF_protocol, newproto);
+
+ if (oldproto != newproto) {
Backend *ob = backend_from_proto(oldproto);
- Backend *nb = backend_from_proto(cfg->protocol);
+ Backend *nb = backend_from_proto(newproto);
assert(ob);
assert(nb);
/* Iff the user hasn't changed the port from the old protocol's
* controls in order and setting a non-default port before
* getting to the protocol; we want that non-default port
* to be preserved. */
- if (cfg->port == ob->default_port)
- cfg->port = nb->default_port;
+ port = conf_get_int(conf, CONF_port);
+ if (port == ob->default_port)
+ conf_set_int(conf, CONF_port, nb->default_port);
}
dlg_refresh(hp->host, dlg);
dlg_refresh(hp->port, dlg);
void *data, int event)
{
int button;
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
/* This function works just like the standard radio-button handler,
* but it has to fall back to "no logging" in situations where the
* configured logging type isn't applicable.
*/
if (event == EVENT_REFRESH) {
+ int logtype = conf_get_int(conf, CONF_logtype);
+
for (button = 0; button < ctrl->radio.nbuttons; button++)
- if (cfg->logtype == ctrl->radio.buttondata[button].i)
+ if (logtype == ctrl->radio.buttondata[button].i)
break;
-
- /* We fell off the end, so we lack the configured logging type */
- if (button == ctrl->radio.nbuttons) {
- button=0;
- cfg->logtype=LGTYP_NONE;
- }
- dlg_radiobutton_set(ctrl, dlg, button);
+
+ /* We fell off the end, so we lack the configured logging type */
+ if (button == ctrl->radio.nbuttons) {
+ button = 0;
+ conf_set_int(conf, CONF_logtype, LGTYP_NONE);
+ }
+ dlg_radiobutton_set(ctrl, dlg, button);
} else if (event == EVENT_VALCHANGE) {
button = dlg_radiobutton_get(ctrl, dlg);
assert(button >= 0 && button < ctrl->radio.nbuttons);
- cfg->logtype = ctrl->radio.buttondata[button].i;
+ conf_set_int(conf, CONF_logtype, ctrl->radio.buttondata[button].i);
}
}
void *data, int event)
{
int button;
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
/*
* This function works much like the standard radio button
- * handler, but it has to handle two fields in Config.
+ * handler, but it has to handle two fields in Conf.
*/
if (event == EVENT_REFRESH) {
- if (cfg->nethack_keypad)
+ if (conf_get_int(conf, CONF_nethack_keypad))
button = 2;
- else if (cfg->app_keypad)
+ else if (conf_get_int(conf, CONF_app_keypad))
button = 1;
else
button = 0;
button = dlg_radiobutton_get(ctrl, dlg);
assert(button >= 0 && button < ctrl->radio.nbuttons);
if (button == 2) {
- cfg->app_keypad = FALSE;
- cfg->nethack_keypad = TRUE;
+ conf_set_int(conf, CONF_app_keypad, FALSE);
+ conf_set_int(conf, CONF_nethack_keypad, TRUE);
} else {
- cfg->app_keypad = (button != 0);
- cfg->nethack_keypad = FALSE;
+ conf_set_int(conf, CONF_app_keypad, (button != 0));
+ conf_set_int(conf, CONF_nethack_keypad, FALSE);
}
}
}
static void cipherlist_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
int i;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < CIPHER_MAX; i++) {
- int c = cfg->ssh_cipherlist[i];
+ int c = conf_get_int_int(conf, CONF_ssh_cipherlist, i);
int j;
char *cstr = NULL;
for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
/* Update array to match the list box. */
for (i=0; i < CIPHER_MAX; i++)
- cfg->ssh_cipherlist[i] = dlg_listbox_getid(ctrl, dlg, i);
-
+ conf_set_int_int(conf, CONF_ssh_cipherlist, i,
+ dlg_listbox_getid(ctrl, dlg, i));
}
}
static void gsslist_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
int i;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < ngsslibs; i++) {
- int id = cfg->ssh_gsslist[i];
+ int id = conf_get_int_int(conf, CONF_ssh_gsslist, i);
assert(id >= 0 && id < ngsslibs);
dlg_listbox_addwithid(ctrl, dlg, gsslibnames[id], id);
}
/* Update array to match the list box. */
for (i=0; i < ngsslibs; i++)
- cfg->ssh_gsslist[i] = dlg_listbox_getid(ctrl, dlg, i);
+ conf_set_int_int(conf, CONF_ssh_gsslist, i,
+ dlg_listbox_getid(ctrl, dlg, i));
}
}
#endif
static void kexlist_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
int i;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < KEX_MAX; i++) {
- int k = cfg->ssh_kexlist[i];
+ int k = conf_get_int_int(conf, CONF_ssh_kexlist, i);
int j;
char *kstr = NULL;
for (j = 0; j < (sizeof kexes) / (sizeof kexes[0]); j++) {
/* Update array to match the list box. */
for (i=0; i < KEX_MAX; i++)
- cfg->ssh_kexlist[i] = dlg_listbox_getid(ctrl, dlg, i);
-
+ conf_set_int_int(conf, CONF_ssh_kexlist, i,
+ dlg_listbox_getid(ctrl, dlg, i));
}
}
static void printerbox_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
int nprinters, i;
printer_enum *pe;
+ char *printer;
dlg_update_start(ctrl, dlg);
/*
dlg_listbox_add(ctrl, dlg, printer_get_name(pe, i));
printer_finish_enum(pe);
}
- dlg_editbox_set(ctrl, dlg,
- (*cfg->printer ? cfg->printer :
- PRINTER_DISABLED_STRING));
+ printer = conf_get_str(conf, CONF_printer);
+ if (!printer)
+ printer = PRINTER_DISABLED_STRING;
+ dlg_editbox_set(ctrl, dlg, printer);
dlg_update_done(ctrl, dlg);
} else if (event == EVENT_VALCHANGE) {
- dlg_editbox_get(ctrl, dlg, cfg->printer, sizeof(cfg->printer));
- if (!strcmp(cfg->printer, PRINTER_DISABLED_STRING))
- *cfg->printer = '\0';
+ char *printer = dlg_editbox_get(ctrl, dlg);
+ if (!strcmp(printer, PRINTER_DISABLED_STRING))
+ printer[0] = '\0';
+ conf_set_str(conf, CONF_printer, printer);
+ sfree(printer);
}
}
static void codepage_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
int i;
const char *cp, *thiscp;
dlg_update_start(ctrl, dlg);
- thiscp = cp_name(decode_codepage(cfg->line_codepage));
+ thiscp = cp_name(decode_codepage(conf_get_str(conf,
+ CONF_line_codepage)));
dlg_listbox_clear(ctrl, dlg);
for (i = 0; (cp = cp_enumerate(i)) != NULL; i++)
dlg_listbox_add(ctrl, dlg, cp);
dlg_editbox_set(ctrl, dlg, thiscp);
- strcpy(cfg->line_codepage, thiscp);
+ conf_set_str(conf, CONF_line_codepage, thiscp);
dlg_update_done(ctrl, dlg);
} else if (event == EVENT_VALCHANGE) {
- dlg_editbox_get(ctrl, dlg, cfg->line_codepage,
- sizeof(cfg->line_codepage));
- strcpy(cfg->line_codepage,
- cp_name(decode_codepage(cfg->line_codepage)));
+ char *codepage = dlg_editbox_get(ctrl, dlg);
+ conf_set_str(conf, CONF_line_codepage,
+ cp_name(decode_codepage(codepage)));
+ sfree(codepage);
}
}
static void sshbug_handler(union control *ctrl, void *dlg,
void *data, int event)
{
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO);
dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF);
dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON);
- switch (*(int *)ATOFFSET(data, ctrl->listbox.context.i)) {
+ switch (conf_get_int(conf, ctrl->listbox.context.i)) {
case AUTO: dlg_listbox_select(ctrl, dlg, 0); break;
case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 1); break;
case FORCE_ON: dlg_listbox_select(ctrl, dlg, 2); break;
i = AUTO;
else
i = dlg_listbox_getid(ctrl, dlg, i);
- *(int *)ATOFFSET(data, ctrl->listbox.context.i) = i;
+ conf_set_int(conf, ctrl->listbox.context.i, i);
}
}
*/
static int load_selected_session(struct sessionsaver_data *ssd,
char *savedsession,
- void *dlg, Config *cfg, int *maybe_launch)
+ void *dlg, Conf *conf, int *maybe_launch)
{
int i = dlg_listbox_index(ssd->listbox, dlg);
int isdef;
return 0;
}
isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
- load_settings(ssd->sesslist.sessions[i], cfg);
+ load_settings(ssd->sesslist.sessions[i], conf);
if (!isdef) {
strncpy(savedsession, ssd->sesslist.sessions[i],
SAVEDSESSION_LEN);
static void sessionsaver_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct sessionsaver_data *ssd =
(struct sessionsaver_data *)ctrl->generic.context.p;
char *savedsession;
* The first time we're called in a new dialog, we must
* allocate space to store the current contents of the saved
* session edit box (since it must persist even when we switch
- * panels, but is not part of the Config).
+ * panels, but is not part of the Conf).
+ *
+ * FIXME: this is disgusting, and we'd do much better to have
+ * the persistent storage be dynamically allocated and get rid
+ * of the arbitrary limit SAVEDSESSION_LEN. To do that would
+ * require a means of making sure the memory gets freed at the
+ * appropriate moment.
*/
if (!ssd->editbox) {
savedsession = NULL;
} else if (event == EVENT_VALCHANGE) {
int top, bottom, halfway, i;
if (ctrl == ssd->editbox) {
- dlg_editbox_get(ctrl, dlg, savedsession,
- SAVEDSESSION_LEN);
+ char *tmp = dlg_editbox_get(ctrl, dlg);
+ strncpy(savedsession, tmp, SAVEDSESSION_LEN);
+ sfree(tmp);
top = ssd->sesslist.nsessions;
bottom = -1;
while (top-bottom > 1) {
* double-click on the list box _and_ that session
* contains a hostname.
*/
- if (load_selected_session(ssd, savedsession, dlg, cfg, &mbl) &&
- (mbl && ctrl == ssd->listbox && cfg_launchable(cfg))) {
+ if (load_selected_session(ssd, savedsession, dlg, conf, &mbl) &&
+ (mbl && ctrl == ssd->listbox && conf_launchable(conf))) {
dlg_end(dlg, 1); /* it's all over, and succeeded */
}
} else if (ctrl == ssd->savebutton) {
}
}
{
- char *errmsg = save_settings(savedsession, cfg);
+ char *errmsg = save_settings(savedsession, conf);
if (errmsg) {
dlg_error_msg(dlg, errmsg);
sfree(errmsg);
* valid host name in it, then load it and go.
*/
if (dlg_last_focused(ctrl, dlg) == ssd->listbox &&
- !cfg_launchable(cfg)) {
- Config cfg2;
+ !conf_launchable(conf)) {
+ Conf *conf2 = conf_new();
int mbl = FALSE;
if (!load_selected_session(ssd, savedsession, dlg,
- &cfg2, &mbl)) {
+ conf2, &mbl)) {
dlg_beep(dlg);
+ conf_free(conf2);
return;
}
/* If at this point we have a valid session, go! */
- if (mbl && cfg_launchable(&cfg2)) {
- *cfg = cfg2; /* structure copy */
- cfg->remote_cmd_ptr = NULL;
+ if (mbl && conf_launchable(conf2)) {
+ conf_copy_into(conf, conf2);
dlg_end(dlg, 1);
} else
dlg_beep(dlg);
+
+ conf_free(conf2);
return;
}
* Otherwise, do the normal thing: if we have a valid
* session, get going.
*/
- if (cfg_launchable(cfg)) {
+ if (conf_launchable(conf)) {
dlg_end(dlg, 1);
} else
dlg_beep(dlg);
static void charclass_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct charclass_data *ccd =
(struct charclass_data *)ctrl->generic.context.p;
for (i = 0; i < 128; i++) {
char str[100];
sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
- (i >= 0x21 && i != 0x7F) ? i : ' ', cfg->wordness[i]);
+ (i >= 0x21 && i != 0x7F) ? i : ' ',
+ conf_get_int_int(conf, CONF_wordness, i));
dlg_listbox_add(ctrl, dlg, str);
}
dlg_update_done(ctrl, dlg);
}
} else if (event == EVENT_ACTION) {
if (ctrl == ccd->button) {
- char str[100];
+ char *str;
int i, n;
- dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str));
+ str = dlg_editbox_get(ccd->editbox, dlg);
n = atoi(str);
+ sfree(str);
for (i = 0; i < 128; i++) {
if (dlg_listbox_issel(ccd->listbox, dlg, i))
- cfg->wordness[i] = n;
+ conf_set_int_int(conf, CONF_wordness, i, n);
}
dlg_refresh(ccd->listbox, dlg);
}
static void colour_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct colour_data *cd =
(struct colour_data *)ctrl->generic.context.p;
int update = FALSE, clear = FALSE, r, g, b;
clear = TRUE;
} else {
clear = FALSE;
- r = cfg->colours[i][0];
- g = cfg->colours[i][1];
- b = cfg->colours[i][2];
+ r = conf_get_int_int(conf, CONF_colours, i*3+0);
+ g = conf_get_int_int(conf, CONF_colours, i*3+0);
+ b = conf_get_int_int(conf, CONF_colours, i*3+0);
}
update = TRUE;
}
} else if (event == EVENT_VALCHANGE) {
if (ctrl == cd->redit || ctrl == cd->gedit || ctrl == cd->bedit) {
/* The user has changed the colour using the edit boxes. */
- char buf[80];
+ char *str;
int i, cval;
- dlg_editbox_get(ctrl, dlg, buf, lenof(buf));
- cval = atoi(buf);
+ str = dlg_editbox_get(ctrl, dlg);
+ cval = atoi(str);
+ sfree(str);
if (cval > 255) cval = 255;
if (cval < 0) cval = 0;
i = dlg_listbox_index(cd->listbox, dlg);
if (i >= 0) {
if (ctrl == cd->redit)
- cfg->colours[i][0] = cval;
+ conf_set_int_int(conf, CONF_colours, i*3+0, cval);
else if (ctrl == cd->gedit)
- cfg->colours[i][1] = cval;
+ conf_set_int_int(conf, CONF_colours, i*3+1, cval);
else if (ctrl == cd->bedit)
- cfg->colours[i][2] = cval;
+ conf_set_int_int(conf, CONF_colours, i*3+2, cval);
}
}
} else if (event == EVENT_ACTION) {
* pick up the results.
*/
dlg_coloursel_start(ctrl, dlg,
- cfg->colours[i][0],
- cfg->colours[i][1],
- cfg->colours[i][2]);
+ conf_get_int_int(conf, CONF_colours, i*3+0),
+ conf_get_int_int(conf, CONF_colours, i*3+1),
+ conf_get_int_int(conf, CONF_colours, i*3+2));
}
} else if (event == EVENT_CALLBACK) {
if (ctrl == cd->button) {
* selector did nothing (user hit Cancel, for example).
*/
if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
- cfg->colours[i][0] = r;
- cfg->colours[i][1] = g;
- cfg->colours[i][2] = b;
+ conf_set_int_int(conf, CONF_colours, i*3+0, r);
+ conf_set_int_int(conf, CONF_colours, i*3+0, g);
+ conf_set_int_int(conf, CONF_colours, i*3+0, b);
clear = FALSE;
update = TRUE;
}
static void ttymodes_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct ttymodes_data *td =
(struct ttymodes_data *)ctrl->generic.context.p;
if (event == EVENT_REFRESH) {
if (ctrl == td->listbox) {
- char *p = cfg->ttymodes;
+ char *key, *val;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
- while (*p) {
- int tabpos = strchr(p, '\t') - p;
- char *disp = dupprintf("%.*s\t%s", tabpos, p,
- (p[tabpos+1] == 'A') ? "(auto)" :
- p+tabpos+2);
+ for (val = conf_get_str_strs(conf, CONF_ttymodes, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_ttymodes, key, &key)) {
+ char *disp = dupprintf("%s\t%s", key,
+ (val[0] == 'A') ? "(auto)" : val+1);
dlg_listbox_add(ctrl, dlg, disp);
- p += strlen(p) + 1;
sfree(disp);
}
dlg_update_done(ctrl, dlg);
int ind = dlg_listbox_index(td->modelist, dlg);
if (ind >= 0) {
char type = dlg_radiobutton_get(td->valradio, dlg) ? 'V' : 'A';
- int slen, left;
- char *p, str[lenof(cfg->ttymodes)];
+ const char *key;
+ char *str, *val;
/* Construct new entry */
- memset(str, 0, lenof(str));
- strncpy(str, ttymodes[ind], lenof(str)-3);
- slen = strlen(str);
- str[slen] = '\t';
- str[slen+1] = type;
- slen += 2;
- if (type == 'V') {
- dlg_editbox_get(td->valbox, dlg, str+slen, lenof(str)-slen);
- }
- /* Find end of list, deleting any existing instance */
- p = cfg->ttymodes;
- left = lenof(cfg->ttymodes);
- while (*p) {
- int t = strchr(p, '\t') - p;
- if (t == strlen(ttymodes[ind]) &&
- strncmp(p, ttymodes[ind], t) == 0) {
- memmove(p, p+strlen(p)+1, left - (strlen(p)+1));
- continue;
- }
- left -= strlen(p) + 1;
- p += strlen(p) + 1;
- }
- /* Append new entry */
- memset(p, 0, left);
- strncpy(p, str, left - 2);
+ key = ttymodes[ind];
+ str = dlg_editbox_get(td->valbox, dlg);
+ val = dupprintf("%c%s", type, str);
+ sfree(str);
+ conf_set_str_str(conf, CONF_ttymodes, key, val);
+ sfree(val);
dlg_refresh(td->listbox, dlg);
} else
dlg_beep(dlg);
} else if (ctrl == td->rembutton) {
- char *p = cfg->ttymodes;
- int i = 0, len = lenof(cfg->ttymodes);
- while (*p) {
- int multisel = dlg_listbox_index(td->listbox, dlg) < 0;
+ int i = 0;
+ char *key, *val;
+ int multisel = dlg_listbox_index(td->listbox, dlg) < 0;
+ for (val = conf_get_str_strs(conf, CONF_ttymodes, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_ttymodes, key, &key)) {
if (dlg_listbox_issel(td->listbox, dlg, i)) {
if (!multisel) {
/* Populate controls with entry we're about to
* delete, for ease of editing.
* (If multiple entries were selected, don't
* touch the controls.) */
- char *val = strchr(p, '\t');
- if (val) {
- int ind = 0;
- val++;
- while (ttymodes[ind]) {
- if (strlen(ttymodes[ind]) == val-p-1 &&
- !strncmp(ttymodes[ind], p, val-p-1))
- break;
- ind++;
- }
- dlg_listbox_select(td->modelist, dlg, ind);
- dlg_radiobutton_set(td->valradio, dlg,
- (*val == 'V'));
- dlg_editbox_set(td->valbox, dlg, val+1);
+ int ind = 0;
+ val++;
+ while (ttymodes[ind]) {
+ if (!strcmp(ttymodes[ind], key))
+ break;
+ ind++;
}
+ dlg_listbox_select(td->modelist, dlg, ind);
+ dlg_radiobutton_set(td->valradio, dlg,
+ (*val == 'V'));
+ dlg_editbox_set(td->valbox, dlg, val+1);
}
- memmove(p, p+strlen(p)+1, len - (strlen(p)+1));
- i++;
- continue;
+ conf_del_str_str(conf, CONF_ttymodes, key);
}
- len -= strlen(p) + 1;
- p += strlen(p) + 1;
i++;
}
- memset(p, 0, lenof(cfg->ttymodes) - len);
dlg_refresh(td->listbox, dlg);
}
}
static void environ_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct environ_data *ed =
(struct environ_data *)ctrl->generic.context.p;
if (event == EVENT_REFRESH) {
if (ctrl == ed->listbox) {
- char *p = cfg->environmt;
+ char *key, *val;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
- while (*p) {
+ for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_environmt, key, &key)) {
+ char *p = dupprintf("%s\t%s", key, val);
dlg_listbox_add(ctrl, dlg, p);
- p += strlen(p) + 1;
+ sfree(p);
}
dlg_update_done(ctrl, dlg);
}
} else if (event == EVENT_ACTION) {
if (ctrl == ed->addbutton) {
- char str[sizeof(cfg->environmt)];
- char *p;
- dlg_editbox_get(ed->varbox, dlg, str, sizeof(str)-1);
- if (!*str) {
+ char *key, *val, *str;
+ key = dlg_editbox_get(ed->varbox, dlg);
+ if (!*key) {
+ sfree(key);
dlg_beep(dlg);
return;
}
- p = str + strlen(str);
- *p++ = '\t';
- dlg_editbox_get(ed->valbox, dlg, p, sizeof(str)-1 - (p - str));
- if (!*p) {
+ val = dlg_editbox_get(ed->valbox, dlg);
+ if (!*val) {
+ sfree(key);
+ sfree(val);
dlg_beep(dlg);
return;
}
- p = cfg->environmt;
- while (*p) {
- while (*p)
- p++;
- p++;
- }
- if ((p - cfg->environmt) + strlen(str) + 2 <
- sizeof(cfg->environmt)) {
- strcpy(p, str);
- p[strlen(str) + 1] = '\0';
- dlg_listbox_add(ed->listbox, dlg, str);
- dlg_editbox_set(ed->varbox, dlg, "");
- dlg_editbox_set(ed->valbox, dlg, "");
- } else {
- dlg_error_msg(dlg, "Environment too big");
- }
+ conf_set_str_str(conf, CONF_environmt, key, val);
+ str = dupcat(key, "\t", val, NULL);
+ dlg_editbox_set(ed->varbox, dlg, "");
+ dlg_editbox_set(ed->valbox, dlg, "");
+ sfree(str);
+ sfree(key);
+ sfree(val);
+ dlg_refresh(ed->listbox, dlg);
} else if (ctrl == ed->rembutton) {
int i = dlg_listbox_index(ed->listbox, dlg);
if (i < 0) {
dlg_beep(dlg);
} else {
- char *p, *q, *str;
-
- dlg_listbox_del(ed->listbox, dlg, i);
- p = cfg->environmt;
- while (i > 0) {
- if (!*p)
- goto disaster;
- while (*p)
- p++;
- p++;
- i--;
- }
- q = p;
- if (!*p)
- goto disaster;
- /* Populate controls with the entry we're about to delete
- * for ease of editing */
- str = p;
- p = strchr(p, '\t');
- if (!p)
- goto disaster;
- *p = '\0';
- dlg_editbox_set(ed->varbox, dlg, str);
- p++;
- str = p;
- dlg_editbox_set(ed->valbox, dlg, str);
- p = strchr(p, '\0');
- if (!p)
- goto disaster;
- p++;
- while (*p) {
- while (*p)
- *q++ = *p++;
- *q++ = *p++;
+ char *key, *val;
+
+ key = conf_get_str_nthstrkey(conf, CONF_environmt, i);
+ if (key) {
+ /* Populate controls with the entry we're about to delete
+ * for ease of editing */
+ val = conf_get_str_str(conf, CONF_environmt, key);
+ dlg_editbox_set(ed->varbox, dlg, key);
+ dlg_editbox_set(ed->valbox, dlg, val);
+ /* And delete it */
+ conf_del_str_str(conf, CONF_environmt, key);
}
- *q = '\0';
- disaster:;
}
+ dlg_refresh(ed->listbox, dlg);
}
}
}
static void portfwd_handler(union control *ctrl, void *dlg,
void *data, int event)
{
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
struct portfwd_data *pfd =
(struct portfwd_data *)ctrl->generic.context.p;
if (event == EVENT_REFRESH) {
if (ctrl == pfd->listbox) {
- char *p = cfg->portfwd;
+ char *key, *val;
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
- while (*p) {
+ for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
+ char *p;
+ if (!strcmp(val, "D"))
+ p = dupprintf("D%s\t", key+1);
+ else
+ p = dupprintf("%s\t%s", key, val);
dlg_listbox_add(ctrl, dlg, p);
- p += strlen(p) + 1;
+ sfree(p);
}
dlg_update_done(ctrl, dlg);
} else if (ctrl == pfd->direction) {
}
} else if (event == EVENT_ACTION) {
if (ctrl == pfd->addbutton) {
- char str[sizeof(cfg->portfwd)];
- char *p;
- int i, type;
- int whichbutton;
+ char *family, *type, *src, *key, *val;
+ int i, whichbutton;
i = 0;
#ifndef NO_IPV6
whichbutton = dlg_radiobutton_get(pfd->addressfamily, dlg);
if (whichbutton == 1)
- str[i++] = '4';
+ family = "4";
else if (whichbutton == 2)
- str[i++] = '6';
+ family = "6";
+ else
+ family = "";
#endif
whichbutton = dlg_radiobutton_get(pfd->direction, dlg);
if (whichbutton == 0)
- type = 'L';
+ type = "L";
else if (whichbutton == 1)
- type = 'R';
+ type = "R";
else
- type = 'D';
- str[i++] = type;
+ type = "D";
- dlg_editbox_get(pfd->sourcebox, dlg, str+i, sizeof(str) - i);
- if (!str[i]) {
+ src = dlg_editbox_get(pfd->sourcebox, dlg);
+ if (!*src) {
dlg_error_msg(dlg, "You need to specify a source port number");
+ sfree(src);
return;
}
- p = str + strlen(str);
- if (type != 'D') {
- *p++ = '\t';
- dlg_editbox_get(pfd->destbox, dlg, p,
- sizeof(str) - (p - str));
- if (!*p || !strchr(p, ':')) {
+ if (*type != 'D') {
+ val = dlg_editbox_get(pfd->destbox, dlg);
+ if (!*val || !strchr(val, ':')) {
dlg_error_msg(dlg,
"You need to specify a destination address\n"
"in the form \"host.name:port\"");
+ sfree(src);
+ sfree(val);
return;
}
- } else
- *p = '\0';
- p = cfg->portfwd;
- while (*p) {
- if (strcmp(p,str) == 0) {
- dlg_error_msg(dlg, "Specified forwarding already exists");
- break;
- }
- while (*p)
- p++;
- p++;
- }
- if (!*p) {
- if ((p - cfg->portfwd) + strlen(str) + 2 <=
- sizeof(cfg->portfwd)) {
- strcpy(p, str);
- p[strlen(str) + 1] = '\0';
- dlg_listbox_add(pfd->listbox, dlg, str);
- dlg_editbox_set(pfd->sourcebox, dlg, "");
- dlg_editbox_set(pfd->destbox, dlg, "");
- } else {
- dlg_error_msg(dlg, "Too many forwardings");
- }
+ } else {
+ type = "L";
+ val = dupstr("D"); /* special case */
+ }
+
+ key = dupcat(family, type, src, NULL);
+ sfree(src);
+
+ if (conf_get_str_str_opt(conf, CONF_portfwd, key)) {
+ dlg_error_msg(dlg, "Specified forwarding already exists");
+ } else {
+ conf_set_str_str(conf, CONF_portfwd, key, val);
}
+
+ sfree(key);
+ sfree(val);
+ dlg_refresh(pfd->listbox, dlg);
} else if (ctrl == pfd->rembutton) {
int i = dlg_listbox_index(pfd->listbox, dlg);
- if (i < 0)
+ if (i < 0) {
dlg_beep(dlg);
- else {
- char *p, *q, *src, *dst;
- char dir;
-
- dlg_listbox_del(pfd->listbox, dlg, i);
- p = cfg->portfwd;
- while (i > 0) {
- if (!*p)
- goto disaster2;
- while (*p)
- p++;
- p++;
- i--;
- }
- q = p;
- if (!*p)
- goto disaster2;
- /* Populate the controls with the entry we're about to
- * delete, for ease of editing. */
- {
+ } else {
+ char *key, *val, *p;
+
+ key = conf_get_str_nthstrkey(conf, CONF_portfwd, i);
+ if (key) {
static const char *const afs = "A46";
- char *afp = strchr(afs, *p);
+ static const char *const dirs = "LRD";
+ char *afp;
+ int dir;
#ifndef NO_IPV6
- int idx = afp ? afp-afs : 0;
+ int idx;
+#endif
+
+ /* Populate controls with the entry we're about to delete
+ * for ease of editing */
+ p = key;
+
+ afp = strchr(afs, *p);
+#ifndef NO_IPV6
+ idx = afp ? afp-afs : 0;
#endif
if (afp)
p++;
#ifndef NO_IPV6
dlg_radiobutton_set(pfd->addressfamily, dlg, idx);
#endif
- }
- {
- static const char *const dirs = "LRD";
+
dir = *p;
+
+ val = conf_get_str_str(conf, CONF_portfwd, key);
+ if (!strcmp(val, "D")) {
+ dir = 'D';
+ val = "";
+ }
+
dlg_radiobutton_set(pfd->direction, dlg,
strchr(dirs, dir) - dirs);
- }
- p++;
- if (dir != 'D') {
- src = p;
- p = strchr(p, '\t');
- if (!p)
- goto disaster2;
- *p = '\0';
p++;
- dst = p;
- } else {
- src = p;
- dst = "";
- }
- p = strchr(p, '\0');
- if (!p)
- goto disaster2;
- dlg_editbox_set(pfd->sourcebox, dlg, src);
- dlg_editbox_set(pfd->destbox, dlg, dst);
- p++;
- while (*p) {
- while (*p)
- *q++ = *p++;
- *q++ = *p++;
+
+ dlg_editbox_set(pfd->sourcebox, dlg, p);
+ dlg_editbox_set(pfd->destbox, dlg, val);
+ /* And delete it */
+ conf_del_str_str(conf, CONF_portfwd, key);
}
- *q = '\0';
- disaster2:;
}
+ dlg_refresh(pfd->listbox, dlg);
}
}
}
s = ctrl_getset(b, "Session", "otheropts", NULL);
c = ctrl_radiobuttons(s, "Close window on exit:", 'x', 4,
HELPCTX(session_coe),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, close_on_exit)),
+ conf_radiobutton_handler,
+ I(CONF_close_on_exit),
"Always", I(FORCE_ON),
"Never", I(FORCE_OFF),
"Only on clean exit", I(AUTO), NULL);
ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 2,
HELPCTX(logging_main),
loggingbuttons_handler,
- I(offsetof(Config, logtype)),
+ I(CONF_logtype),
"None", 't', I(LGTYP_NONE),
"Printable output", 'p', I(LGTYP_ASCII),
"All session output", 'l', I(LGTYP_DEBUG),
ctrl_filesel(s, "Log file name:", 'f',
NULL, TRUE, "Select session log file name",
HELPCTX(logging_filename),
- dlg_stdfilesel_handler, I(offsetof(Config, logfilename)));
+ conf_filesel_handler, I(CONF_logfilename));
ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
" &T for time, and &H for host name)",
HELPCTX(logging_filename));
ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
HELPCTX(logging_exists),
- dlg_stdradiobutton_handler, I(offsetof(Config,logxfovr)),
+ conf_radiobutton_handler, I(CONF_logxfovr),
"Always overwrite it", I(LGXF_OVR),
"Always append to the end of it", I(LGXF_APN),
"Ask the user every time", I(LGXF_ASK), NULL);
ctrl_checkbox(s, "Flush log file frequently", 'u',
HELPCTX(logging_flush),
- dlg_stdcheckbox_handler, I(offsetof(Config,logflush)));
+ conf_checkbox_handler, I(CONF_logflush));
if ((midsession && protocol == PROT_SSH) ||
(!midsession && backend_from_proto(PROT_SSH))) {
"Options specific to SSH packet logging");
ctrl_checkbox(s, "Omit known password fields", 'k',
HELPCTX(logging_ssh_omit_password),
- dlg_stdcheckbox_handler, I(offsetof(Config,logomitpass)));
+ conf_checkbox_handler, I(CONF_logomitpass));
ctrl_checkbox(s, "Omit session data", 'd',
HELPCTX(logging_ssh_omit_data),
- dlg_stdcheckbox_handler, I(offsetof(Config,logomitdata)));
+ conf_checkbox_handler, I(CONF_logomitdata));
}
/*
s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
HELPCTX(terminal_autowrap),
- dlg_stdcheckbox_handler, I(offsetof(Config,wrap_mode)));
+ conf_checkbox_handler, I(CONF_wrap_mode));
ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
HELPCTX(terminal_decom),
- dlg_stdcheckbox_handler, I(offsetof(Config,dec_om)));
+ conf_checkbox_handler, I(CONF_dec_om));
ctrl_checkbox(s, "Implicit CR in every LF", 'r',
HELPCTX(terminal_lfhascr),
- dlg_stdcheckbox_handler, I(offsetof(Config,lfhascr)));
+ conf_checkbox_handler, I(CONF_lfhascr));
ctrl_checkbox(s, "Implicit LF in every CR", 'f',
HELPCTX(terminal_crhaslf),
- dlg_stdcheckbox_handler, I(offsetof(Config,crhaslf)));
+ conf_checkbox_handler, I(CONF_crhaslf));
ctrl_checkbox(s, "Use background colour to erase screen", 'e',
HELPCTX(terminal_bce),
- dlg_stdcheckbox_handler, I(offsetof(Config,bce)));
+ conf_checkbox_handler, I(CONF_bce));
ctrl_checkbox(s, "Enable blinking text", 'n',
HELPCTX(terminal_blink),
- dlg_stdcheckbox_handler, I(offsetof(Config,blinktext)));
+ conf_checkbox_handler, I(CONF_blinktext));
ctrl_editbox(s, "Answerback to ^E:", 's', 100,
HELPCTX(terminal_answerback),
- dlg_stdeditbox_handler, I(offsetof(Config,answerback)),
- I(sizeof(((Config *)0)->answerback)));
+ conf_editbox_handler, I(CONF_answerback), I(1));
s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
ctrl_radiobuttons(s, "Local echo:", 'l', 3,
HELPCTX(terminal_localecho),
- dlg_stdradiobutton_handler,I(offsetof(Config,localecho)),
+ conf_radiobutton_handler,I(CONF_localecho),
"Auto", I(AUTO),
"Force on", I(FORCE_ON),
"Force off", I(FORCE_OFF), NULL);
ctrl_radiobuttons(s, "Local line editing:", 't', 3,
HELPCTX(terminal_localedit),
- dlg_stdradiobutton_handler,I(offsetof(Config,localedit)),
+ conf_radiobutton_handler,I(CONF_localedit),
"Auto", I(AUTO),
"Force on", I(FORCE_ON),
"Force off", I(FORCE_OFF), NULL);
"Change the sequences sent by:");
ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
HELPCTX(keyboard_backspace),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, bksp_is_delete)),
+ conf_radiobutton_handler,
+ I(CONF_bksp_is_delete),
"Control-H", I(0), "Control-? (127)", I(1), NULL);
ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
HELPCTX(keyboard_homeend),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, rxvt_homeend)),
+ conf_radiobutton_handler,
+ I(CONF_rxvt_homeend),
"Standard", I(0), "rxvt", I(1), NULL);
ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3,
HELPCTX(keyboard_funkeys),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, funky_type)),
+ conf_radiobutton_handler,
+ I(CONF_funky_type),
"ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2),
"VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL);
"Application keypad settings:");
ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
HELPCTX(keyboard_appcursor),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, app_cursor)),
+ conf_radiobutton_handler,
+ I(CONF_app_cursor),
"Normal", I(0), "Application", I(1), NULL);
ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
HELPCTX(keyboard_appkeypad),
s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
HELPCTX(bell_style),
- dlg_stdradiobutton_handler, I(offsetof(Config, beep)),
+ conf_radiobutton_handler, I(CONF_beep),
"None (bell disabled)", I(BELL_DISABLED),
"Make default system alert sound", I(BELL_DEFAULT),
"Visual bell (flash window)", I(BELL_VISUAL), NULL);
"Control the bell overload behaviour");
ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
HELPCTX(bell_overload),
- dlg_stdcheckbox_handler, I(offsetof(Config,bellovl)));
+ conf_checkbox_handler, I(CONF_bellovl));
ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
HELPCTX(bell_overload),
- dlg_stdeditbox_handler, I(offsetof(Config,bellovl_n)), I(-1));
+ conf_editbox_handler, I(CONF_bellovl_n), I(-1));
ctrl_editbox(s, "... in this many seconds", 't', 20,
HELPCTX(bell_overload),
- dlg_stdeditbox_handler, I(offsetof(Config,bellovl_t)),
+ conf_editbox_handler, I(CONF_bellovl_t),
I(-TICKSPERSEC));
ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
HELPCTX(bell_overload));
ctrl_editbox(s, "Seconds of silence required", 's', 20,
HELPCTX(bell_overload),
- dlg_stdeditbox_handler, I(offsetof(Config,bellovl_s)),
+ conf_editbox_handler, I(CONF_bellovl_s),
I(-TICKSPERSEC));
/*
s = ctrl_getset(b, "Terminal/Features", "main", NULL);
ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
HELPCTX(features_application),
- dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_c)));
+ conf_checkbox_handler, I(CONF_no_applic_c));
ctrl_checkbox(s, "Disable application keypad mode", 'k',
HELPCTX(features_application),
- dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_k)));
+ conf_checkbox_handler, I(CONF_no_applic_k));
ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
HELPCTX(features_mouse),
- dlg_stdcheckbox_handler, I(offsetof(Config,no_mouse_rep)));
+ conf_checkbox_handler, I(CONF_no_mouse_rep));
ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
HELPCTX(features_resize),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,no_remote_resize)));
+ conf_checkbox_handler,
+ I(CONF_no_remote_resize));
ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
HELPCTX(features_altscreen),
- dlg_stdcheckbox_handler, I(offsetof(Config,no_alt_screen)));
+ conf_checkbox_handler, I(CONF_no_alt_screen));
ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
HELPCTX(features_retitle),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,no_remote_wintitle)));
+ conf_checkbox_handler,
+ I(CONF_no_remote_wintitle));
ctrl_radiobuttons(s, "Response to remote title query (SECURITY):", 'q', 3,
HELPCTX(features_qtitle),
- dlg_stdradiobutton_handler,
- I(offsetof(Config,remote_qtitle_action)),
+ conf_radiobutton_handler,
+ I(CONF_remote_qtitle_action),
"None", I(TITLE_NONE),
"Empty string", I(TITLE_EMPTY),
"Window title", I(TITLE_REAL), NULL);
ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
HELPCTX(features_dbackspace),
- dlg_stdcheckbox_handler, I(offsetof(Config,no_dbackspace)));
+ conf_checkbox_handler, I(CONF_no_dbackspace));
ctrl_checkbox(s, "Disable remote-controlled character set configuration",
- 'r', HELPCTX(features_charset), dlg_stdcheckbox_handler,
- I(offsetof(Config,no_remote_charset)));
+ 'r', HELPCTX(features_charset), conf_checkbox_handler,
+ I(CONF_no_remote_charset));
ctrl_checkbox(s, "Disable Arabic text shaping",
- 'l', HELPCTX(features_arabicshaping), dlg_stdcheckbox_handler,
- I(offsetof(Config, arabicshaping)));
+ 'l', HELPCTX(features_arabicshaping), conf_checkbox_handler,
+ I(CONF_arabicshaping));
ctrl_checkbox(s, "Disable bidirectional text display",
- 'd', HELPCTX(features_bidi), dlg_stdcheckbox_handler,
- I(offsetof(Config, bidi)));
+ 'd', HELPCTX(features_bidi), conf_checkbox_handler,
+ I(CONF_bidi));
/*
* The Window panel.
ctrl_columns(s, 2, 50, 50);
c = ctrl_editbox(s, "Columns", 'm', 100,
HELPCTX(window_size),
- dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
+ conf_editbox_handler, I(CONF_width), I(-1));
c->generic.column = 0;
c = ctrl_editbox(s, "Rows", 'r', 100,
HELPCTX(window_size),
- dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
+ conf_editbox_handler, I(CONF_height),I(-1));
c->generic.column = 1;
ctrl_columns(s, 1, 100);
"Control the scrollback in the window");
ctrl_editbox(s, "Lines of scrollback", 's', 50,
HELPCTX(window_scrollback),
- dlg_stdeditbox_handler, I(offsetof(Config,savelines)), I(-1));
+ conf_editbox_handler, I(CONF_savelines), I(-1));
ctrl_checkbox(s, "Display scrollbar", 'd',
HELPCTX(window_scrollback),
- dlg_stdcheckbox_handler, I(offsetof(Config,scrollbar)));
+ conf_checkbox_handler, I(CONF_scrollbar));
ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
HELPCTX(window_scrollback),
- dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_key)));
+ conf_checkbox_handler, I(CONF_scroll_on_key));
ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
HELPCTX(window_scrollback),
- dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp)));
+ conf_checkbox_handler, I(CONF_scroll_on_disp));
ctrl_checkbox(s, "Push erased text into scrollback", 'e',
HELPCTX(window_erased),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,erase_to_scrollback)));
+ conf_checkbox_handler,
+ I(CONF_erase_to_scrollback));
/*
* The Window/Appearance panel.
"Adjust the use of the cursor");
ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
HELPCTX(appearance_cursor),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, cursor_type)),
+ conf_radiobutton_handler,
+ I(CONF_cursor_type),
"Block", 'l', I(0),
"Underline", 'u', I(1),
"Vertical line", 'v', I(2), NULL);
ctrl_checkbox(s, "Cursor blinks", 'b',
HELPCTX(appearance_cursor),
- dlg_stdcheckbox_handler, I(offsetof(Config,blink_cur)));
+ conf_checkbox_handler, I(CONF_blink_cur));
s = ctrl_getset(b, "Window/Appearance", "font",
"Font settings");
ctrl_fontsel(s, "Font used in the terminal window", 'n',
HELPCTX(appearance_font),
- dlg_stdfontsel_handler, I(offsetof(Config, font)));
+ conf_fontsel_handler, I(CONF_font));
s = ctrl_getset(b, "Window/Appearance", "mouse",
"Adjust the use of the mouse pointer");
ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
HELPCTX(appearance_hidemouse),
- dlg_stdcheckbox_handler, I(offsetof(Config,hide_mouseptr)));
+ conf_checkbox_handler, I(CONF_hide_mouseptr));
s = ctrl_getset(b, "Window/Appearance", "border",
"Adjust the window border");
ctrl_editbox(s, "Gap between text and window edge:", 'e', 20,
HELPCTX(appearance_border),
- dlg_stdeditbox_handler,
- I(offsetof(Config,window_border)), I(-1));
+ conf_editbox_handler,
+ I(CONF_window_border), I(-1));
/*
* The Window/Behaviour panel.
"Adjust the behaviour of the window title");
ctrl_editbox(s, "Window title:", 't', 100,
HELPCTX(appearance_title),
- dlg_stdeditbox_handler, I(offsetof(Config,wintitle)),
- I(sizeof(((Config *)0)->wintitle)));
+ conf_editbox_handler, I(CONF_wintitle), I(1));
ctrl_checkbox(s, "Separate window and icon titles", 'i',
HELPCTX(appearance_title),
- dlg_stdcheckbox_handler,
- I(CHECKBOX_INVERT | offsetof(Config,win_name_always)));
+ conf_checkbox_handler,
+ I(CHECKBOX_INVERT | CONF_win_name_always));
s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
ctrl_checkbox(s, "Warn before closing window", 'w',
HELPCTX(behaviour_closewarn),
- dlg_stdcheckbox_handler, I(offsetof(Config,warn_on_close)));
+ conf_checkbox_handler, I(CONF_warn_on_close));
/*
* The Window/Translation panel.
s = ctrl_getset(b, "Window/Translation", "tweaks", NULL);
ctrl_checkbox(s, "Treat CJK ambiguous characters as wide", 'w',
HELPCTX(translation_cjk_ambig_wide),
- dlg_stdcheckbox_handler, I(offsetof(Config,cjk_ambig_wide)));
+ conf_checkbox_handler, I(CONF_cjk_ambig_wide));
str = dupprintf("Adjust how %s handles line drawing characters", appname);
s = ctrl_getset(b, "Window/Translation", "linedraw", str);
sfree(str);
ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1,
HELPCTX(translation_linedraw),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, vtmode)),
+ conf_radiobutton_handler,
+ I(CONF_vtmode),
"Use Unicode line drawing code points",'u',I(VT_UNICODE),
"Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN),
NULL);
ctrl_checkbox(s, "Copy and paste line drawing characters as lqqqk",'d',
HELPCTX(selection_linedraw),
- dlg_stdcheckbox_handler, I(offsetof(Config,rawcnp)));
+ conf_checkbox_handler, I(CONF_rawcnp));
/*
* The Window/Selection panel.
"Control use of mouse");
ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
HELPCTX(selection_shiftdrag),
- dlg_stdcheckbox_handler, I(offsetof(Config,mouse_override)));
+ conf_checkbox_handler, I(CONF_mouse_override));
ctrl_radiobuttons(s,
"Default selection mode (Alt+drag does the other one):",
NO_SHORTCUT, 2,
HELPCTX(selection_rect),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, rect_select)),
+ conf_radiobutton_handler,
+ I(CONF_rect_select),
"Normal", 'n', I(0),
"Rectangular block", 'r', I(1), NULL);
"General options for colour usage");
ctrl_checkbox(s, "Allow terminal to specify ANSI colours", 'i',
HELPCTX(colours_ansi),
- dlg_stdcheckbox_handler, I(offsetof(Config,ansi_colour)));
+ conf_checkbox_handler, I(CONF_ansi_colour));
ctrl_checkbox(s, "Allow terminal to use xterm 256-colour mode", '2',
- HELPCTX(colours_xterm256), dlg_stdcheckbox_handler,
- I(offsetof(Config,xterm_256_colour)));
+ HELPCTX(colours_xterm256), conf_checkbox_handler,
+ I(CONF_xterm_256_colour));
ctrl_checkbox(s, "Bolded text is a different colour", 'b',
HELPCTX(colours_bold),
- dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour)));
+ conf_checkbox_handler, I(CONF_bold_colour));
str = dupprintf("Adjust the precise colours %s displays", appname);
s = ctrl_getset(b, "Window/Colours", "adjust", str);
"Sending of null packets to keep session active");
ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
HELPCTX(connection_keepalive),
- dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
+ conf_editbox_handler, I(CONF_ping_interval),
I(-1));
if (!midsession) {
"Low-level TCP connection options");
ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)",
'n', HELPCTX(connection_nodelay),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,tcp_nodelay)));
+ conf_checkbox_handler,
+ I(CONF_tcp_nodelay));
ctrl_checkbox(s, "Enable TCP keepalives (SO_KEEPALIVE option)",
'p', HELPCTX(connection_tcpkeepalive),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,tcp_keepalives)));
+ conf_checkbox_handler,
+ I(CONF_tcp_keepalives));
#ifndef NO_IPV6
s = ctrl_getset(b, "Connection", "ipversion",
"Internet protocol version");
ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
HELPCTX(connection_ipversion),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, addressfamily)),
+ conf_radiobutton_handler,
+ I(CONF_addressfamily),
"Auto", 'u', I(ADDRTYPE_UNSPEC),
"IPv4", '4', I(ADDRTYPE_IPV4),
"IPv6", '6', I(ADDRTYPE_IPV6),
"Logical name of remote host");
ctrl_editbox(s, label, 'm', 100,
HELPCTX(connection_loghost),
- dlg_stdeditbox_handler, I(offsetof(Config,loghost)),
- I(sizeof(((Config *)0)->loghost)));
+ conf_editbox_handler, I(CONF_loghost), I(1));
}
}
"Login details");
ctrl_editbox(s, "Auto-login username", 'u', 50,
HELPCTX(connection_username),
- dlg_stdeditbox_handler, I(offsetof(Config,username)),
- I(sizeof(((Config *)0)->username)));
+ conf_editbox_handler, I(CONF_username), I(1));
{
/* We assume the local username is sufficiently stable
* to include on the dialog box. */
sfree(user);
ctrl_radiobuttons(s, "When username is not specified:", 'n', 4,
HELPCTX(connection_username_from_env),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, username_from_env)),
+ conf_radiobutton_handler,
+ I(CONF_username_from_env),
"Prompt", I(FALSE),
userlabel, I(TRUE),
NULL);
"Terminal details");
ctrl_editbox(s, "Terminal-type string", 't', 50,
HELPCTX(connection_termtype),
- dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
- I(sizeof(((Config *)0)->termtype)));
+ conf_editbox_handler, I(CONF_termtype), I(1));
ctrl_editbox(s, "Terminal speeds", 's', 50,
HELPCTX(connection_termspeed),
- dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
- I(sizeof(((Config *)0)->termspeed)));
+ conf_editbox_handler, I(CONF_termspeed), I(1));
s = ctrl_getset(b, "Connection/Data", "env",
"Environment variables");
s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
ctrl_radiobuttons(s, "Proxy type:", 't', 3,
HELPCTX(proxy_type),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, proxy_type)),
+ conf_radiobutton_handler,
+ I(CONF_proxy_type),
"None", I(PROXY_NONE),
"SOCKS 4", I(PROXY_SOCKS4),
"SOCKS 5", I(PROXY_SOCKS5),
ctrl_columns(s, 2, 80, 20);
c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
HELPCTX(proxy_main),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_host)),
- I(sizeof(((Config *)0)->proxy_host)));
+ conf_editbox_handler,
+ I(CONF_proxy_host), I(1));
c->generic.column = 0;
c = ctrl_editbox(s, "Port", 'p', 100,
HELPCTX(proxy_main),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_port)),
+ conf_editbox_handler,
+ I(CONF_proxy_port),
I(-1));
c->generic.column = 1;
ctrl_columns(s, 1, 100);
ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
HELPCTX(proxy_exclude),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_exclude_list)),
- I(sizeof(((Config *)0)->proxy_exclude_list)));
+ conf_editbox_handler,
+ I(CONF_proxy_exclude_list), I(1));
ctrl_checkbox(s, "Consider proxying local host connections", 'x',
HELPCTX(proxy_exclude),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,even_proxy_localhost)));
+ conf_checkbox_handler,
+ I(CONF_even_proxy_localhost));
ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
HELPCTX(proxy_dns),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, proxy_dns)),
+ conf_radiobutton_handler,
+ I(CONF_proxy_dns),
"No", I(FORCE_OFF),
"Auto", I(AUTO),
"Yes", I(FORCE_ON), NULL);
ctrl_editbox(s, "Username", 'u', 60,
HELPCTX(proxy_auth),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_username)),
- I(sizeof(((Config *)0)->proxy_username)));
+ conf_editbox_handler,
+ I(CONF_proxy_username), I(1));
c = ctrl_editbox(s, "Password", 'w', 60,
HELPCTX(proxy_auth),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_password)),
- I(sizeof(((Config *)0)->proxy_password)));
+ conf_editbox_handler,
+ I(CONF_proxy_password), I(1));
c->editbox.password = 1;
ctrl_editbox(s, "Telnet command", 'm', 100,
HELPCTX(proxy_command),
- dlg_stdeditbox_handler,
- I(offsetof(Config,proxy_telnet_command)),
- I(sizeof(((Config *)0)->proxy_telnet_command)));
+ conf_editbox_handler,
+ I(CONF_proxy_telnet_command), I(1));
}
/*
ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
NO_SHORTCUT, 2,
HELPCTX(telnet_oldenviron),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, rfc_environ)),
+ conf_radiobutton_handler,
+ I(CONF_rfc_environ),
"BSD (commonplace)", 'b', I(0),
"RFC 1408 (unusual)", 'f', I(1), NULL);
ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
HELPCTX(telnet_passive),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, passive_telnet)),
+ conf_radiobutton_handler,
+ I(CONF_passive_telnet),
"Passive", I(1), "Active", I(0), NULL);
}
ctrl_checkbox(s, "Keyboard sends Telnet special commands", 'k',
HELPCTX(telnet_specialkeys),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,telnet_keyboard)));
+ conf_checkbox_handler,
+ I(CONF_telnet_keyboard));
ctrl_checkbox(s, "Return key sends Telnet New Line instead of ^M",
'm', HELPCTX(telnet_newline),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,telnet_newline)));
+ conf_checkbox_handler,
+ I(CONF_telnet_newline));
}
if (!midsession) {
"Data to send to the server");
ctrl_editbox(s, "Local username:", 'l', 50,
HELPCTX(rlogin_localuser),
- dlg_stdeditbox_handler, I(offsetof(Config,localusername)),
- I(sizeof(((Config *)0)->localusername)));
+ conf_editbox_handler, I(CONF_localusername), I(1));
}
"Data to send to the server");
ctrl_editbox(s, "Remote command:", 'r', 100,
HELPCTX(ssh_command),
- dlg_stdeditbox_handler, I(offsetof(Config,remote_cmd)),
- I(sizeof(((Config *)0)->remote_cmd)));
+ conf_editbox_handler, I(CONF_remote_cmd), I(1));
s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
ctrl_checkbox(s, "Don't start a shell or command at all", 'n',
HELPCTX(ssh_noshell),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,ssh_no_shell)));
+ conf_checkbox_handler,
+ I(CONF_ssh_no_shell));
}
if (!midsession || protcfginfo != 1) {
ctrl_checkbox(s, "Enable compression", 'e',
HELPCTX(ssh_compress),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,compression)));
+ conf_checkbox_handler,
+ I(CONF_compression));
}
if (!midsession) {
ctrl_radiobuttons(s, "Preferred SSH protocol version:", NO_SHORTCUT, 4,
HELPCTX(ssh_protocol),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, sshprot)),
+ conf_radiobutton_handler,
+ I(CONF_sshprot),
"1 only", 'l', I(0),
"1", '1', I(1),
"2", '2', I(2),
ctrl_checkbox(s, "Enable legacy use of single-DES in SSH-2", 'i',
HELPCTX(ssh_ciphers),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,ssh2_des_cbc)));
+ conf_checkbox_handler,
+ I(CONF_ssh2_des_cbc));
}
/*
ctrl_editbox(s, "Max minutes before rekey (0 for no limit)", 't', 20,
HELPCTX(ssh_kex_repeat),
- dlg_stdeditbox_handler,
- I(offsetof(Config,ssh_rekey_time)),
+ conf_editbox_handler,
+ I(CONF_ssh_rekey_time),
I(-1));
ctrl_editbox(s, "Max data before rekey (0 for no limit)", 'x', 20,
HELPCTX(ssh_kex_repeat),
- dlg_stdeditbox_handler,
- I(offsetof(Config,ssh_rekey_data)),
+ conf_editbox_handler,
+ I(CONF_ssh_rekey_data),
I(16));
ctrl_text(s, "(Use 1M for 1 megabyte, 1G for 1 gigabyte etc)",
HELPCTX(ssh_kex_repeat));
s = ctrl_getset(b, "Connection/SSH/Auth", "main", NULL);
ctrl_checkbox(s, "Bypass authentication entirely (SSH-2 only)", 'b',
HELPCTX(ssh_auth_bypass),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,ssh_no_userauth)));
+ conf_checkbox_handler,
+ I(CONF_ssh_no_userauth));
ctrl_checkbox(s, "Display pre-authentication banner (SSH-2 only)",
'd', HELPCTX(ssh_auth_banner),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,ssh_show_banner)));
+ conf_checkbox_handler,
+ I(CONF_ssh_show_banner));
s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
"Authentication methods");
ctrl_checkbox(s, "Attempt authentication using Pageant", 'p',
HELPCTX(ssh_auth_pageant),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,tryagent)));
+ conf_checkbox_handler,
+ I(CONF_tryagent));
ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH-1)", 'm',
HELPCTX(ssh_auth_tis),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,try_tis_auth)));
+ conf_checkbox_handler,
+ I(CONF_try_tis_auth));
ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH-2)",
'i', HELPCTX(ssh_auth_ki),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,try_ki_auth)));
+ conf_checkbox_handler,
+ I(CONF_try_ki_auth));
s = ctrl_getset(b, "Connection/SSH/Auth", "params",
"Authentication parameters");
ctrl_checkbox(s, "Allow agent forwarding", 'f',
HELPCTX(ssh_auth_agentfwd),
- dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
+ conf_checkbox_handler, I(CONF_agentfwd));
ctrl_checkbox(s, "Allow attempted changes of username in SSH-2", NO_SHORTCUT,
HELPCTX(ssh_auth_changeuser),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,change_username)));
+ conf_checkbox_handler,
+ I(CONF_change_username));
ctrl_filesel(s, "Private key file for authentication:", 'k',
FILTER_KEY_FILES, FALSE, "Select private key file",
HELPCTX(ssh_auth_privkey),
- dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
+ conf_filesel_handler, I(CONF_keyfile));
#ifndef NO_GSSAPI
/*
ctrl_checkbox(s, "Attempt GSSAPI authentication (SSH-2 only)",
't', HELPCTX(ssh_gssapi),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,try_gssapi_auth)));
+ conf_checkbox_handler,
+ I(CONF_try_gssapi_auth));
ctrl_checkbox(s, "Allow GSSAPI credential delegation", 'l',
HELPCTX(ssh_gssapi_delegation),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,gssapifwd)));
+ conf_checkbox_handler,
+ I(CONF_gssapifwd));
/*
* GSSAPI library selection.
ctrl_filesel(s, "User-supplied GSSAPI library path:", 's',
FILTER_DYNLIB_FILES, FALSE, "Select library file",
HELPCTX(ssh_gssapi_libraries),
- dlg_stdfilesel_handler,
- I(offsetof(Config, ssh_gss_custom)));
+ conf_filesel_handler,
+ I(CONF_ssh_gss_custom));
}
#endif
}
s = ctrl_getset(b, "Connection/SSH/TTY", "sshtty", NULL);
ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
HELPCTX(ssh_nopty),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,nopty)));
+ conf_checkbox_handler,
+ I(CONF_nopty));
s = ctrl_getset(b, "Connection/SSH/TTY", "ttymodes",
"Terminal modes");
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
ctrl_checkbox(s, "Enable X11 forwarding", 'e',
HELPCTX(ssh_tunnels_x11),
- dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
+ conf_checkbox_handler,I(CONF_x11_forward));
ctrl_editbox(s, "X display location", 'x', 50,
HELPCTX(ssh_tunnels_x11),
- dlg_stdeditbox_handler, I(offsetof(Config,x11_display)),
- I(sizeof(((Config *)0)->x11_display)));
+ conf_editbox_handler, I(CONF_x11_display), I(1));
ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
HELPCTX(ssh_tunnels_x11auth),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, x11_auth)),
+ conf_radiobutton_handler,
+ I(CONF_x11_auth),
"MIT-Magic-Cookie-1", I(X11_MIT),
"XDM-Authorization-1", I(X11_XDM), NULL);
}
"Port forwarding");
ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
HELPCTX(ssh_tunnels_portfwd_localhost),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,lport_acceptall)));
+ conf_checkbox_handler,
+ I(CONF_lport_acceptall));
ctrl_checkbox(s, "Remote ports do the same (SSH-2 only)", 'p',
HELPCTX(ssh_tunnels_portfwd_localhost),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,rport_acceptall)));
+ conf_checkbox_handler,
+ I(CONF_rport_acceptall));
ctrl_columns(s, 3, 55, 20, 25);
c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
"Detection of known bugs in SSH servers");
ctrl_droplist(s, "Chokes on SSH-1 ignore messages", 'i', 20,
HELPCTX(ssh_bugs_ignore1),
- sshbug_handler, I(offsetof(Config,sshbug_ignore1)));
+ sshbug_handler, I(CONF_sshbug_ignore1));
ctrl_droplist(s, "Refuses all SSH-1 password camouflage", 's', 20,
HELPCTX(ssh_bugs_plainpw1),
- sshbug_handler, I(offsetof(Config,sshbug_plainpw1)));
+ sshbug_handler, I(CONF_sshbug_plainpw1));
ctrl_droplist(s, "Chokes on SSH-1 RSA authentication", 'r', 20,
HELPCTX(ssh_bugs_rsa1),
- sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
+ sshbug_handler, I(CONF_sshbug_rsa1));
ctrl_droplist(s, "Chokes on SSH-2 ignore messages", '2', 20,
HELPCTX(ssh_bugs_ignore2),
- sshbug_handler, I(offsetof(Config,sshbug_ignore2)));
+ sshbug_handler, I(CONF_sshbug_ignore2));
ctrl_droplist(s, "Miscomputes SSH-2 HMAC keys", 'm', 20,
HELPCTX(ssh_bugs_hmac2),
- sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
+ sshbug_handler, I(CONF_sshbug_hmac2));
ctrl_droplist(s, "Miscomputes SSH-2 encryption keys", 'e', 20,
HELPCTX(ssh_bugs_derivekey2),
- sshbug_handler, I(offsetof(Config,sshbug_derivekey2)));
+ sshbug_handler, I(CONF_sshbug_derivekey2));
ctrl_droplist(s, "Requires padding on SSH-2 RSA signatures", 'p', 20,
HELPCTX(ssh_bugs_rsapad2),
- sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
+ sshbug_handler, I(CONF_sshbug_rsapad2));
ctrl_droplist(s, "Misuses the session ID in SSH-2 PK auth", 'n', 20,
HELPCTX(ssh_bugs_pksessid2),
- sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));
+ sshbug_handler, I(CONF_sshbug_pksessid2));
ctrl_droplist(s, "Handles SSH-2 key re-exchange badly", 'k', 20,
HELPCTX(ssh_bugs_rekey2),
- sshbug_handler, I(offsetof(Config,sshbug_rekey2)));
+ sshbug_handler, I(CONF_sshbug_rekey2));
ctrl_droplist(s, "Ignores SSH-2 maximum packet size", 'x', 20,
HELPCTX(ssh_bugs_maxpkt2),
- sshbug_handler, I(offsetof(Config,sshbug_maxpkt2)));
+ sshbug_handler, I(CONF_sshbug_maxpkt2));
}
}
}
outbuf[2] = 0x04; /* Response */
outbuf[3] = 0x10; /* Length */
hmacmd5_chap(data, p->chap_current_datalen,
- p->cfg.proxy_password, &outbuf[4]);
+ conf_get_str(p->conf, CONF_proxy_password),
+ &outbuf[4]);
sk_write(p->sub_socket, (char *)outbuf, 20);
break;
case 0x11:
int proxy_socks5_selectchap(Proxy_Socket p)
{
- if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {
+ char *username = conf_get_str(p->conf, CONF_proxy_username);
+ char *password = conf_get_str(p->conf, CONF_proxy_password);
+ if (username[0] || password[0]) {
char chapbuf[514];
int ulen;
chapbuf[0] = '\x01'; /* Version */
chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
chapbuf[5] = '\x02'; /* Second attribute - username */
- ulen = strlen(p->cfg.proxy_username);
+ ulen = strlen(username);
if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;
chapbuf[6] = ulen;
- memcpy(chapbuf+7, p->cfg.proxy_username, ulen);
+ memcpy(chapbuf+7, username, ulen);
sk_write(p->sub_socket, chapbuf, ulen + 7);
p->chap_num_attributes = 0;
}
sfree(ctrl);
}
-
-void dlg_stdradiobutton_handler(union control *ctrl, void *dlg,
- void *data, int event)
-{
- int button;
- /*
- * For a standard radio button set, the context parameter gives
- * offsetof(targetfield, Config), and the extra data per button
- * gives the value the target field should take if that button
- * is the one selected.
- */
- if (event == EVENT_REFRESH) {
- for (button = 0; button < ctrl->radio.nbuttons; button++)
- if (*(int *)ATOFFSET(data, ctrl->radio.context.i) ==
- ctrl->radio.buttondata[button].i)
- break;
- /* We expected that `break' to happen, in all circumstances. */
- assert(button < ctrl->radio.nbuttons);
- dlg_radiobutton_set(ctrl, dlg, button);
- } else if (event == EVENT_VALCHANGE) {
- button = dlg_radiobutton_get(ctrl, dlg);
- assert(button >= 0 && button < ctrl->radio.nbuttons);
- *(int *)ATOFFSET(data, ctrl->radio.context.i) =
- ctrl->radio.buttondata[button].i;
- }
-}
-
-void dlg_stdcheckbox_handler(union control *ctrl, void *dlg,
- void *data, int event)
-{
- int offset, invert;
-
- /*
- * For a standard checkbox, the context parameter gives
- * offsetof(targetfield, Config), optionally ORed with
- * CHECKBOX_INVERT.
- */
- offset = ctrl->checkbox.context.i;
- if (offset & CHECKBOX_INVERT) {
- offset &= ~CHECKBOX_INVERT;
- invert = 1;
- } else
- invert = 0;
-
- /*
- * C lacks a logical XOR, so the following code uses the idiom
- * (!a ^ !b) to obtain the logical XOR of a and b. (That is, 1
- * iff exactly one of a and b is nonzero, otherwise 0.)
- */
-
- if (event == EVENT_REFRESH) {
- dlg_checkbox_set(ctrl,dlg, (!*(int *)ATOFFSET(data,offset) ^ !invert));
- } else if (event == EVENT_VALCHANGE) {
- *(int *)ATOFFSET(data, offset) = !dlg_checkbox_get(ctrl,dlg) ^ !invert;
- }
-}
-
-void dlg_stdeditbox_handler(union control *ctrl, void *dlg,
- void *data, int event)
-{
- /*
- * The standard edit-box handler expects the main `context'
- * field to contain the `offsetof' a field in the structure
- * pointed to by `data'. The secondary `context2' field
- * indicates the type of this field:
- *
- * - if context2 > 0, the field is a char array and context2
- * gives its size.
- * - if context2 == -1, the field is an int and the edit box
- * is numeric.
- * - if context2 < -1, the field is an int and the edit box is
- * _floating_, and (-context2) gives the scale. (E.g. if
- * context2 == -1000, then typing 1.2 into the box will set
- * the field to 1200.)
- */
- int offset = ctrl->editbox.context.i;
- int length = ctrl->editbox.context2.i;
-
- if (length > 0) {
- char *field = (char *)ATOFFSET(data, offset);
- if (event == EVENT_REFRESH) {
- dlg_editbox_set(ctrl, dlg, field);
- } else if (event == EVENT_VALCHANGE) {
- dlg_editbox_get(ctrl, dlg, field, length);
- }
- } else if (length < 0) {
- int *field = (int *)ATOFFSET(data, offset);
- char data[80];
- if (event == EVENT_REFRESH) {
- if (length == -1)
- sprintf(data, "%d", *field);
- else
- sprintf(data, "%g", (double)*field / (double)(-length));
- dlg_editbox_set(ctrl, dlg, data);
- } else if (event == EVENT_VALCHANGE) {
- dlg_editbox_get(ctrl, dlg, data, lenof(data));
- if (length == -1)
- *field = atoi(data);
- else
- *field = (int)((-length) * atof(data));
- }
- }
-}
-
-void dlg_stdfilesel_handler(union control *ctrl, void *dlg,
- void *data, int event)
-{
- /*
- * The standard file-selector handler expects the `context'
- * field to contain the `offsetof' a Filename field in the
- * structure pointed to by `data'.
- */
- int offset = ctrl->fileselect.context.i;
-
- if (event == EVENT_REFRESH) {
- dlg_filesel_set(ctrl, dlg, *(Filename *)ATOFFSET(data, offset));
- } else if (event == EVENT_VALCHANGE) {
- dlg_filesel_get(ctrl, dlg, (Filename *)ATOFFSET(data, offset));
- }
-}
-
-void dlg_stdfontsel_handler(union control *ctrl, void *dlg,
- void *data, int event)
-{
- /*
- * The standard file-selector handler expects the `context'
- * field to contain the `offsetof' a FontSpec field in the
- * structure pointed to by `data'.
- */
- int offset = ctrl->fontselect.context.i;
-
- if (event == EVENT_REFRESH) {
- dlg_fontsel_set(ctrl, dlg, *(FontSpec *)ATOFFSET(data, offset));
- } else if (event == EVENT_VALCHANGE) {
- dlg_fontsel_get(ctrl, dlg, (FontSpec *)ATOFFSET(data, offset));
- }
-}
*
* The `data' parameter points to the writable data being
* modified as a result of the configuration activity; for
- * example, the PuTTY `Config' structure, although not
+ * example, the PuTTY `Conf' structure, although not
* necessarily.
*
* The `dlg' parameter is passed back to the platform-
union control *ctrl_tabdelay(struct controlset *, union control *);
/*
- * Standard handler routines to cover most of the common cases in
- * the config box.
- */
-/*
- * The standard radio-button handler expects the main `context'
- * field to contain the `offsetof' of an int field in the structure
- * pointed to by `data', and expects each of the individual button
- * data to give a value for that int field.
- */
-void dlg_stdradiobutton_handler(union control *ctrl, void *dlg,
- void *data, int event);
-/*
- * The standard checkbox handler expects the main `context' field
- * to contain the `offsetof' an int field in the structure pointed
- * to by `data', optionally ORed with CHECKBOX_INVERT to indicate
- * that the sense of the datum is opposite to the sense of the
- * checkbox.
- */
-#define CHECKBOX_INVERT (1<<30)
-void dlg_stdcheckbox_handler(union control *ctrl, void *dlg,
- void *data, int event);
-/*
- * The standard edit-box handler expects the main `context' field
- * to contain the `offsetof' a field in the structure pointed to by
- * `data'. The secondary `context2' field indicates the type of
- * this field:
- *
- * - if context2 > 0, the field is a char array and context2 gives
- * its size.
- * - if context2 == -1, the field is an int and the edit box is
- * numeric.
- * - if context2 < -1, the field is an int and the edit box is
- * _floating_, and (-context2) gives the scale. (E.g. if
- * context2 == -1000, then typing 1.2 into the box will set the
- * field to 1200.)
- */
-void dlg_stdeditbox_handler(union control *ctrl, void *dlg,
- void *data, int event);
-/*
* The standard file-selector handler expects the main `context'
* field to contain the `offsetof' a Filename field in the
* structure pointed to by `data'.
void dlg_checkbox_set(union control *ctrl, void *dlg, int checked);
int dlg_checkbox_get(union control *ctrl, void *dlg);
void dlg_editbox_set(union control *ctrl, void *dlg, char const *text);
-void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length);
+char *dlg_editbox_get(union control *ctrl, void *dlg); /* result must be freed by caller */
/* The `listbox' functions can also apply to combo boxes. */
void dlg_listbox_clear(union control *ctrl, void *dlg);
void dlg_listbox_del(union control *ctrl, void *dlg, int index);
#include "terminal.h"
#include "ldisc.h"
-#define ECHOING (ldisc->cfg->localecho == FORCE_ON || \
- (ldisc->cfg->localecho == AUTO && \
+#define ECHOING (ldisc->localecho == FORCE_ON || \
+ (ldisc->localecho == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \
term_ldisc(ldisc->term, LD_ECHO))))
-#define EDITING (ldisc->cfg->localedit == FORCE_ON || \
- (ldisc->cfg->localedit == AUTO && \
+#define EDITING (ldisc->localedit == FORCE_ON || \
+ (ldisc->localedit == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \
term_ldisc(ldisc->term, LD_EDIT))))
#define CTRL(x) (x^'@')
#define KCTRL(x) ((x^'@') | 0x100)
-void *ldisc_create(Config *mycfg, Terminal *term,
+void *ldisc_create(Conf *conf, Terminal *term,
Backend *back, void *backhandle,
void *frontend)
{
ldisc->bufsiz = 0;
ldisc->quotenext = 0;
- ldisc->cfg = mycfg;
ldisc->back = back;
ldisc->backhandle = backhandle;
ldisc->term = term;
ldisc->frontend = frontend;
+ ldisc_configure(ldisc, conf);
+
/* Link ourselves into the backend and the terminal */
if (term)
term->ldisc = ldisc;
return ldisc;
}
+void ldisc_configure(void *handle, Conf *conf)
+{
+ Ldisc ldisc = (Ldisc) handle;
+
+ ldisc->telnet_keyboard = conf_get_int(conf, CONF_telnet_keyboard);
+ ldisc->telnet_newline = conf_get_int(conf, CONF_telnet_newline);
+ ldisc->protocol = conf_get_int(conf, CONF_protocol);
+ ldisc->localecho = conf_get_int(conf, CONF_localecho);
+ ldisc->localedit = conf_get_int(conf, CONF_localedit);
+}
+
void ldisc_free(void *handle)
{
Ldisc ldisc = (Ldisc) handle;
* configured telnet specials off! This breaks
* talkers otherwise.
*/
- if (!ldisc->cfg->telnet_keyboard)
+ if (!ldisc->telnet_keyboard)
goto default_case;
if (c == CTRL('C'))
ldisc->back->special(ldisc->backhandle, TS_IP);
* default clause because of the break.
*/
case CTRL('J'):
- if (ldisc->cfg->protocol == PROT_RAW &&
+ if (ldisc->protocol == PROT_RAW &&
ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') {
if (ECHOING)
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
case KCTRL('M'): /* send with newline */
if (ldisc->buflen > 0)
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
- if (ldisc->cfg->protocol == PROT_RAW)
+ if (ldisc->protocol == PROT_RAW)
ldisc->back->send(ldisc->backhandle, "\r\n", 2);
- else if (ldisc->cfg->protocol == PROT_TELNET && ldisc->cfg->telnet_newline)
+ else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL);
else
ldisc->back->send(ldisc->backhandle, "\r", 1);
if (len > 0) {
if (ECHOING)
c_write(ldisc, buf, len);
- if (keyflag && ldisc->cfg->protocol == PROT_TELNET && len == 1) {
+ if (keyflag && ldisc->protocol == PROT_TELNET && len == 1) {
switch (buf[0]) {
case CTRL('M'):
- if (ldisc->cfg->protocol == PROT_TELNET && ldisc->cfg->telnet_newline)
+ if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL);
else
ldisc->back->send(ldisc->backhandle, "\r", 1);
break;
case CTRL('?'):
case CTRL('H'):
- if (ldisc->cfg->telnet_keyboard) {
+ if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_EC);
break;
}
case CTRL('C'):
- if (ldisc->cfg->telnet_keyboard) {
+ if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_IP);
break;
}
case CTRL('Z'):
- if (ldisc->cfg->telnet_keyboard) {
+ if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_SUSP);
break;
}
typedef struct ldisc_tag {
Terminal *term;
Backend *back;
- Config *cfg;
void *backhandle;
void *frontend;
+ /*
+ * Values cached out of conf.
+ */
+ int telnet_keyboard, telnet_newline, protocol, localecho, localedit;
+
char *buf;
int buflen, bufsiz, quotenext;
} *Ldisc;
bufchain queue;
Filename currlogfilename;
void *frontend;
- Config cfg;
+ Conf *conf;
+ int logtype; /* cached out of conf */
};
static void xlatlognam(Filename *d, Filename s, char *hostname, struct tm *tm);
*/
void logflush(void *handle) {
struct LogContext *ctx = (struct LogContext *)handle;
- if (ctx->cfg.logtype > 0)
+ if (ctx->logtype > 0)
if (ctx->state == L_OPEN)
fflush(ctx->lgfp);
}
ctx->state == L_ERROR ?
(mode == 0 ? "Disabled writing" : "Error writing") :
(mode == 1 ? "Appending" : "Writing new"),
- (ctx->cfg.logtype == LGTYP_ASCII ? "ASCII" :
- ctx->cfg.logtype == LGTYP_DEBUG ? "raw" :
- ctx->cfg.logtype == LGTYP_PACKETS ? "SSH packets" :
- ctx->cfg.logtype == LGTYP_SSHRAW ? "SSH raw data" :
+ (ctx->logtype == LGTYP_ASCII ? "ASCII" :
+ ctx->logtype == LGTYP_DEBUG ? "raw" :
+ ctx->logtype == LGTYP_PACKETS ? "SSH packets" :
+ ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" :
"unknown"),
filename_to_str(&ctx->currlogfilename));
logevent(ctx->frontend, event);
if (ctx->state != L_CLOSED)
return;
- if (!ctx->cfg.logtype)
+ if (!ctx->logtype)
return;
tm = ltime();
/* substitute special codes in file name */
- xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm);
+ xlatlognam(&ctx->currlogfilename,
+ *conf_get_filename(ctx->conf, CONF_logfilename),
+ conf_get_str(ctx->conf, CONF_host), &tm);
ctx->lgfp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */
if (ctx->lgfp) {
+ int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
fclose(ctx->lgfp);
- if (ctx->cfg.logxfovr != LGXF_ASK) {
- mode = ((ctx->cfg.logxfovr == LGXF_OVR) ? 2 : 1);
+ if (logxfovr != LGXF_ASK) {
+ mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
} else
mode = askappend(ctx->frontend, ctx->currlogfilename,
logfopen_callback, ctx);
void logtraffic(void *handle, unsigned char c, int logmode)
{
struct LogContext *ctx = (struct LogContext *)handle;
- if (ctx->cfg.logtype > 0) {
- if (ctx->cfg.logtype == logmode)
+ if (ctx->logtype > 0) {
+ if (ctx->logtype == logmode)
logwrite(ctx, &c, 1);
}
}
/* If we don't have a context yet (eg winnet.c init) then skip entirely */
if (!ctx)
return;
- if (ctx->cfg.logtype != LGTYP_PACKETS &&
- ctx->cfg.logtype != LGTYP_SSHRAW)
+ if (ctx->logtype != LGTYP_PACKETS &&
+ ctx->logtype != LGTYP_SSHRAW)
return;
logprintf(ctx, "Event Log: %s\r\n", event);
logflush(ctx);
int p = 0, b = 0, omitted = 0;
int output_pos = 0; /* NZ if pending output in dumpdata */
- if (!(ctx->cfg.logtype == LGTYP_SSHRAW ||
- (ctx->cfg.logtype == LGTYP_PACKETS && texttype)))
+ if (!(ctx->logtype == LGTYP_SSHRAW ||
+ (ctx->logtype == LGTYP_PACKETS && texttype)))
return;
/* Packet header. */
logflush(ctx);
}
-void *log_init(void *frontend, Config *cfg)
+void *log_init(void *frontend, Conf *conf)
{
struct LogContext *ctx = snew(struct LogContext);
ctx->lgfp = NULL;
ctx->state = L_CLOSED;
ctx->frontend = frontend;
- ctx->cfg = *cfg; /* STRUCTURE COPY */
+ ctx->conf = conf_copy(conf);
+ ctx->logtype = conf_get_int(ctx->conf, CONF_logtype);
bufchain_init(&ctx->queue);
return ctx;
}
sfree(ctx);
}
-void log_reconfig(void *handle, Config *cfg)
+void log_reconfig(void *handle, Conf *conf)
{
struct LogContext *ctx = (struct LogContext *)handle;
int reset_logging;
- if (!filename_equal(ctx->cfg.logfilename, cfg->logfilename) ||
- ctx->cfg.logtype != cfg->logtype)
+ if (!filename_equal(*conf_get_filename(ctx->conf, CONF_logfilename),
+ *conf_get_filename(conf, CONF_logfilename)) ||
+ conf_get_int(ctx->conf, CONF_logtype) !=
+ conf_get_int(conf, CONF_logtype))
reset_logging = TRUE;
else
reset_logging = FALSE;
if (reset_logging)
logfclose(ctx);
- ctx->cfg = *cfg; /* STRUCTURE COPY */
+ conf_free(ctx->conf);
+ ctx->conf = conf_copy(conf);
+
+ ctx->logtype = conf_get_int(ctx->conf, CONF_logtype);
if (reset_logging)
logfopen(ctx);
Other ways in which the port is currently unfinished include:
+Bit rot
+-------
+
+ - the conversion of the old fixed-size 'Config' structure to the
+ new dynamic 'Conf' was never applied to this directory
+
+ - probably other things are out of date too; it would need some
+ work to make it compile again
+
Missing terminal window features
--------------------------------
#endif /* def DEBUG */
/*
- * Determine whether or not a Config structure represents a session
- * which can sensibly be launched right now.
+ * Determine whether or not a Conf represents a session which can
+ * sensibly be launched right now.
*/
-int cfg_launchable(const Config *cfg)
+int conf_launchable(Conf *conf)
{
- if (cfg->protocol == PROT_SERIAL)
- return cfg->serline[0] != 0;
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
+ return conf_get_str(conf, CONF_serline)[0] != 0;
else
- return cfg->host[0] != 0;
+ return conf_get_str(conf, CONF_host)[0] != 0;
}
-char const *cfg_dest(const Config *cfg)
+char const *conf_dest(Conf *conf)
{
- if (cfg->protocol == PROT_SERIAL)
- return cfg->serline;
+ if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
+ return conf_get_str(conf, CONF_serline);
else
- return cfg->host;
+ return conf_get_str(conf, CONF_host);
}
#ifndef DONE_TYPEDEFS
#define DONE_TYPEDEFS
-typedef struct config_tag Config;
+typedef struct conf_tag Conf;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal;
#endif
Socket new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg);
+ Plug plug, Conf *conf);
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
- const Config *cfg, int addressfamily);
+ Conf *conf, int addressfamily);
SockAddr name_lookup(char *host, int port, char **canonicalname,
- const Config *cfg, int addressfamily);
+ Conf *conf, int addressfamily);
/* platform-dependent callback from new_connection() */
/* (same caveat about addr as new_connection()) */
Socket platform_new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg);
+ Plug plug, Conf *conf);
/* socket functions */
}
}
-Pinger pinger_new(Config *cfg, Backend *back, void *backhandle)
+Pinger pinger_new(Conf *conf, Backend *back, void *backhandle)
{
Pinger pinger = snew(struct pinger_tag);
- pinger->interval = cfg->ping_interval;
+ pinger->interval = conf_get_int(conf, CONF_ping_interval);
pinger->pending = FALSE;
pinger->back = back;
pinger->backhandle = backhandle;
return pinger;
}
-void pinger_reconfig(Pinger pinger, Config *oldcfg, Config *newcfg)
+void pinger_reconfig(Pinger pinger, Conf *oldconf, Conf *newconf)
{
- if (oldcfg->ping_interval != newcfg->ping_interval) {
- pinger->interval = newcfg->ping_interval;
+ int newinterval = conf_get_int(newconf, CONF_ping_interval);
+ if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) {
+ pinger->interval = newinterval;
pinger_schedule(pinger);
}
}
* Called when receiving a PORT OPEN from the server
*/
const char *pfd_newconnect(Socket *s, char *hostname, int port,
- void *c, const Config *cfg, int addressfamily)
+ void *c, Conf *conf, int addressfamily)
{
static const struct plug_function_table fn_table = {
pfd_log,
/*
* Try to find host.
*/
- addr = name_lookup(hostname, port, &dummy_realhost, cfg, addressfamily);
+ addr = name_lookup(hostname, port, &dummy_realhost, conf, addressfamily);
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
pr->dynamic = 0;
pr->s = *s = new_connection(addr, dummy_realhost, port,
- 0, 1, 0, 0, (Plug) pr, cfg);
+ 0, 1, 0, 0, (Plug) pr, conf);
if ((err = sk_socket_error(*s)) != NULL) {
sfree(pr);
return err;
sets up a listener on the local machine on (srcaddr:)port
*/
const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
- int port, void *backhandle, const Config *cfg,
+ int port, void *backhandle, Conf *conf,
void **sockdata, int address_family)
{
static const struct plug_function_table fn_table = {
pr->backhandle = backhandle;
pr->s = s = new_listener(srcaddr, port, (Plug) pr,
- !cfg->lport_acceptall, cfg, address_family);
+ !conf_get_int(conf, CONF_lport_acceptall),
+ conf, address_family);
if ((err = sk_socket_error(s)) != NULL) {
sfree(pr);
return err;
Socket platform_new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg)
+ Plug plug, Conf *conf)
{
return NULL;
}
#include "network.h"
#include "proxy.h"
-#define do_proxy_dns(cfg) \
- (cfg->proxy_dns == FORCE_ON || \
- (cfg->proxy_dns == AUTO && cfg->proxy_type != PROXY_SOCKS4))
+#define do_proxy_dns(conf) \
+ (conf_get_int(conf, CONF_proxy_dns) == FORCE_ON || \
+ (conf_get_int(conf, CONF_proxy_dns) == AUTO && \
+ conf_get_int(conf, CONF_proxy_type) != PROXY_SOCKS4))
/*
* Call this when proxy negotiation is complete, so that this
* it will only check the host name.
*/
static int proxy_for_destination (SockAddr addr, char *hostname, int port,
- const Config *cfg)
+ Conf *conf)
{
int s = 0, e = 0;
char hostip[64];
* Check the host name and IP against the hard-coded
* representations of `localhost'.
*/
- if (!cfg->even_proxy_localhost &&
+ if (!conf_get_int(conf, CONF_even_proxy_localhost) &&
(sk_hostname_is_local(hostname) ||
(addr && sk_address_is_local(addr))))
return 0; /* do not proxy */
hostname_len = strlen(hostname);
- exclude_list = cfg->proxy_exclude_list;
+ exclude_list = conf_get_str(conf, CONF_proxy_exclude_list);
/* now parse the exclude list, and see if either our IP
* or hostname matches anything in it.
}
SockAddr name_lookup(char *host, int port, char **canonicalname,
- const Config *cfg, int addressfamily)
+ Conf *conf, int addressfamily)
{
- if (cfg->proxy_type != PROXY_NONE &&
- do_proxy_dns(cfg) &&
- proxy_for_destination(NULL, host, port, cfg)) {
+ if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
+ do_proxy_dns(conf) &&
+ proxy_for_destination(NULL, host, port, conf)) {
*canonicalname = dupstr(host);
return sk_nonamelookup(host);
}
Socket new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg)
+ Plug plug, Conf *conf)
{
static const struct socket_function_table socket_fn_table = {
sk_proxy_plug,
plug_proxy_accepting
};
- if (cfg->proxy_type != PROXY_NONE &&
- proxy_for_destination(addr, hostname, port, cfg))
+ if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
+ proxy_for_destination(addr, hostname, port, conf))
{
Proxy_Socket ret;
Proxy_Plug pplug;
SockAddr proxy_addr;
char *proxy_canonical_name;
Socket sret;
+ int type;
if ((sret = platform_new_connection(addr, hostname, port, privport,
oobinline, nodelay, keepalive,
- plug, cfg)) !=
+ plug, conf)) !=
NULL)
return sret;
ret = snew(struct Socket_proxy_tag);
ret->fn = &socket_fn_table;
- ret->cfg = *cfg; /* STRUCTURE COPY */
+ ret->conf = conf_copy(conf);
ret->plug = plug;
ret->remote_addr = addr; /* will need to be freed on close */
ret->remote_port = port;
ret->sub_socket = NULL;
ret->state = PROXY_STATE_NEW;
ret->negotiate = NULL;
-
- if (cfg->proxy_type == PROXY_HTTP) {
+
+ type = conf_get_int(conf, CONF_proxy_type);
+ if (type == PROXY_HTTP) {
ret->negotiate = proxy_http_negotiate;
- } else if (cfg->proxy_type == PROXY_SOCKS4) {
+ } else if (type == PROXY_SOCKS4) {
ret->negotiate = proxy_socks4_negotiate;
- } else if (cfg->proxy_type == PROXY_SOCKS5) {
+ } else if (type == PROXY_SOCKS5) {
ret->negotiate = proxy_socks5_negotiate;
- } else if (cfg->proxy_type == PROXY_TELNET) {
+ } else if (type == PROXY_TELNET) {
ret->negotiate = proxy_telnet_negotiate;
} else {
ret->error = "Proxy error: Unknown proxy method";
pplug->proxy_socket = ret;
/* look-up proxy */
- proxy_addr = sk_namelookup(cfg->proxy_host,
- &proxy_canonical_name, cfg->addressfamily);
+ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host),
+ &proxy_canonical_name,
+ conf_get_int(conf, CONF_addressfamily));
if (sk_addr_error(proxy_addr) != NULL) {
ret->error = "Proxy error: Unable to resolve proxy host name";
return (Socket)ret;
/* create the actual socket we will be using,
* connected to our proxy server and port.
*/
- ret->sub_socket = sk_new(proxy_addr, cfg->proxy_port,
+ ret->sub_socket = sk_new(proxy_addr,
+ conf_get_int(conf, CONF_proxy_port),
privport, oobinline,
nodelay, keepalive, (Plug) pplug);
if (sk_socket_error(ret->sub_socket) != NULL)
}
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
- const Config *cfg, int addressfamily)
+ Conf *conf, int addressfamily)
{
/* TODO: SOCKS (and potentially others) support inbound
* TODO: connections via the proxy. support them.
* request
*/
char *buf, dest[512];
+ char *username, *password;
sk_getaddr(p->remote_addr, dest, lenof(dest));
sk_write(p->sub_socket, buf, strlen(buf));
sfree(buf);
- if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {
- char buf[sizeof(p->cfg.proxy_username)+sizeof(p->cfg.proxy_password)];
- char buf2[sizeof(buf)*4/3 + 100];
+ username = conf_get_str(p->conf, CONF_proxy_username);
+ password = conf_get_str(p->conf, CONF_proxy_password);
+ if (username[0] || password[0]) {
+ char *buf, *buf2;
int i, j, len;
- sprintf(buf, "%s:%s", p->cfg.proxy_username, p->cfg.proxy_password);
+ buf = dupprintf("%s:%s", username, password);
len = strlen(buf);
+ buf2 = snewn(len * 4 / 3 + 100, char);
sprintf(buf2, "Proxy-Authorization: Basic ");
for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)
base64_encode_atom((unsigned char *)(buf+i),
(len-i > 3 ? 3 : len-i), buf2+j);
strcpy(buf2+j, "\r\n");
sk_write(p->sub_socket, buf2, strlen(buf2));
+ sfree(buf);
+ sfree(buf2);
}
sk_write(p->sub_socket, "\r\n", 2);
int length, type, namelen;
char *command, addr[4], hostname[512];
+ char *username;
type = sk_addrtype(p->remote_addr);
if (type == ADDRTYPE_IPV6) {
addr[3] = 1;
}
- length = strlen(p->cfg.proxy_username) + namelen + 9;
+ username = conf_get_str(p->conf, CONF_proxy_username);
+ length = strlen(username) + namelen + 9;
command = snewn(length, char);
- strcpy(command + 8, p->cfg.proxy_username);
+ strcpy(command + 8, username);
command[0] = 4; /* version 4 */
command[1] = 1; /* CONNECT command */
memcpy(command + 4, addr, 4);
/* hostname */
- memcpy(command + 8 + strlen(p->cfg.proxy_username) + 1,
+ memcpy(command + 8 + strlen(username) + 1,
hostname, namelen);
sk_write(p->sub_socket, command, length);
+ sfree(username);
sfree(command);
p->state = 1;
*/
char command[5];
+ char *username, *password;
int len;
command[0] = 5; /* version 5 */
- if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {
+ username = conf_get_str(p->conf, CONF_proxy_username);
+ password = conf_get_str(p->conf, CONF_proxy_password);
+ if (username[0] || password[0]) {
command[2] = 0x00; /* no authentication */
len = 3;
proxy_socks5_offerencryptedauth (command, &len);
}
if (p->state == 5) {
- if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {
- char userpwbuf[514];
+ char *username = conf_get_str(p->conf, CONF_proxy_username);
+ char *password = conf_get_str(p->conf, CONF_proxy_password);
+ if (username[0] || password[0]) {
+ char userpwbuf[255 + 255 + 3];
int ulen, plen;
- ulen = strlen(p->cfg.proxy_username);
+ ulen = strlen(username);
if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;
- plen = strlen(p->cfg.proxy_password);
+ plen = strlen(password);
if (plen > 255) plen = 255; if (plen < 1) plen = 1;
userpwbuf[0] = 1; /* version number of subnegotiation */
userpwbuf[1] = ulen;
- memcpy(userpwbuf+2, p->cfg.proxy_username, ulen);
+ memcpy(userpwbuf+2, username, ulen);
userpwbuf[ulen+2] = plen;
- memcpy(userpwbuf+ulen+3, p->cfg.proxy_password, plen);
+ memcpy(userpwbuf+ulen+3, password, plen);
sk_write(p->sub_socket, userpwbuf, ulen + plen + 3);
p->state = 7;
} else
* standardised or at all well-defined.)
*/
-char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
+char *format_telnet_command(SockAddr addr, int port, Conf *conf)
{
+ char *fmt = conf_get_str(conf, CONF_proxy_telnet_command);
char *ret = NULL;
int retlen = 0, retsize = 0;
int so = 0, eo = 0;
* %%, %host, %port, %user, and %pass
*/
- while (cfg->proxy_telnet_command[eo] != 0) {
+ while (fmt[eo] != 0) {
/* scan forward until we hit end-of-line,
* or an escape character (\ or %) */
- while (cfg->proxy_telnet_command[eo] != 0 &&
- cfg->proxy_telnet_command[eo] != '%' &&
- cfg->proxy_telnet_command[eo] != '\\') eo++;
+ while (fmt[eo] != 0 && fmt[eo] != '%' && fmt[eo] != '\\')
+ eo++;
/* if we hit eol, break out of our escaping loop */
- if (cfg->proxy_telnet_command[eo] == 0) break;
+ if (fmt[eo] == 0) break;
/* if there was any unescaped text before the escape
* character, send that now */
if (eo != so) {
ENSURE(eo - so);
- memcpy(ret + retlen, cfg->proxy_telnet_command + so, eo - so);
+ memcpy(ret + retlen, fmt + so, eo - so);
retlen += eo - so;
}
/* if the escape character was the last character of
* the line, we'll just stop and send it. */
- if (cfg->proxy_telnet_command[eo] == 0) break;
+ if (fmt[eo] == 0) break;
- if (cfg->proxy_telnet_command[so] == '\\') {
+ if (fmt[so] == '\\') {
/* we recognize \\, \%, \r, \n, \t, \x??.
* anything else, we just send unescaped (including the \).
*/
- switch (cfg->proxy_telnet_command[eo]) {
+ switch (fmt[eo]) {
case '\\':
ENSURE(1);
for (;;) {
eo++;
- if (cfg->proxy_telnet_command[eo] >= '0' &&
- cfg->proxy_telnet_command[eo] <= '9')
- v += cfg->proxy_telnet_command[eo] - '0';
- else if (cfg->proxy_telnet_command[eo] >= 'a' &&
- cfg->proxy_telnet_command[eo] <= 'f')
- v += cfg->proxy_telnet_command[eo] - 'a' + 10;
- else if (cfg->proxy_telnet_command[eo] >= 'A' &&
- cfg->proxy_telnet_command[eo] <= 'F')
- v += cfg->proxy_telnet_command[eo] - 'A' + 10;
+ if (fmt[eo] >= '0' && fmt[eo] <= '9')
+ v += fmt[eo] - '0';
+ else if (fmt[eo] >= 'a' && fmt[eo] <= 'f')
+ v += fmt[eo] - 'a' + 10;
+ else if (fmt[eo] >= 'A' && fmt[eo] <= 'F')
+ v += fmt[eo] - 'A' + 10;
else {
/* non hex character, so we abort and just
* send the whole thing unescaped (including \x)
default:
ENSURE(2);
- memcpy(ret+retlen, cfg->proxy_telnet_command + so, 2);
+ memcpy(ret+retlen, fmt + so, 2);
retlen += 2;
eo++;
break;
* unescaped (including the %).
*/
- if (cfg->proxy_telnet_command[eo] == '%') {
+ if (fmt[eo] == '%') {
ENSURE(1);
ret[retlen++] = '%';
eo++;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "host", 4) == 0) {
+ else if (strnicmp(fmt + eo, "host", 4) == 0) {
char dest[512];
int destlen;
sk_getaddr(addr, dest, lenof(dest));
retlen += destlen;
eo += 4;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "port", 4) == 0) {
+ else if (strnicmp(fmt + eo, "port", 4) == 0) {
char portstr[8], portlen;
portlen = sprintf(portstr, "%i", port);
ENSURE(portlen);
retlen += portlen;
eo += 4;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "user", 4) == 0) {
- int userlen = strlen(cfg->proxy_username);
+ else if (strnicmp(fmt + eo, "user", 4) == 0) {
+ char *username = conf_get_str(conf, CONF_proxy_username);
+ int userlen = strlen(username);
ENSURE(userlen);
- memcpy(ret+retlen, cfg->proxy_username, userlen);
+ memcpy(ret+retlen, username, userlen);
retlen += userlen;
eo += 4;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "pass", 4) == 0) {
- int passlen = strlen(cfg->proxy_password);
+ else if (strnicmp(fmt + eo, "pass", 4) == 0) {
+ char *password = conf_get_str(conf, CONF_proxy_password);
+ int passlen = strlen(password);
ENSURE(passlen);
- memcpy(ret+retlen, cfg->proxy_password, passlen);
+ memcpy(ret+retlen, password, passlen);
retlen += passlen;
eo += 4;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "proxyhost", 9) == 0) {
- int phlen = strlen(cfg->proxy_host);
+ else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) {
+ char *host = conf_get_str(conf, CONF_proxy_host);
+ int phlen = strlen(host);
ENSURE(phlen);
- memcpy(ret+retlen, cfg->proxy_host, phlen);
+ memcpy(ret+retlen, host, phlen);
retlen += phlen;
eo += 9;
}
- else if (strnicmp(cfg->proxy_telnet_command + eo,
- "proxyport", 9) == 0) {
+ else if (strnicmp(fmt + eo, "proxyport", 9) == 0) {
+ int port = conf_get_int(conf, CONF_proxy_port);
char pport[50];
int pplen;
- sprintf(pport, "%d", cfg->proxy_port);
+ sprintf(pport, "%d", port);
pplen = strlen(pport);
ENSURE(pplen);
memcpy(ret+retlen, pport, pplen);
/* if there is any unescaped text at the end of the line, send it */
if (eo != so) {
ENSURE(eo - so);
- memcpy(ret + retlen, cfg->proxy_telnet_command + so, eo - so);
+ memcpy(ret + retlen, fmt + so, eo - so);
retlen += eo - so;
}
char *formatted_cmd;
formatted_cmd = format_telnet_command(p->remote_addr, p->remote_port,
- &p->cfg);
+ p->conf);
sk_write(p->sub_socket, formatted_cmd, strlen(formatted_cmd));
sfree(formatted_cmd);
OSSocket accepting_sock;
/* configuration, used to look up proxy settings */
- Config cfg;
+ Conf *conf;
/* CHAP transient data */
int chap_num_attributes;
* This may be reused by local-command proxies on individual
* platforms.
*/
-char *format_telnet_command(SockAddr addr, int port, const Config *cfg);
+char *format_telnet_command(SockAddr addr, int port, Conf *conf);
/*
* These are implemented in cproxy.c or nocproxy.c, depending on
static Backend *back;
static void *backhandle;
-static Config cfg;
+static Conf *conf;
static void source(char *src);
static void rsource(char *src);
*/
if (!loaded_session) {
/* Try to load settings for `host' into a temporary config */
- Config cfg2;
- cfg2.host[0] = '\0';
- do_defaults(host, &cfg2);
- if (cfg2.host[0] != '\0') {
+ Conf *conf2 = conf_new();
+ conf_set_str(conf2, CONF_host, "");
+ do_defaults(host, conf2);
+ if (conf_get_str(conf2, CONF_host)[0] != '\0') {
/* Settings present and include hostname */
/* Re-load data into the real config. */
- do_defaults(host, &cfg);
+ do_defaults(host, conf);
} else {
/* Session doesn't exist or mention a hostname. */
/* Use `host' as a bare hostname. */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, host);
}
} else {
/* Patch in hostname `host' to session details. */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, host);
}
/*
* Force use of SSH. (If they got the protocol wrong we assume the
* port is useless too.)
*/
- if (cfg.protocol != PROT_SSH) {
- cfg.protocol = PROT_SSH;
- cfg.port = 22;
+ if (conf_get_int(conf, CONF_protocol) != PROT_SSH) {
+ conf_set_int(conf, CONF_protocol, PROT_SSH);
+ conf_set_int(conf, CONF_port, 22);
}
/*
* Enact command-line overrides.
*/
- cmdline_run_saved(&cfg);
+ cmdline_run_saved(conf);
/*
- * Trim leading whitespace off the hostname if it's there.
+ * Muck about with the hostname in various ways.
*/
{
- int space = strspn(cfg.host, " \t");
- memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
- }
+ char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
+ char *host = hostbuf;
+ char *p, *q;
+
+ /*
+ * Trim leading whitespace.
+ */
+ host += strspn(host, " \t");
- /* See if host is of the form user@host */
- if (cfg.host[0] != '\0') {
- char *atsign = strrchr(cfg.host, '@');
- /* Make sure we're not overflowing the user field */
- if (atsign) {
- if (atsign - cfg.host < sizeof cfg.username) {
- strncpy(cfg.username, cfg.host, atsign - cfg.host);
- cfg.username[atsign - cfg.host] = '\0';
+ /*
+ * See if host is of the form user@host, and separate out
+ * the username if so.
+ */
+ if (host[0] != '\0') {
+ char *atsign = strrchr(host, '@');
+ if (atsign) {
+ *atsign = '\0';
+ conf_set_str(conf, CONF_username, host);
+ host = atsign + 1;
}
- memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
- }
- /*
- * Remove any remaining whitespace from the hostname.
- */
- {
- int p1 = 0, p2 = 0;
- while (cfg.host[p2] != '\0') {
- if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
- cfg.host[p1] = cfg.host[p2];
- p1++;
- }
- p2++;
+ /*
+ * Remove any remaining whitespace.
+ */
+ p = hostbuf;
+ q = host;
+ while (*q) {
+ if (*q != ' ' && *q != '\t')
+ *p++ = *q;
+ q++;
}
- cfg.host[p1] = '\0';
+ *p = '\0';
+
+ conf_set_str(conf, CONF_host, hostbuf);
+ sfree(hostbuf);
}
/* Set username */
if (user != NULL && user[0] != '\0') {
- strncpy(cfg.username, user, sizeof(cfg.username) - 1);
- cfg.username[sizeof(cfg.username) - 1] = '\0';
- } else if (cfg.username[0] == '\0') {
+ conf_set_str(conf, CONF_username, user);
+ } else if (conf_get_str(conf, CONF_username)[0] == '\0') {
user = get_username();
if (!user)
bump("Empty user name");
else {
if (verbose)
tell_user(stderr, "Guessing user name: %s", user);
- strncpy(cfg.username, user, sizeof(cfg.username) - 1);
- cfg.username[sizeof(cfg.username) - 1] = '\0';
+ conf_set_str(conf, CONF_username, user);
sfree(user);
}
}
* things like SCP and SFTP: agent forwarding, port forwarding,
* X forwarding.
*/
- cfg.x11_forward = 0;
- cfg.agentfwd = 0;
- cfg.portfwd[0] = cfg.portfwd[1] = '\0';
- cfg.ssh_simple = TRUE;
+ conf_set_int(conf, CONF_x11_forward, 0);
+ conf_set_int(conf, CONF_agentfwd, 0);
+ conf_set_int(conf, CONF_ssh_simple, TRUE);
+ {
+ char *key;
+ while ((key = conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) != NULL)
+ conf_del_str_str(conf, CONF_portfwd, key);
+ }
/*
* Set up main and possibly fallback command depending on
* Attempt to start the SFTP subsystem as a first choice,
* falling back to the provided scp command if that fails.
*/
- cfg.remote_cmd_ptr2 = NULL;
+ conf_set_str(conf, CONF_remote_cmd2, "");
if (try_sftp) {
/* First choice is SFTP subsystem. */
main_cmd_is_sftp = 1;
- strcpy(cfg.remote_cmd, "sftp");
- cfg.ssh_subsys = TRUE;
+ conf_set_str(conf, CONF_remote_cmd, "sftp");
+ conf_set_int(conf, CONF_ssh_subsys, TRUE);
if (try_scp) {
/* Fallback is to use the provided scp command. */
fallback_cmd_is_sftp = 0;
- cfg.remote_cmd_ptr2 = cmd;
- cfg.ssh_subsys2 = FALSE;
+ conf_set_str(conf, CONF_remote_cmd2, "sftp");
+ conf_set_int(conf, CONF_ssh_subsys2, FALSE);
} else {
/* Since we're not going to try SCP, we may as well try
* harder to find an SFTP server, since in the current
* implementation we have a spare slot. */
fallback_cmd_is_sftp = 1;
/* see psftp.c for full explanation of this kludge */
- cfg.remote_cmd_ptr2 =
- "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n"
- "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n"
- "exec sftp-server";
- cfg.ssh_subsys2 = FALSE;
+ conf_set_str(conf, CONF_remote_cmd2,
+ "test -x /usr/lib/sftp-server &&"
+ " exec /usr/lib/sftp-server\n"
+ "test -x /usr/local/lib/sftp-server &&"
+ " exec /usr/local/lib/sftp-server\n"
+ "exec sftp-server");
+ conf_set_int(conf, CONF_ssh_subsys2, FALSE);
}
} else {
/* Don't try SFTP at all; just try the scp command. */
main_cmd_is_sftp = 0;
- cfg.remote_cmd_ptr = cmd;
- cfg.ssh_subsys = FALSE;
+ conf_set_str(conf, CONF_remote_cmd, cmd);
+ conf_set_int(conf, CONF_ssh_subsys, FALSE);
}
- cfg.nopty = TRUE;
+ conf_set_int(conf, CONF_nopty, TRUE);
back = &ssh_backend;
- err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,
- 0, cfg.tcp_keepalives);
+ err = back->init(NULL, &backhandle, conf,
+ conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port),
+ &realhost, 0,
+ conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL)
bump("ssh_init: %s", err);
- logctx = log_init(NULL, &cfg);
+ logctx = log_init(NULL, conf);
back->provide_logctx(backhandle, logctx);
console_provide_logctx(logctx);
ssh_scp_init();
sk_init();
/* Load Default Settings before doing anything else. */
- do_defaults(NULL, &cfg);
+ conf = conf_new();
+ do_defaults(NULL, conf);
loaded_session = FALSE;
for (i = 1; i < argc; i++) {
int ret;
if (argv[i][0] != '-')
break;
- ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, &cfg);
+ ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, conf);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", argv[i]);
} else if (ret == 2) {
char *pwd, *homedir;
static Backend *back;
static void *backhandle;
-static Config cfg;
+static Conf *conf;
/* ----------------------------------------------------------------------
* Higher-level helper functions used in commands.
*/
if (!loaded_session) {
/* Try to load settings for `host' into a temporary config */
- Config cfg2;
- cfg2.host[0] = '\0';
- do_defaults(host, &cfg2);
- if (cfg2.host[0] != '\0') {
+ Conf *conf2 = conf_new();
+ conf_set_str(conf2, CONF_host, "");
+ do_defaults(host, conf2);
+ if (conf_get_str(conf2, CONF_host)[0] != '\0') {
/* Settings present and include hostname */
/* Re-load data into the real config. */
- do_defaults(host, &cfg);
+ do_defaults(host, conf);
} else {
/* Session doesn't exist or mention a hostname. */
/* Use `host' as a bare hostname. */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, host);
}
} else {
/* Patch in hostname `host' to session details. */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, host);
}
/*
* Force use of SSH. (If they got the protocol wrong we assume the
* port is useless too.)
*/
- if (cfg.protocol != PROT_SSH) {
- cfg.protocol = PROT_SSH;
- cfg.port = 22;
+ if (conf_get_int(conf, CONF_protocol) != PROT_SSH) {
+ conf_set_int(conf, CONF_protocol, PROT_SSH);
+ conf_set_int(conf, CONF_port, 22);
}
/*
* work for SFTP. (Can be overridden with `-1' option.)
* But if it says `2 only' or `2', respect which.
*/
- if (cfg.sshprot != 2 && cfg.sshprot != 3)
- cfg.sshprot = 2;
+ if ((conf_get_int(conf, CONF_sshprot) & ~1) != 2) /* is it 2 or 3? */
+ conf_set_int(conf, CONF_sshprot, 2);
/*
* Enact command-line overrides.
*/
- cmdline_run_saved(&cfg);
+ cmdline_run_saved(conf);
/*
- * Trim leading whitespace off the hostname if it's there.
+ * Muck about with the hostname in various ways.
*/
{
- int space = strspn(cfg.host, " \t");
- memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
- }
-
- /* See if host is of the form user@host */
- if (cfg.host[0] != '\0') {
- char *atsign = strrchr(cfg.host, '@');
- /* Make sure we're not overflowing the user field */
- if (atsign) {
- if (atsign - cfg.host < sizeof cfg.username) {
- strncpy(cfg.username, cfg.host, atsign - cfg.host);
- cfg.username[atsign - cfg.host] = '\0';
- }
- memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
- }
- }
+ char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
+ char *host = hostbuf;
+ char *p, *q;
- /*
- * Trim a colon suffix off the hostname if it's there.
- */
- cfg.host[strcspn(cfg.host, ":")] = '\0';
+ /*
+ * Trim leading whitespace.
+ */
+ host += strspn(host, " \t");
- /*
- * Remove any remaining whitespace from the hostname.
- */
- {
- int p1 = 0, p2 = 0;
- while (cfg.host[p2] != '\0') {
- if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
- cfg.host[p1] = cfg.host[p2];
- p1++;
+ /*
+ * See if host is of the form user@host, and separate out
+ * the username if so.
+ */
+ if (host[0] != '\0') {
+ char *atsign = strrchr(host, '@');
+ if (atsign) {
+ *atsign = '\0';
+ conf_set_str(conf, CONF_username, host);
+ host = atsign + 1;
}
- p2++;
}
- cfg.host[p1] = '\0';
+
+ /*
+ * Remove any remaining whitespace.
+ */
+ p = hostbuf;
+ q = host;
+ while (*q) {
+ if (*q != ' ' && *q != '\t')
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+
+ conf_set_str(conf, CONF_host, hostbuf);
+ sfree(hostbuf);
}
/* Set username */
if (user != NULL && user[0] != '\0') {
- strncpy(cfg.username, user, sizeof(cfg.username) - 1);
- cfg.username[sizeof(cfg.username) - 1] = '\0';
+ conf_set_str(conf, CONF_username, user);
}
if (portnumber)
- cfg.port = portnumber;
+ conf_set_int(conf, CONF_port, portnumber);
/*
* Disable scary things which shouldn't be enabled for simple
* things like SCP and SFTP: agent forwarding, port forwarding,
* X forwarding.
*/
- cfg.x11_forward = 0;
- cfg.agentfwd = 0;
- cfg.portfwd[0] = cfg.portfwd[1] = '\0';
- cfg.ssh_simple = TRUE;
+ conf_set_int(conf, CONF_x11_forward, 0);
+ conf_set_int(conf, CONF_agentfwd, 0);
+ conf_set_int(conf, CONF_ssh_simple, TRUE);
+ {
+ char *key;
+ while ((key = conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) != NULL)
+ conf_del_str_str(conf, CONF_portfwd, key);
+ }
/* Set up subsystem name. */
- strcpy(cfg.remote_cmd, "sftp");
- cfg.ssh_subsys = TRUE;
- cfg.nopty = TRUE;
+ conf_set_str(conf, CONF_remote_cmd, "sftp");
+ conf_set_int(conf, CONF_ssh_subsys, TRUE);
+ conf_set_int(conf, CONF_nopty, TRUE);
/*
* Set up fallback option, for SSH-1 servers or servers with the
* obvious pathnames and then give up, and when it does give up
* it will print the preferred pathname in the error messages.
*/
- cfg.remote_cmd_ptr2 =
- "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n"
- "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n"
- "exec sftp-server";
- cfg.ssh_subsys2 = FALSE;
+ conf_set_str(conf, CONF_remote_cmd2,
+ "test -x /usr/lib/sftp-server &&"
+ " exec /usr/lib/sftp-server\n"
+ "test -x /usr/local/lib/sftp-server &&"
+ " exec /usr/local/lib/sftp-server\n"
+ "exec sftp-server");
+ conf_set_int(conf, CONF_ssh_subsys2, FALSE);
back = &ssh_backend;
- err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,
- 0, cfg.tcp_keepalives);
+ err = back->init(NULL, &backhandle, conf,
+ conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port),
+ &realhost, 0,
+ conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL) {
fprintf(stderr, "ssh_init: %s\n", err);
return 1;
}
- logctx = log_init(NULL, &cfg);
+ logctx = log_init(NULL, conf);
back->provide_logctx(backhandle, logctx);
console_provide_logctx(logctx);
while (!back->sendok(backhandle)) {
userhost = user = NULL;
/* Load Default Settings before doing anything else. */
- do_defaults(NULL, &cfg);
+ conf = conf_new();
+ do_defaults(NULL, conf);
loaded_session = FALSE;
for (i = 1; i < argc; i++) {
userhost = dupstr(argv[i]);
continue;
}
- ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, &cfg);
+ ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, conf);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", argv[i]);
} else if (ret == 2) {
* otherwise been specified, pop it in `userhost' so that
* `psftp -load sessname' is sufficient to start a session.
*/
- if (!userhost && cfg.host[0] != '\0') {
- userhost = dupstr(cfg.host);
+ if (!userhost && conf_get_str(conf, CONF_host)[0] != '\0') {
+ userhost = dupstr(conf_get_str(conf, CONF_host));
}
/*
#ifndef DONE_TYPEDEFS
#define DONE_TYPEDEFS
-typedef struct config_tag Config;
+typedef struct conf_tag Conf;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal;
#endif
};
enum {
- /* Protocol back ends. (cfg.protocol) */
+ /* Protocol back ends. (CONF_protocol) */
PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH,
/* PROT_SERIAL is supported on a subset of platforms, but it doesn't
* hurt to define it globally. */
};
enum {
- /* Bell settings (cfg.beep) */
+ /* Bell settings (CONF_beep) */
BELL_DISABLED, BELL_DEFAULT, BELL_VISUAL, BELL_WAVEFILE, BELL_PCSPEAKER
};
enum {
- /* Taskbar flashing indication on bell (cfg.beep_ind) */
+ /* Taskbar flashing indication on bell (CONF_beep_ind) */
B_IND_DISABLED, B_IND_FLASH, B_IND_STEADY
};
enum {
- /* Resize actions (cfg.resize_action) */
+ /* Resize actions (CONF_resize_action) */
RESIZE_TERM, RESIZE_DISABLED, RESIZE_FONT, RESIZE_EITHER
};
enum {
- /* Function key types (cfg.funky_type) */
+ /* Function key types (CONF_funky_type) */
FUNKY_TILDE,
FUNKY_LINUX,
FUNKY_XTERM,
struct backend_tag {
const char *(*init) (void *frontend_handle, void **backend_handle,
- Config *cfg,
- char *host, int port, char **realhost, int nodelay,
- int keepalive);
+ Conf *conf, char *host, int port, char **realhost,
+ int nodelay, int keepalive);
void (*free) (void *handle);
/* back->reconfig() passes in a replacement configuration. */
- void (*reconfig) (void *handle, Config *cfg);
+ void (*reconfig) (void *handle, Conf *conf);
/* 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 */
extern const char *const appname;
/*
- * IMPORTANT POLICY POINT: everything in this structure which wants
- * to be treated like an integer must be an actual, honest-to-
- * goodness `int'. No enum-typed variables. This is because parts
- * of the code will want to pass around `int *' pointers to them
- * and we can't run the risk of porting to some system on which the
- * enum comes out as a different size from int.
- */
-struct config_tag {
- /* Basic options */
- char host[512];
- int port;
- int protocol;
- int addressfamily;
- int close_on_exit;
- int warn_on_close;
- int ping_interval; /* in seconds */
- int tcp_nodelay;
- int tcp_keepalives;
- char loghost[512]; /* logical host being contacted, for host key check */
- /* Proxy options */
- char proxy_exclude_list[512];
- int proxy_dns;
- int even_proxy_localhost;
- int proxy_type;
- char proxy_host[512];
- int proxy_port;
- char proxy_username[128];
- char proxy_password[128];
- char proxy_telnet_command[512];
- /* SSH options */
- char remote_cmd[512];
- char *remote_cmd_ptr; /* might point to a larger command
- * but never for loading/saving */
- char *remote_cmd_ptr2; /* might point to a larger command
- * but never for loading/saving */
- int nopty;
- int compression;
- int ssh_kexlist[KEX_MAX];
- int ssh_rekey_time; /* in minutes */
- char ssh_rekey_data[16];
- int tryagent;
- int agentfwd;
- int change_username; /* allow username switching in SSH-2 */
- int ssh_cipherlist[CIPHER_MAX];
- Filename keyfile;
- int sshprot; /* use v1 or v2 when both available */
- int ssh2_des_cbc; /* "des-cbc" unrecommended SSH-2 cipher */
- int ssh_no_userauth; /* bypass "ssh-userauth" (SSH-2 only) */
- int ssh_show_banner; /* show USERAUTH_BANNERs (SSH-2 only) */
- int try_tis_auth;
- int try_ki_auth;
- int try_gssapi_auth; /* attempt gssapi auth */
- int gssapifwd; /* forward tgt via gss */
- int ssh_gsslist[4]; /* preference order for local GSS libs */
- Filename ssh_gss_custom;
- int ssh_subsys; /* run a subsystem rather than a command */
- int ssh_subsys2; /* fallback to go with remote_cmd_ptr2 */
- int ssh_no_shell; /* avoid running a shell */
- char ssh_nc_host[512]; /* host to connect to in `nc' mode */
- int ssh_nc_port; /* port to connect to in `nc' mode */
- /* Telnet options */
- char termtype[32];
- char termspeed[32];
- char ttymodes[768]; /* MODE\tVvalue\0MODE\tA\0\0 */
- char environmt[1024]; /* VAR\tvalue\0VAR\tvalue\0\0 */
- char username[100];
- int username_from_env;
- char localusername[100];
- int rfc_environ;
- int passive_telnet;
- /* Serial port options */
- char serline[256];
- int serspeed;
- int serdatabits, serstopbits;
- int serparity;
- int serflow;
- /* Keyboard options */
- int bksp_is_delete;
- int rxvt_homeend;
- int funky_type;
- int no_applic_c; /* totally disable app cursor keys */
- int no_applic_k; /* totally disable app keypad */
- int no_mouse_rep; /* totally disable mouse reporting */
- int no_remote_resize; /* disable remote resizing */
- int no_alt_screen; /* disable alternate screen */
- int no_remote_wintitle; /* disable remote retitling */
- int no_dbackspace; /* disable destructive backspace */
- int no_remote_charset; /* disable remote charset config */
- int remote_qtitle_action; /* remote win title query action */
- int app_cursor;
- int app_keypad;
- int nethack_keypad;
- int telnet_keyboard;
- int telnet_newline;
- int alt_f4; /* is it special? */
- int alt_space; /* is it special? */
- int alt_only; /* is it special? */
- int localecho;
- int localedit;
- int alwaysontop;
- int fullscreenonaltenter;
- int scroll_on_key;
- int scroll_on_disp;
- int erase_to_scrollback;
- int compose_key;
- int ctrlaltkeys;
- char wintitle[256]; /* initial window title */
- /* Terminal options */
- int savelines;
- int dec_om;
- int wrap_mode;
- int lfhascr;
- int cursor_type; /* 0=block 1=underline 2=vertical */
- int blink_cur;
- int beep;
- int beep_ind;
- int bellovl; /* bell overload protection active? */
- int bellovl_n; /* number of bells to cause overload */
- int bellovl_t; /* time interval for overload (seconds) */
- int bellovl_s; /* period of silence to re-enable bell (s) */
- Filename bell_wavefile;
- int scrollbar;
- int scrollbar_in_fullscreen;
- int resize_action;
- int bce;
- int blinktext;
- int win_name_always;
- int width, height;
- FontSpec font;
- int font_quality;
- Filename logfilename;
- int logtype;
- int logxfovr;
- int logflush;
- int logomitpass;
- int logomitdata;
- int hide_mouseptr;
- int sunken_edge;
- int window_border;
- char answerback[256];
- char printer[128];
- int arabicshaping;
- int bidi;
- /* Colour options */
- int ansi_colour;
- int xterm_256_colour;
- int system_colour;
- int try_palette;
- int bold_colour;
- unsigned char colours[22][3];
- /* Selection options */
- int mouse_is_xterm;
- int rect_select;
- int rawcnp;
- int rtf_paste;
- int mouse_override;
- short wordness[256];
- /* translations */
- int vtmode;
- char line_codepage[128];
- int cjk_ambig_wide;
- int utf8_override;
- int xlat_capslockcyr;
- /* X11 forwarding */
- int x11_forward;
- char x11_display[128];
- int x11_auth;
- Filename xauthfile;
- /* port forwarding */
- int lport_acceptall; /* accept conns from hosts other than localhost */
- int rport_acceptall; /* same for remote forwarded ports (SSH-2 only) */
- /*
- * The port forwarding string contains a number of
- * NUL-terminated substrings, terminated in turn by an empty
- * string (i.e. a second NUL immediately after the previous
- * one). Each string can be of one of the following forms:
- *
- * [LR]localport\thost:port
- * [LR]localaddr:localport\thost:port
- * Dlocalport
- * Dlocaladdr:localport
- */
- char portfwd[1024];
- /* SSH bug compatibility modes */
- int sshbug_ignore1, sshbug_plainpw1, sshbug_rsa1,
- sshbug_hmac2, sshbug_derivekey2, sshbug_rsapad2,
- sshbug_pksessid2, sshbug_rekey2, sshbug_maxpkt2,
- sshbug_ignore2;
- /*
- * ssh_simple means that we promise never to open any channel other
- * than the main one, which means it can safely use a very large
- * window in SSH-2.
- */
- int ssh_simple;
- /* Options for pterm. Should split out into platform-dependent part. */
- int stamp_utmp;
- int login_shell;
- int scrollbar_on_left;
- int shadowbold;
- FontSpec boldfont;
- FontSpec widefont;
- FontSpec wideboldfont;
- int shadowboldoffset;
- int crhaslf;
- char winclass[256];
-};
-
-/*
* Some global flags denoting the type of application.
*
* FLAG_VERBOSE is set when the user requests verbose details.
void cleanup_exit(int);
/*
+ * Exports from conf.c, and a big enum (via parametric macro) of
+ * configuration option keys.
+ */
+#define CONFIG_OPTIONS(X) \
+ /* X(value-type, subkey-type, keyword) */ \
+ X(STR, NONE, host) \
+ X(INT, NONE, port) \
+ X(INT, NONE, protocol) \
+ X(INT, NONE, addressfamily) \
+ X(INT, NONE, close_on_exit) \
+ X(INT, NONE, warn_on_close) \
+ X(INT, NONE, ping_interval) /* in seconds */ \
+ X(INT, NONE, tcp_nodelay) \
+ X(INT, NONE, tcp_keepalives) \
+ X(STR, NONE, loghost) /* logical host being contacted, for host key check */ \
+ /* Proxy options */ \
+ X(STR, NONE, proxy_exclude_list) \
+ X(INT, NONE, proxy_dns) \
+ X(INT, NONE, even_proxy_localhost) \
+ X(INT, NONE, proxy_type) \
+ X(STR, NONE, proxy_host) \
+ X(INT, NONE, proxy_port) \
+ X(STR, NONE, proxy_username) \
+ X(STR, NONE, proxy_password) \
+ X(STR, NONE, proxy_telnet_command) \
+ /* SSH options */ \
+ X(STR, NONE, remote_cmd) \
+ X(STR, NONE, remote_cmd2) /* fallback if remote_cmd fails; never loaded or saved */ \
+ X(INT, NONE, nopty) \
+ X(INT, NONE, compression) \
+ X(INT, INT, ssh_kexlist) \
+ X(INT, NONE, ssh_rekey_time) /* in minutes */ \
+ X(STR, NONE, ssh_rekey_data) /* string encoding e.g. "100K", "2M", "1G" */ \
+ X(INT, NONE, tryagent) \
+ X(INT, NONE, agentfwd) \
+ X(INT, NONE, change_username) /* allow username switching in SSH-2 */ \
+ X(INT, INT, ssh_cipherlist) \
+ X(FILENAME, NONE, keyfile) \
+ X(INT, NONE, sshprot) /* use v1 or v2 when both available */ \
+ X(INT, NONE, ssh2_des_cbc) /* "des-cbc" unrecommended SSH-2 cipher */ \
+ X(INT, NONE, ssh_no_userauth) /* bypass "ssh-userauth" (SSH-2 only) */ \
+ X(INT, NONE, ssh_show_banner) /* show USERAUTH_BANNERs (SSH-2 only) */ \
+ X(INT, NONE, try_tis_auth) \
+ X(INT, NONE, try_ki_auth) \
+ X(INT, NONE, try_gssapi_auth) /* attempt gssapi auth */ \
+ X(INT, NONE, gssapifwd) /* forward tgt via gss */ \
+ X(INT, INT, ssh_gsslist) /* preference order for local GSS libs */ \
+ X(FILENAME, NONE, ssh_gss_custom) \
+ X(INT, NONE, ssh_subsys) /* run a subsystem rather than a command */ \
+ X(INT, NONE, ssh_subsys2) /* fallback to go with remote_cmd_ptr2 */ \
+ X(INT, NONE, ssh_no_shell) /* avoid running a shell */ \
+ X(STR, NONE, ssh_nc_host) /* host to connect to in `nc' mode */ \
+ X(INT, NONE, ssh_nc_port) /* port to connect to in `nc' mode */ \
+ /* Telnet options */ \
+ X(STR, NONE, termtype) \
+ X(STR, NONE, termspeed) \
+ X(STR, STR, ttymodes) /* values are "Vvalue" or "A" */ \
+ X(STR, STR, environmt) \
+ X(STR, NONE, username) \
+ X(INT, NONE, username_from_env) \
+ X(STR, NONE, localusername) \
+ X(INT, NONE, rfc_environ) \
+ X(INT, NONE, passive_telnet) \
+ /* Serial port options */ \
+ X(STR, NONE, serline) \
+ X(INT, NONE, serspeed) \
+ X(INT, NONE, serdatabits) \
+ X(INT, NONE, serstopbits) \
+ X(INT, NONE, serparity) \
+ X(INT, NONE, serflow) \
+ /* Keyboard options */ \
+ X(INT, NONE, bksp_is_delete) \
+ X(INT, NONE, rxvt_homeend) \
+ X(INT, NONE, funky_type) \
+ X(INT, NONE, no_applic_c) /* totally disable app cursor keys */ \
+ X(INT, NONE, no_applic_k) /* totally disable app keypad */ \
+ X(INT, NONE, no_mouse_rep) /* totally disable mouse reporting */ \
+ X(INT, NONE, no_remote_resize) /* disable remote resizing */ \
+ X(INT, NONE, no_alt_screen) /* disable alternate screen */ \
+ X(INT, NONE, no_remote_wintitle) /* disable remote retitling */ \
+ X(INT, NONE, no_dbackspace) /* disable destructive backspace */ \
+ X(INT, NONE, no_remote_charset) /* disable remote charset config */ \
+ X(INT, NONE, remote_qtitle_action) /* remote win title query action */ \
+ X(INT, NONE, app_cursor) \
+ X(INT, NONE, app_keypad) \
+ X(INT, NONE, nethack_keypad) \
+ X(INT, NONE, telnet_keyboard) \
+ X(INT, NONE, telnet_newline) \
+ X(INT, NONE, alt_f4) /* is it special? */ \
+ X(INT, NONE, alt_space) /* is it special? */ \
+ X(INT, NONE, alt_only) /* is it special? */ \
+ X(INT, NONE, localecho) \
+ X(INT, NONE, localedit) \
+ X(INT, NONE, alwaysontop) \
+ X(INT, NONE, fullscreenonaltenter) \
+ X(INT, NONE, scroll_on_key) \
+ X(INT, NONE, scroll_on_disp) \
+ X(INT, NONE, erase_to_scrollback) \
+ X(INT, NONE, compose_key) \
+ X(INT, NONE, ctrlaltkeys) \
+ X(STR, NONE, wintitle) /* initial window title */ \
+ /* Terminal options */ \
+ X(INT, NONE, savelines) \
+ X(INT, NONE, dec_om) \
+ X(INT, NONE, wrap_mode) \
+ X(INT, NONE, lfhascr) \
+ X(INT, NONE, cursor_type) /* 0=block 1=underline 2=vertical */ \
+ X(INT, NONE, blink_cur) \
+ X(INT, NONE, beep) \
+ X(INT, NONE, beep_ind) \
+ X(INT, NONE, bellovl) /* bell overload protection active? */ \
+ X(INT, NONE, bellovl_n) /* number of bells to cause overload */ \
+ X(INT, NONE, bellovl_t) /* time interval for overload (seconds) */ \
+ X(INT, NONE, bellovl_s) /* period of silence to re-enable bell (s) */ \
+ X(FILENAME, NONE, bell_wavefile) \
+ X(INT, NONE, scrollbar) \
+ X(INT, NONE, scrollbar_in_fullscreen) \
+ X(INT, NONE, resize_action) \
+ X(INT, NONE, bce) \
+ X(INT, NONE, blinktext) \
+ X(INT, NONE, win_name_always) \
+ X(INT, NONE, width) \
+ X(INT, NONE, height) \
+ X(FONT, NONE, font) \
+ X(INT, NONE, font_quality) \
+ X(FILENAME, NONE, logfilename) \
+ X(INT, NONE, logtype) \
+ X(INT, NONE, logxfovr) \
+ X(INT, NONE, logflush) \
+ X(INT, NONE, logomitpass) \
+ X(INT, NONE, logomitdata) \
+ X(INT, NONE, hide_mouseptr) \
+ X(INT, NONE, sunken_edge) \
+ X(INT, NONE, window_border) \
+ X(STR, NONE, answerback) \
+ X(STR, NONE, printer) \
+ X(INT, NONE, arabicshaping) \
+ X(INT, NONE, bidi) \
+ /* Colour options */ \
+ X(INT, NONE, ansi_colour) \
+ X(INT, NONE, xterm_256_colour) \
+ X(INT, NONE, system_colour) \
+ X(INT, NONE, try_palette) \
+ X(INT, NONE, bold_colour) \
+ X(INT, INT, colours) \
+ /* Selection options */ \
+ X(INT, NONE, mouse_is_xterm) \
+ X(INT, NONE, rect_select) \
+ X(INT, NONE, rawcnp) \
+ X(INT, NONE, rtf_paste) \
+ X(INT, NONE, mouse_override) \
+ X(INT, INT, wordness) \
+ /* translations */ \
+ X(INT, NONE, vtmode) \
+ X(STR, NONE, line_codepage) \
+ X(INT, NONE, cjk_ambig_wide) \
+ X(INT, NONE, utf8_override) \
+ X(INT, NONE, xlat_capslockcyr) \
+ /* X11 forwarding */ \
+ X(INT, NONE, x11_forward) \
+ X(STR, NONE, x11_display) \
+ X(INT, NONE, x11_auth) \
+ X(FILENAME, NONE, xauthfile) \
+ /* port forwarding */ \
+ X(INT, NONE, lport_acceptall) /* accept conns from hosts other than localhost */ \
+ X(INT, NONE, rport_acceptall) /* same for remote forwarded ports (SSH-2 only) */ \
+ /* \
+ * Subkeys for 'portfwd' can have the following forms: \
+ * \
+ * [LR]localport \
+ * [LR]localaddr:localport \
+ * \
+ * Dynamic forwardings are indicated by an 'L' key, and the \
+ * special value "D". For all other forwardings, the value \
+ * should be of the form 'host:port'. \
+ */ \
+ X(STR, STR, portfwd) \
+ /* SSH bug compatibility modes */ \
+ X(INT, NONE, sshbug_ignore1) \
+ X(INT, NONE, sshbug_plainpw1) \
+ X(INT, NONE, sshbug_rsa1) \
+ X(INT, NONE, sshbug_hmac2) \
+ X(INT, NONE, sshbug_derivekey2) \
+ X(INT, NONE, sshbug_rsapad2) \
+ X(INT, NONE, sshbug_pksessid2) \
+ X(INT, NONE, sshbug_rekey2) \
+ X(INT, NONE, sshbug_maxpkt2) \
+ X(INT, NONE, sshbug_ignore2) \
+ /* \
+ * ssh_simple means that we promise never to open any channel \
+ * other than the main one, which means it can safely use a very \
+ * large window in SSH-2. \
+ */ \
+ X(INT, NONE, ssh_simple) \
+ /* Options for pterm. Should split out into platform-dependent part. */ \
+ X(INT, NONE, stamp_utmp) \
+ X(INT, NONE, login_shell) \
+ X(INT, NONE, scrollbar_on_left) \
+ X(INT, NONE, shadowbold) \
+ X(FONT, NONE, boldfont) \
+ X(FONT, NONE, widefont) \
+ X(FONT, NONE, wideboldfont) \
+ X(INT, NONE, shadowboldoffset) \
+ X(INT, NONE, crhaslf) \
+ X(STR, NONE, winclass) \
+
+/* Now define the actual enum of option keywords using that macro. */
+#define CONF_ENUM_DEF(valtype, keytype, keyword) CONF_ ## keyword,
+enum config_primary_key { CONFIG_OPTIONS(CONF_ENUM_DEF) N_CONFIG_OPTIONS };
+#undef CONF_ENUM_DEF
+
+#define NCFGCOLOURS 22 /* number of colours in CONF_colours above */
+
+/* Functions handling configuration structures. */
+Conf *conf_new(void); /* create an empty configuration */
+void conf_free(Conf *conf);
+Conf *conf_copy(Conf *oldconf);
+void conf_copy_into(Conf *dest, Conf *src);
+/* Mandatory accessor functions: enforce by assertion that keys exist. */
+int conf_get_int(Conf *conf, int key);
+int conf_get_int_int(Conf *conf, int key, int subkey);
+char *conf_get_str(Conf *conf, int key); /* result still owned by conf */
+char *conf_get_str_str(Conf *conf, int key, const char *subkey);
+Filename *conf_get_filename(Conf *conf, int key);
+FontSpec *conf_get_fontspec(Conf *conf, int key);
+/* Optional accessor function: return NULL if key does not exist. */
+char *conf_get_str_str_opt(Conf *conf, int key, const char *subkey);
+/* Accessor function to step through a string-subkeyed list.
+ * Returns the next subkey after the provided one, or the first if NULL.
+ * Returns NULL if there are none left.
+ * Both the return value and *subkeyout are still owned by conf. */
+char *conf_get_str_strs(Conf *conf, int key, char *subkeyin, char **subkeyout);
+/* Return the nth string subkey in a list. Owned by conf. NULL if beyond end */
+char *conf_get_str_nthstrkey(Conf *conf, int key, int n);
+/* Functions to set entries in configuration. Always copy their inputs. */
+void conf_set_int(Conf *conf, int key, int value);
+void conf_set_int_int(Conf *conf, int key, int subkey, int value);
+void conf_set_str(Conf *conf, int key, const char *value);
+void conf_set_str_str(Conf *conf, int key,
+ const char *subkey, const char *val);
+void conf_del_str_str(Conf *conf, int key, const char *subkey);
+void conf_set_filename(Conf *conf, int key, const Filename *val);
+void conf_set_fontspec(Conf *conf, int key, const FontSpec *val);
+/* Serialisation functions for Duplicate Session */
+int conf_serialised_size(Conf *conf);
+void conf_serialise(Conf *conf, void *data);
+int conf_deserialise(Conf *conf, void *data, int maxsize);/*returns size used*/
+
+/*
* Exports from noise.c.
*/
void noise_get_heavy(void (*func) (void *, int));
*/
Backend *backend_from_name(const char *name);
Backend *backend_from_proto(int proto);
-int get_remote_username(Config *cfg, char *user, size_t len);
-char *save_settings(char *section, Config * cfg);
-void save_open_settings(void *sesskey, Config *cfg);
-void load_settings(char *section, Config * cfg);
-void load_open_settings(void *sesskey, Config *cfg);
+char *get_remote_username(Conf *conf); /* dynamically allocated */
+char *save_settings(char *section, Conf *conf);
+void save_open_settings(void *sesskey, Conf *conf);
+void load_settings(char *section, Conf *conf);
+void load_open_settings(void *sesskey, Conf *conf);
void get_sesslist(struct sesslist *, int allocate);
-void do_defaults(char *, Config *);
+void do_defaults(char *, Conf *);
void registry_cleanup(void);
/*
* Exports from terminal.c.
*/
-Terminal *term_init(Config *, struct unicode_data *, void *);
+Terminal *term_init(Conf *, struct unicode_data *, void *);
void term_free(Terminal *);
void term_size(Terminal *, int, int, int);
void term_paint(Terminal *, Context, int, int, int, int, int);
void term_nopaste(Terminal *);
int term_ldisc(Terminal *, int option);
void term_copyall(Terminal *);
-void term_reconfig(Terminal *, Config *);
+void term_reconfig(Terminal *, Conf *);
void term_seen_key_event(Terminal *);
int term_data(Terminal *, int is_stderr, const char *data, int len);
int term_data_untrusted(Terminal *, const char *data, int len);
/*
* Exports from logging.c.
*/
-void *log_init(void *frontend, Config *cfg);
+void *log_init(void *frontend, Conf *conf);
void log_free(void *logctx);
-void log_reconfig(void *logctx, Config *cfg);
+void log_reconfig(void *logctx, Conf *conf);
void logfopen(void *logctx);
void logfclose(void *logctx);
void logtraffic(void *logctx, unsigned char c, int logmode);
/*
* Exports from ldisc.c.
*/
-void *ldisc_create(Config *, Terminal *, Backend *, void *, void *);
+void *ldisc_create(Conf *, Terminal *, Backend *, void *, void *);
+void ldisc_configure(void *, Conf *);
void ldisc_free(void *);
void ldisc_send(void *handle, char *buf, int len, int interactive);
* Exports from pinger.c.
*/
typedef struct pinger_tag *Pinger;
-Pinger pinger_new(Config *cfg, Backend *back, void *backhandle);
-void pinger_reconfig(Pinger, Config *oldcfg, Config *newcfg);
+Pinger pinger_new(Conf *conf, Backend *back, void *backhandle);
+void pinger_reconfig(Pinger, Conf *oldconf, Conf *newconf);
void pinger_free(Pinger);
/*
*/
#include "misc.h"
-int cfg_launchable(const Config *cfg);
-char const *cfg_dest(const Config *cfg);
+int conf_launchable(Conf *conf);
+char const *conf_dest(Conf *conf);
/*
* Exports from sercfg.c.
* defined differently in various places and required _by_
* cmdline.c).
*/
-int cmdline_process_param(char *, char *, int, Config *);
-void cmdline_run_saved(Config *);
+int cmdline_process_param(char *, char *, int, Conf *);
+void cmdline_run_saved(Conf *);
void cmdline_cleanup(void);
int cmdline_get_passwd_input(prompts_t *p, unsigned char *in, int inlen);
#define TOOLTYPE_FILETRANSFER 1
* Exports from config.c.
*/
struct controlbox;
+union control;
+void conf_radiobutton_handler(union control *ctrl, void *dlg,
+ void *data, int event);
+#define CHECKBOX_INVERT (1<<30)
+void conf_checkbox_handler(union control *ctrl, void *dlg,
+ void *data, int event);
+void conf_editbox_handler(union control *ctrl, void *dlg,
+ void *data, int event);
+void conf_filesel_handler(union control *ctrl, void *dlg,
+ void *data, int event);
+void conf_fontsel_handler(union control *ctrl, void *dlg,
+ void *data, int event);
void setup_config_box(struct controlbox *b, int midsession,
int protocol, int protcfginfo);
* freed by the caller.
*/
static const char *raw_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
+ Conf *conf,
char *host, int port, char **realhost, int nodelay,
int keepalive)
{
SockAddr addr;
const char *err;
Raw raw;
+ int addressfamily;
+ char *loghost;
raw = snew(struct raw_backend_data);
raw->fn = &fn_table;
raw->frontend = frontend_handle;
+ addressfamily = conf_get_int(conf, CONF_addressfamily);
/*
* Try to find host.
*/
{
char *buf;
buf = dupprintf("Looking up host \"%s\"%s", host,
- (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
- (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
+ (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
+ (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
"")));
logevent(raw->frontend, buf);
sfree(buf);
}
- addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);
+ addr = name_lookup(host, port, realhost, conf, addressfamily);
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
* Open socket.
*/
raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
- (Plug) raw, cfg);
+ (Plug) raw, conf);
if ((err = sk_socket_error(raw->s)) != NULL)
return err;
- if (*cfg->loghost) {
+ loghost = conf_get_str(conf, CONF_loghost);
+ if (*loghost) {
char *colon;
sfree(*realhost);
- *realhost = dupstr(cfg->loghost);
+ *realhost = dupstr(loghost);
colon = strrchr(*realhost, ':');
if (colon) {
/*
/*
* Stub routine (we don't have any need to reconfigure this backend).
*/
-static void raw_reconfig(void *handle, Config *cfg)
+static void raw_reconfig(void *handle, Conf *conf)
{
}
int term_width, term_height;
void *frontend;
- Config cfg;
+ Conf *conf;
/* In case we need to read a username from the terminal before starting */
prompts_t *prompt;
{
char z = 0;
char *p;
+
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, rlogin->cfg.localusername,
- strlen(rlogin->cfg.localusername));
+ p = conf_get_str(rlogin->conf, CONF_localusername);
+ sk_write(rlogin->s, p, strlen(p));
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, ruser,
- strlen(ruser));
+ sk_write(rlogin->s, ruser, strlen(ruser));
sk_write(rlogin->s, &z, 1);
- sk_write(rlogin->s, rlogin->cfg.termtype,
- strlen(rlogin->cfg.termtype));
+ p = conf_get_str(rlogin->conf, CONF_termtype);
+ sk_write(rlogin->s, p, strlen(p));
sk_write(rlogin->s, "/", 1);
- for (p = rlogin->cfg.termspeed; isdigit((unsigned char)*p); p++) continue;
- sk_write(rlogin->s, rlogin->cfg.termspeed, p - rlogin->cfg.termspeed);
+ p = conf_get_str(rlogin->conf, CONF_termspeed);
+ sk_write(rlogin->s, p, strspn(p, "0123456789"));
rlogin->bufsize = sk_write(rlogin->s, &z, 1);
rlogin->prompt = NULL;
* freed by the caller.
*/
static const char *rlogin_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
+ Conf *conf,
char *host, int port, char **realhost,
int nodelay, int keepalive)
{
SockAddr addr;
const char *err;
Rlogin rlogin;
- char ruser[sizeof(cfg->username)];
+ char *ruser;
+ int addressfamily;
+ char *loghost;
rlogin = snew(struct rlogin_tag);
rlogin->fn = &fn_table;
rlogin->s = NULL;
rlogin->frontend = frontend_handle;
- rlogin->term_width = cfg->width;
- rlogin->term_height = cfg->height;
+ rlogin->term_width = conf_get_int(conf, CONF_width);
+ rlogin->term_height = conf_get_int(conf, CONF_height);
rlogin->firstbyte = 1;
rlogin->cansize = 0;
rlogin->prompt = NULL;
- rlogin->cfg = *cfg; /* STRUCTURE COPY */
+ rlogin->conf = conf_copy(conf);
*backend_handle = rlogin;
+ addressfamily = conf_get_int(conf, CONF_addressfamily);
/*
* Try to find host.
*/
{
char *buf;
buf = dupprintf("Looking up host \"%s\"%s", host,
- (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
- (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
+ (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
+ (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
"")));
logevent(rlogin->frontend, buf);
sfree(buf);
}
- addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);
+ addr = name_lookup(host, port, realhost, conf, addressfamily);
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
* Open socket.
*/
rlogin->s = new_connection(addr, *realhost, port, 1, 0,
- nodelay, keepalive, (Plug) rlogin, cfg);
+ nodelay, keepalive, (Plug) rlogin, conf);
if ((err = sk_socket_error(rlogin->s)) != NULL)
return err;
- if (*cfg->loghost) {
+ loghost = conf_get_str(conf, CONF_loghost);
+ if (*loghost) {
char *colon;
sfree(*realhost);
- *realhost = dupstr(cfg->loghost);
+ *realhost = dupstr(loghost);
colon = strrchr(*realhost, ':');
if (colon) {
/*
* in which case we prompt for it and may end up deferring doing
* anything else until the local prompt mechanism returns.
*/
- if (get_remote_username(cfg, ruser, sizeof(ruser))) {
+ if ((ruser = get_remote_username(conf)) == NULL) {
rlogin_startup(rlogin, ruser);
+ sfree(ruser);
} else {
int ret;
rlogin->prompt = new_prompts(rlogin->frontend);
rlogin->prompt->to_server = TRUE;
rlogin->prompt->name = dupstr("Rlogin login name");
- add_prompt(rlogin->prompt, dupstr("rlogin username: "), TRUE,
- sizeof(cfg->username));
+ /* 512 is an arbitrary limit :-( */
+ add_prompt(rlogin->prompt, dupstr("rlogin username: "), TRUE, 512);
ret = get_userpass_input(rlogin->prompt, NULL, 0);
if (ret >= 0) {
rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result);
free_prompts(rlogin->prompt);
if (rlogin->s)
sk_close(rlogin->s);
+ conf_free(rlogin->conf);
sfree(rlogin);
}
/*
* Stub routine (we don't have any need to reconfigure this backend).
*/
-static void rlogin_reconfig(void *handle, Config *cfg)
+static void rlogin_reconfig(void *handle, Conf *conf)
{
}
};
int mask = ctrl->listbox.context.i;
int i, j;
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
- int oldparity = cfg->serparity;/* preserve past reentrant calls */
+ /* Fetching this once at the start of the function ensures we
+ * remember what the right value is supposed to be when
+ * operations below cause reentrant calls to this function. */
+ int oldparity = conf_get_int(conf, CONF_serparity);
+
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < lenof(parities); i++) {
oldparity = SER_PAR_NONE;
}
dlg_update_done(ctrl, dlg);
- cfg->serparity = oldparity; /* restore */
+ conf_set_int(conf, CONF_serparity, oldparity); /* restore */
} else if (event == EVENT_SELCHANGE) {
int i = dlg_listbox_index(ctrl, dlg);
if (i < 0)
i = SER_PAR_NONE;
else
i = dlg_listbox_getid(ctrl, dlg, i);
- cfg->serparity = i;
+ conf_set_int(conf, CONF_serparity, i);
}
}
};
int mask = ctrl->listbox.context.i;
int i, j;
- Config *cfg = (Config *)data;
+ Conf *conf = (Conf *)data;
if (event == EVENT_REFRESH) {
- int oldflow = cfg->serflow; /* preserve past reentrant calls */
+ /* Fetching this once at the start of the function ensures we
+ * remember what the right value is supposed to be when
+ * operations below cause reentrant calls to this function. */
+ int oldflow = conf_get_int(conf, CONF_serflow);
+
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < lenof(flows); i++) {
oldflow = SER_FLOW_NONE;
}
dlg_update_done(ctrl, dlg);
- cfg->serflow = oldflow; /* restore */
+ conf_set_int(conf, CONF_serflow, oldflow);/* restore */
} else if (event == EVENT_SELCHANGE) {
int i = dlg_listbox_index(ctrl, dlg);
if (i < 0)
i = SER_FLOW_NONE;
else
i = dlg_listbox_getid(ctrl, dlg, i);
- cfg->serflow = i;
+ conf_set_int(conf, CONF_serflow, i);
}
}
"Select a serial line");
ctrl_editbox(s, "Serial line to connect to", 'l', 40,
HELPCTX(serial_line),
- dlg_stdeditbox_handler, I(offsetof(Config,serline)),
- I(sizeof(((Config *)0)->serline)));
+ conf_editbox_handler, I(CONF_serline), I(1));
}
s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
ctrl_editbox(s, "Speed (baud)", 's', 40,
HELPCTX(serial_speed),
- dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1));
+ conf_editbox_handler, I(CONF_serspeed), I(-1));
ctrl_editbox(s, "Data bits", 'b', 40,
HELPCTX(serial_databits),
- dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1));
+ conf_editbox_handler, I(CONF_serdatabits), I(-1));
/*
* Stop bits come in units of one half.
*/
ctrl_editbox(s, "Stop bits", 't', 40,
HELPCTX(serial_stopbits),
- dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2));
+ conf_editbox_handler, I(CONF_serstopbits), I(-2));
ctrl_droplist(s, "Parity", 'p', 40,
HELPCTX(serial_parity),
serial_parity_handler, I(parity_mask));
return NULL;
}
-int get_remote_username(Config *cfg, char *user, size_t len)
+char *get_remote_username(Conf *conf)
{
- if (*cfg->username) {
- strncpy(user, cfg->username, len);
- user[len-1] = '\0';
+ char *username = conf_get_str(conf, CONF_username);
+ if (*username) {
+ return dupstr(username);
+ } else if (conf_get_int(conf, CONF_username_from_env)) {
+ /* Use local username. */
+ return get_username(); /* might still be NULL */
} else {
- if (cfg->username_from_env) {
- /* Use local username. */
- char *luser = get_username();
- if (luser) {
- strncpy(user, luser, len);
- user[len-1] = '\0';
- sfree(luser);
- } else {
- *user = '\0';
- }
- } else {
- *user = '\0';
- }
+ return NULL;
}
- return (*user != '\0');
}
-static void gpps(void *handle, const char *name, const char *def,
- char *val, int len)
+static char *gpps_raw(void *handle, const char *name, const char *def)
{
- if (!read_setting_s(handle, name, val, len)) {
- char *pdef;
-
- pdef = platform_default_s(name);
- if (pdef) {
- strncpy(val, pdef, len);
- sfree(pdef);
- } else {
- strncpy(val, def, len);
- }
+ char *ret = read_setting_s(handle, name);
+ if (!ret)
+ ret = platform_default_s(name);
+ if (!ret)
+ ret = def ? dupstr(def) : NULL; /* permit NULL as final fallback */
+ return ret;
+}
- val[len - 1] = '\0';
- }
+static void gpps(void *handle, const char *name, const char *def,
+ Conf *conf, int primary)
+{
+ char *val = gpps_raw(handle, name, def);
+ conf_set_str(conf, primary, val);
+ sfree(val);
}
/*
* format of a Filename or Font is platform-dependent. So the
* platform-dependent functions MUST return some sort of value.
*/
-static void gppfont(void *handle, const char *name, FontSpec *result)
+static void gppfont(void *handle, const char *name, Conf *conf, int primary)
{
- if (!read_setting_fontspec(handle, name, result))
- *result = platform_default_fontspec(name);
+ FontSpec result;
+ if (!read_setting_fontspec(handle, name, &result))
+ result = platform_default_fontspec(name);
+ conf_set_fontspec(conf, primary, &result);
}
-static void gppfile(void *handle, const char *name, Filename *result)
+static void gppfile(void *handle, const char *name, Conf *conf, int primary)
{
- if (!read_setting_filename(handle, name, result))
- *result = platform_default_filename(name);
+ Filename result;
+ if (!read_setting_filename(handle, name, &result))
+ result = platform_default_filename(name);
+ conf_set_filename(conf, primary, &result);
}
-static void gppi(void *handle, char *name, int def, int *i)
+static int gppi_raw(void *handle, char *name, int def)
{
def = platform_default_i(name, def);
- *i = read_setting_i(handle, name, def);
+ return read_setting_i(handle, name, def);
+}
+
+static void gppi(void *handle, char *name, int def, Conf *conf, int primary)
+{
+ conf_set_int(conf, primary, gppi_raw(handle, name, def));
}
/*
* NAME=VALUE,NAME=VALUE, in storage
* `def' is in the storage format.
*/
-static void gppmap(void *handle, char *name, char *def, char *val, int len)
+static int gppmap(void *handle, char *name, Conf *conf, int primary)
{
- char *buf = snewn(2*len, char), *p, *q;
- gpps(handle, name, def, buf, 2*len);
+ char *buf, *p, *q, *key, *val;
+
+ /*
+ * Start by clearing any existing subkeys of this key from conf.
+ */
+ for (val = conf_get_str_strs(conf, primary, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, primary, key, &key))
+ conf_del_str_str(conf, primary, key);
+
+ /*
+ * Now read a serialised list from the settings and unmarshal it
+ * into its components.
+ */
+ buf = gpps_raw(handle, name, NULL);
+ if (!buf)
+ return FALSE;
+
p = buf;
- q = val;
while (*p) {
+ q = buf;
+ val = NULL;
while (*p && *p != ',') {
int c = *p++;
if (c == '=')
- c = '\t';
+ c = '\0';
if (c == '\\')
c = *p++;
*q++ = c;
+ if (!c)
+ val = q;
}
if (*p == ',')
p++;
- *q++ = '\0';
+ if (!val)
+ val = q;
+ *q = '\0';
+
+ if (primary == CONF_portfwd && buf[0] == 'D') {
+ /*
+ * Backwards-compatibility hack: dynamic forwardings are
+ * indexed in the data store as a third type letter in the
+ * key, 'D' alongside 'L' and 'R' - but really, they
+ * should be filed under 'L' with a special _value_,
+ * because local and dynamic forwardings both involve
+ * _listening_ on a local port, and are hence mutually
+ * exclusive on the same port number. So here we translate
+ * the legacy storage format into the sensible internal
+ * form.
+ */
+ char *newkey = dupcat("L", buf+1, NULL);
+ conf_set_str_str(conf, primary, newkey, "D");
+ sfree(newkey);
+ } else {
+ conf_set_str_str(conf, primary, buf, val);
+ }
}
- *q = '\0';
sfree(buf);
+
+ return TRUE;
}
/*
* Write a set of name/value pairs in the above format.
*/
-static void wmap(void *handle, char const *key, char const *value, int len)
+static void wmap(void *handle, char const *outkey, Conf *conf, int primary)
{
- char *buf = snewn(2*len, char), *p;
- const char *q;
+ char *buf, *p, *q, *key, *realkey, *val;
+ int len;
+
+ len = 1; /* allow for NUL */
+
+ for (val = conf_get_str_strs(conf, primary, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, primary, key, &key))
+ len += 2 + 2 * (strlen(key) + strlen(val)); /* allow for escaping */
+
+ buf = snewn(len, char);
p = buf;
- q = value;
- while (*q) {
- while (*q) {
- int c = *q++;
- if (c == '=' || c == ',' || c == '\\')
+
+ for (val = conf_get_str_strs(conf, primary, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, primary, key, &key)) {
+
+ if (primary == CONF_portfwd && !strcmp(val, "D")) {
+ /*
+ * Backwards-compatibility hack, as above: translate from
+ * the sensible internal representation of dynamic
+ * forwardings (key "L<port>", value "D") to the
+ * conceptually incoherent legacy storage format (key
+ * "D<port>", value empty).
+ */
+ realkey = key; /* restore it at end of loop */
+ val = "";
+ key = dupcat("D", key+1, NULL);
+ } else {
+ realkey = NULL;
+ }
+
+ if (p != buf)
+ *p++ = ',';
+ for (q = key; *q; q++) {
+ if (*q == '=' || *q == ',' || *q == '\\')
*p++ = '\\';
- if (c == '\t')
- c = '=';
- *p++ = c;
+ *p++ = *q;
}
- *p++ = ',';
- q++;
+ *p++ = '=';
+ for (q = val; *q; q++) {
+ if (*q == '=' || *q == ',' || *q == '\\')
+ *p++ = '\\';
+ *p++ = *q;
+ }
+
+ if (realkey) {
+ free(key);
+ key = realkey;
+ }
}
*p = '\0';
- write_setting_s(handle, key, buf);
+ write_setting_s(handle, outkey, buf);
sfree(buf);
}
*/
static void gprefs(void *sesskey, char *name, char *def,
const struct keyvalwhere *mapping, int nvals,
- int *array)
+ Conf *conf, int primary)
{
- char commalist[256];
+ char *commalist;
char *p, *q;
int i, j, n, v, pos;
unsigned long seen = 0; /* bitmap for weeding dups etc */
/*
* Fetch the string which we'll parse as a comma-separated list.
*/
- gpps(sesskey, name, def, commalist, sizeof(commalist));
+ commalist = gpps_raw(sesskey, name, def);
/*
* Go through that list and convert it into values.
v = key2val(mapping, nvals, q);
if (v != -1 && !(seen & (1 << v))) {
seen |= (1 << v);
- array[n++] = v;
+ conf_set_int_int(conf, primary, n, v);
+ n++;
}
}
+ sfree(commalist);
+
/*
* Now go through 'mapping' and add values that weren't mentioned
* in the list we fetched. We may have to loop over it multiple
pos = (mapping[i].where < 0 ? n : 0);
} else {
for (j = 0; j < n; j++)
- if (array[j] == mapping[i].vrel)
+ if (conf_get_int_int(conf, primary, j) ==
+ mapping[i].vrel)
break;
assert(j < n); /* implied by (seen & (1<<vrel)) */
pos = (mapping[i].where < 0 ? j : j+1);
* And add it.
*/
for (j = n-1; j >= pos; j--)
- array[j+1] = array[j];
- array[pos] = mapping[i].v;
+ conf_set_int_int(conf, primary, j+1,
+ conf_get_int_int(conf, primary, j));
+ conf_set_int_int(conf, primary, pos, mapping[i].v);
n++;
}
}
*/
static void wprefs(void *sesskey, char *name,
const struct keyvalwhere *mapping, int nvals,
- int *array)
+ Conf *conf, int primary)
{
char *buf, *p;
int i, maxlen;
for (maxlen = i = 0; i < nvals; i++) {
- const char *s = val2key(mapping, nvals, array[i]);
+ const char *s = val2key(mapping, nvals,
+ conf_get_int_int(conf, primary, i));
if (s) {
maxlen += 1 + strlen(s);
}
p = buf;
for (i = 0; i < nvals; i++) {
- const char *s = val2key(mapping, nvals, array[i]);
+ const char *s = val2key(mapping, nvals,
+ conf_get_int_int(conf, primary, i));
if (s) {
p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);
}
sfree(buf);
}
-char *save_settings(char *section, Config * cfg)
+char *save_settings(char *section, Conf *conf)
{
void *sesskey;
char *errmsg;
sesskey = open_settings_w(section, &errmsg);
if (!sesskey)
return errmsg;
- save_open_settings(sesskey, cfg);
+ save_open_settings(sesskey, conf);
close_settings_w(sesskey);
return NULL;
}
-void save_open_settings(void *sesskey, Config *cfg)
+void save_open_settings(void *sesskey, Conf *conf)
{
int i;
char *p;
write_setting_i(sesskey, "Present", 1);
- write_setting_s(sesskey, "HostName", cfg->host);
- write_setting_filename(sesskey, "LogFileName", cfg->logfilename);
- write_setting_i(sesskey, "LogType", cfg->logtype);
- write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
- write_setting_i(sesskey, "LogFlush", cfg->logflush);
- write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass);
- write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata);
+ write_setting_s(sesskey, "HostName", conf_get_str(conf, CONF_host));
+ write_setting_filename(sesskey, "LogFileName", *conf_get_filename(conf, CONF_logfilename));
+ write_setting_i(sesskey, "LogType", conf_get_int(conf, CONF_logtype));
+ write_setting_i(sesskey, "LogFileClash", conf_get_int(conf, CONF_logxfovr));
+ write_setting_i(sesskey, "LogFlush", conf_get_int(conf, CONF_logflush));
+ write_setting_i(sesskey, "SSHLogOmitPasswords", conf_get_int(conf, CONF_logomitpass));
+ write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata));
p = "raw";
{
- const Backend *b = backend_from_proto(cfg->protocol);
+ const Backend *b = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (b)
p = b->name;
}
write_setting_s(sesskey, "Protocol", p);
- write_setting_i(sesskey, "PortNumber", cfg->port);
+ write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));
/* The CloseOnExit numbers are arranged in a different order from
* the standard FORCE_ON / FORCE_OFF / AUTO. */
- write_setting_i(sesskey, "CloseOnExit", (cfg->close_on_exit+2)%3);
- write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
- write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
- write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
- write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
- write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives);
- write_setting_s(sesskey, "TerminalType", cfg->termtype);
- write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
- wmap(sesskey, "TerminalModes", cfg->ttymodes, lenof(cfg->ttymodes));
+ write_setting_i(sesskey, "CloseOnExit", (conf_get_int(conf, CONF_close_on_exit)+2)%3);
+ write_setting_i(sesskey, "WarnOnClose", !!conf_get_int(conf, CONF_warn_on_close));
+ write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60); /* minutes */
+ write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60); /* seconds */
+ write_setting_i(sesskey, "TCPNoDelay", conf_get_int(conf, CONF_tcp_nodelay));
+ write_setting_i(sesskey, "TCPKeepalives", conf_get_int(conf, CONF_tcp_keepalives));
+ write_setting_s(sesskey, "TerminalType", conf_get_str(conf, CONF_termtype));
+ write_setting_s(sesskey, "TerminalSpeed", conf_get_str(conf, CONF_termspeed));
+ wmap(sesskey, "TerminalModes", conf, CONF_ttymodes);
/* Address family selection */
- write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
+ write_setting_i(sesskey, "AddressFamily", conf_get_int(conf, CONF_addressfamily));
/* proxy settings */
- write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
- write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
- write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost);
- write_setting_i(sesskey, "ProxyMethod", cfg->proxy_type);
- write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
- write_setting_i(sesskey, "ProxyPort", cfg->proxy_port);
- write_setting_s(sesskey, "ProxyUsername", cfg->proxy_username);
- write_setting_s(sesskey, "ProxyPassword", cfg->proxy_password);
- write_setting_s(sesskey, "ProxyTelnetCommand", cfg->proxy_telnet_command);
- wmap(sesskey, "Environment", cfg->environmt, lenof(cfg->environmt));
- write_setting_s(sesskey, "UserName", cfg->username);
- write_setting_i(sesskey, "UserNameFromEnvironment", cfg->username_from_env);
- write_setting_s(sesskey, "LocalUserName", cfg->localusername);
- write_setting_i(sesskey, "NoPTY", cfg->nopty);
- write_setting_i(sesskey, "Compression", cfg->compression);
- write_setting_i(sesskey, "TryAgent", cfg->tryagent);
- write_setting_i(sesskey, "AgentFwd", cfg->agentfwd);
- write_setting_i(sesskey, "GssapiFwd", cfg->gssapifwd);
- write_setting_i(sesskey, "ChangeUsername", cfg->change_username);
- wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX,
- cfg->ssh_cipherlist);
- wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist);
- write_setting_i(sesskey, "RekeyTime", cfg->ssh_rekey_time);
- write_setting_s(sesskey, "RekeyBytes", cfg->ssh_rekey_data);
- write_setting_i(sesskey, "SshNoAuth", cfg->ssh_no_userauth);
- write_setting_i(sesskey, "SshBanner", cfg->ssh_show_banner);
- write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
- write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
- write_setting_i(sesskey, "AuthGSSAPI", cfg->try_gssapi_auth);
+ write_setting_s(sesskey, "ProxyExcludeList", conf_get_str(conf, CONF_proxy_exclude_list));
+ write_setting_i(sesskey, "ProxyDNS", (conf_get_int(conf, CONF_proxy_dns)+2)%3);
+ write_setting_i(sesskey, "ProxyLocalhost", conf_get_int(conf, CONF_even_proxy_localhost));
+ write_setting_i(sesskey, "ProxyMethod", conf_get_int(conf, CONF_proxy_type));
+ write_setting_s(sesskey, "ProxyHost", conf_get_str(conf, CONF_proxy_host));
+ write_setting_i(sesskey, "ProxyPort", conf_get_int(conf, CONF_proxy_port));
+ write_setting_s(sesskey, "ProxyUsername", conf_get_str(conf, CONF_proxy_username));
+ write_setting_s(sesskey, "ProxyPassword", conf_get_str(conf, CONF_proxy_password));
+ write_setting_s(sesskey, "ProxyTelnetCommand", conf_get_str(conf, CONF_proxy_telnet_command));
+ wmap(sesskey, "Environment", conf, CONF_environmt);
+ write_setting_s(sesskey, "UserName", conf_get_str(conf, CONF_username));
+ write_setting_i(sesskey, "UserNameFromEnvironment", conf_get_int(conf, CONF_username_from_env));
+ write_setting_s(sesskey, "LocalUserName", conf_get_str(conf, CONF_localusername));
+ write_setting_i(sesskey, "NoPTY", conf_get_int(conf, CONF_nopty));
+ write_setting_i(sesskey, "Compression", conf_get_int(conf, CONF_compression));
+ write_setting_i(sesskey, "TryAgent", conf_get_int(conf, CONF_tryagent));
+ write_setting_i(sesskey, "AgentFwd", conf_get_int(conf, CONF_agentfwd));
+ write_setting_i(sesskey, "GssapiFwd", conf_get_int(conf, CONF_gssapifwd));
+ write_setting_i(sesskey, "ChangeUsername", conf_get_int(conf, CONF_change_username));
+ wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
+ wprefs(sesskey, "KEX", kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
+ write_setting_i(sesskey, "RekeyTime", conf_get_int(conf, CONF_ssh_rekey_time));
+ write_setting_s(sesskey, "RekeyBytes", conf_get_str(conf, CONF_ssh_rekey_data));
+ write_setting_i(sesskey, "SshNoAuth", conf_get_int(conf, CONF_ssh_no_userauth));
+ write_setting_i(sesskey, "SshBanner", conf_get_int(conf, CONF_ssh_show_banner));
+ write_setting_i(sesskey, "AuthTIS", conf_get_int(conf, CONF_try_tis_auth));
+ write_setting_i(sesskey, "AuthKI", conf_get_int(conf, CONF_try_ki_auth));
+ write_setting_i(sesskey, "AuthGSSAPI", conf_get_int(conf, CONF_try_gssapi_auth));
#ifndef NO_GSSAPI
- wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs,
- cfg->ssh_gsslist);
- write_setting_filename(sesskey, "GSSCustom", cfg->ssh_gss_custom);
+ wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
+ write_setting_filename(sesskey, "GSSCustom", *conf_get_filename(conf, CONF_ssh_gss_custom));
#endif
- write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
- write_setting_i(sesskey, "SshProt", cfg->sshprot);
- write_setting_s(sesskey, "LogHost", cfg->loghost);
- write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc);
- write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile);
- write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
- write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ);
- write_setting_i(sesskey, "PassiveTelnet", cfg->passive_telnet);
- write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete);
- write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend);
- write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type);
- write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k);
- write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c);
- write_setting_i(sesskey, "NoMouseReporting", cfg->no_mouse_rep);
- write_setting_i(sesskey, "NoRemoteResize", cfg->no_remote_resize);
- write_setting_i(sesskey, "NoAltScreen", cfg->no_alt_screen);
- write_setting_i(sesskey, "NoRemoteWinTitle", cfg->no_remote_wintitle);
- write_setting_i(sesskey, "RemoteQTitleAction", cfg->remote_qtitle_action);
- write_setting_i(sesskey, "NoDBackspace", cfg->no_dbackspace);
- write_setting_i(sesskey, "NoRemoteCharset", cfg->no_remote_charset);
- write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor);
- write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad);
- write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad);
- write_setting_i(sesskey, "AltF4", cfg->alt_f4);
- write_setting_i(sesskey, "AltSpace", cfg->alt_space);
- write_setting_i(sesskey, "AltOnly", cfg->alt_only);
- write_setting_i(sesskey, "ComposeKey", cfg->compose_key);
- write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys);
- write_setting_i(sesskey, "TelnetKey", cfg->telnet_keyboard);
- write_setting_i(sesskey, "TelnetRet", cfg->telnet_newline);
- write_setting_i(sesskey, "LocalEcho", cfg->localecho);
- write_setting_i(sesskey, "LocalEdit", cfg->localedit);
- write_setting_s(sesskey, "Answerback", cfg->answerback);
- write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop);
- write_setting_i(sesskey, "FullScreenOnAltEnter", cfg->fullscreenonaltenter);
- write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr);
- write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge);
- write_setting_i(sesskey, "WindowBorder", cfg->window_border);
- write_setting_i(sesskey, "CurType", cfg->cursor_type);
- write_setting_i(sesskey, "BlinkCur", cfg->blink_cur);
- write_setting_i(sesskey, "Beep", cfg->beep);
- write_setting_i(sesskey, "BeepInd", cfg->beep_ind);
- write_setting_filename(sesskey, "BellWaveFile", cfg->bell_wavefile);
- write_setting_i(sesskey, "BellOverload", cfg->bellovl);
- write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n);
- write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t
+ write_setting_i(sesskey, "SshNoShell", conf_get_int(conf, CONF_ssh_no_shell));
+ write_setting_i(sesskey, "SshProt", conf_get_int(conf, CONF_sshprot));
+ write_setting_s(sesskey, "LogHost", conf_get_str(conf, CONF_loghost));
+ write_setting_i(sesskey, "SSH2DES", conf_get_int(conf, CONF_ssh2_des_cbc));
+ write_setting_filename(sesskey, "PublicKeyFile", *conf_get_filename(conf, CONF_keyfile));
+ write_setting_s(sesskey, "RemoteCommand", conf_get_str(conf, CONF_remote_cmd));
+ write_setting_i(sesskey, "RFCEnviron", conf_get_int(conf, CONF_rfc_environ));
+ write_setting_i(sesskey, "PassiveTelnet", conf_get_int(conf, CONF_passive_telnet));
+ write_setting_i(sesskey, "BackspaceIsDelete", conf_get_int(conf, CONF_bksp_is_delete));
+ write_setting_i(sesskey, "RXVTHomeEnd", conf_get_int(conf, CONF_rxvt_homeend));
+ write_setting_i(sesskey, "LinuxFunctionKeys", conf_get_int(conf, CONF_funky_type));
+ write_setting_i(sesskey, "NoApplicationKeys", conf_get_int(conf, CONF_no_applic_k));
+ write_setting_i(sesskey, "NoApplicationCursors", conf_get_int(conf, CONF_no_applic_c));
+ write_setting_i(sesskey, "NoMouseReporting", conf_get_int(conf, CONF_no_mouse_rep));
+ write_setting_i(sesskey, "NoRemoteResize", conf_get_int(conf, CONF_no_remote_resize));
+ write_setting_i(sesskey, "NoAltScreen", conf_get_int(conf, CONF_no_alt_screen));
+ write_setting_i(sesskey, "NoRemoteWinTitle", conf_get_int(conf, CONF_no_remote_wintitle));
+ write_setting_i(sesskey, "RemoteQTitleAction", conf_get_int(conf, CONF_remote_qtitle_action));
+ write_setting_i(sesskey, "NoDBackspace", conf_get_int(conf, CONF_no_dbackspace));
+ write_setting_i(sesskey, "NoRemoteCharset", conf_get_int(conf, CONF_no_remote_charset));
+ write_setting_i(sesskey, "ApplicationCursorKeys", conf_get_int(conf, CONF_app_cursor));
+ write_setting_i(sesskey, "ApplicationKeypad", conf_get_int(conf, CONF_app_keypad));
+ write_setting_i(sesskey, "NetHackKeypad", conf_get_int(conf, CONF_nethack_keypad));
+ write_setting_i(sesskey, "AltF4", conf_get_int(conf, CONF_alt_f4));
+ write_setting_i(sesskey, "AltSpace", conf_get_int(conf, CONF_alt_space));
+ write_setting_i(sesskey, "AltOnly", conf_get_int(conf, CONF_alt_only));
+ write_setting_i(sesskey, "ComposeKey", conf_get_int(conf, CONF_compose_key));
+ write_setting_i(sesskey, "CtrlAltKeys", conf_get_int(conf, CONF_ctrlaltkeys));
+ write_setting_i(sesskey, "TelnetKey", conf_get_int(conf, CONF_telnet_keyboard));
+ write_setting_i(sesskey, "TelnetRet", conf_get_int(conf, CONF_telnet_newline));
+ write_setting_i(sesskey, "LocalEcho", conf_get_int(conf, CONF_localecho));
+ write_setting_i(sesskey, "LocalEdit", conf_get_int(conf, CONF_localedit));
+ write_setting_s(sesskey, "Answerback", conf_get_str(conf, CONF_answerback));
+ write_setting_i(sesskey, "AlwaysOnTop", conf_get_int(conf, CONF_alwaysontop));
+ write_setting_i(sesskey, "FullScreenOnAltEnter", conf_get_int(conf, CONF_fullscreenonaltenter));
+ write_setting_i(sesskey, "HideMousePtr", conf_get_int(conf, CONF_hide_mouseptr));
+ write_setting_i(sesskey, "SunkenEdge", conf_get_int(conf, CONF_sunken_edge));
+ write_setting_i(sesskey, "WindowBorder", conf_get_int(conf, CONF_window_border));
+ write_setting_i(sesskey, "CurType", conf_get_int(conf, CONF_cursor_type));
+ write_setting_i(sesskey, "BlinkCur", conf_get_int(conf, CONF_blink_cur));
+ write_setting_i(sesskey, "Beep", conf_get_int(conf, CONF_beep));
+ write_setting_i(sesskey, "BeepInd", conf_get_int(conf, CONF_beep_ind));
+ write_setting_filename(sesskey, "BellWaveFile", *conf_get_filename(conf, CONF_bell_wavefile));
+ write_setting_i(sesskey, "BellOverload", conf_get_int(conf, CONF_bellovl));
+ write_setting_i(sesskey, "BellOverloadN", conf_get_int(conf, CONF_bellovl_n));
+ write_setting_i(sesskey, "BellOverloadT", conf_get_int(conf, CONF_bellovl_t)
#ifdef PUTTY_UNIX_H
* 1000
#endif
);
- write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s
+ write_setting_i(sesskey, "BellOverloadS", conf_get_int(conf, CONF_bellovl_s)
#ifdef PUTTY_UNIX_H
* 1000
#endif
);
- write_setting_i(sesskey, "ScrollbackLines", cfg->savelines);
- write_setting_i(sesskey, "DECOriginMode", cfg->dec_om);
- write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode);
- write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr);
- write_setting_i(sesskey, "CRImpliesLF", cfg->crhaslf);
- write_setting_i(sesskey, "DisableArabicShaping", cfg->arabicshaping);
- write_setting_i(sesskey, "DisableBidi", cfg->bidi);
- write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always);
- write_setting_s(sesskey, "WinTitle", cfg->wintitle);
- write_setting_i(sesskey, "TermWidth", cfg->width);
- write_setting_i(sesskey, "TermHeight", cfg->height);
- write_setting_fontspec(sesskey, "Font", cfg->font);
- write_setting_i(sesskey, "FontQuality", cfg->font_quality);
- write_setting_i(sesskey, "FontVTMode", cfg->vtmode);
- write_setting_i(sesskey, "UseSystemColours", cfg->system_colour);
- write_setting_i(sesskey, "TryPalette", cfg->try_palette);
- write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour);
- write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour);
- write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour);
+ write_setting_i(sesskey, "ScrollbackLines", conf_get_int(conf, CONF_savelines));
+ write_setting_i(sesskey, "DECOriginMode", conf_get_int(conf, CONF_dec_om));
+ write_setting_i(sesskey, "AutoWrapMode", conf_get_int(conf, CONF_wrap_mode));
+ write_setting_i(sesskey, "LFImpliesCR", conf_get_int(conf, CONF_lfhascr));
+ write_setting_i(sesskey, "CRImpliesLF", conf_get_int(conf, CONF_crhaslf));
+ write_setting_i(sesskey, "DisableArabicShaping", conf_get_int(conf, CONF_arabicshaping));
+ write_setting_i(sesskey, "DisableBidi", conf_get_int(conf, CONF_bidi));
+ write_setting_i(sesskey, "WinNameAlways", conf_get_int(conf, CONF_win_name_always));
+ write_setting_s(sesskey, "WinTitle", conf_get_str(conf, CONF_wintitle));
+ write_setting_i(sesskey, "TermWidth", conf_get_int(conf, CONF_width));
+ write_setting_i(sesskey, "TermHeight", conf_get_int(conf, CONF_height));
+ write_setting_fontspec(sesskey, "Font", *conf_get_fontspec(conf, CONF_font));
+ write_setting_i(sesskey, "FontQuality", conf_get_int(conf, CONF_font_quality));
+ write_setting_i(sesskey, "FontVTMode", conf_get_int(conf, CONF_vtmode));
+ write_setting_i(sesskey, "UseSystemColours", conf_get_int(conf, CONF_system_colour));
+ write_setting_i(sesskey, "TryPalette", conf_get_int(conf, CONF_try_palette));
+ write_setting_i(sesskey, "ANSIColour", conf_get_int(conf, CONF_ansi_colour));
+ write_setting_i(sesskey, "Xterm256Colour", conf_get_int(conf, CONF_xterm_256_colour));
+ write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_colour));
for (i = 0; i < 22; i++) {
char buf[20], buf2[30];
sprintf(buf, "Colour%d", i);
- sprintf(buf2, "%d,%d,%d", cfg->colours[i][0],
- cfg->colours[i][1], cfg->colours[i][2]);
+ sprintf(buf2, "%d,%d,%d",
+ conf_get_int_int(conf, CONF_colours, i*3+0),
+ conf_get_int_int(conf, CONF_colours, i*3+1),
+ conf_get_int_int(conf, CONF_colours, i*3+2));
write_setting_s(sesskey, buf, buf2);
}
- write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
- write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste);
- write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
- write_setting_i(sesskey, "RectSelect", cfg->rect_select);
- write_setting_i(sesskey, "MouseOverride", cfg->mouse_override);
+ write_setting_i(sesskey, "RawCNP", conf_get_int(conf, CONF_rawcnp));
+ write_setting_i(sesskey, "PasteRTF", conf_get_int(conf, CONF_rtf_paste));
+ write_setting_i(sesskey, "MouseIsXterm", conf_get_int(conf, CONF_mouse_is_xterm));
+ write_setting_i(sesskey, "RectSelect", conf_get_int(conf, CONF_rect_select));
+ write_setting_i(sesskey, "MouseOverride", conf_get_int(conf, CONF_mouse_override));
for (i = 0; i < 256; i += 32) {
char buf[20], buf2[256];
int j;
*buf2 = '\0';
for (j = i; j < i + 32; j++) {
sprintf(buf2 + strlen(buf2), "%s%d",
- (*buf2 ? "," : ""), cfg->wordness[j]);
+ (*buf2 ? "," : ""),
+ conf_get_int_int(conf, CONF_wordness, j));
}
write_setting_s(sesskey, buf, buf2);
}
- write_setting_s(sesskey, "LineCodePage", cfg->line_codepage);
- write_setting_i(sesskey, "CJKAmbigWide", cfg->cjk_ambig_wide);
- write_setting_i(sesskey, "UTF8Override", cfg->utf8_override);
- write_setting_s(sesskey, "Printer", cfg->printer);
- write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
- write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
- write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen);
- write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key);
- write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp);
- write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback);
- write_setting_i(sesskey, "LockSize", cfg->resize_action);
- write_setting_i(sesskey, "BCE", cfg->bce);
- write_setting_i(sesskey, "BlinkText", cfg->blinktext);
- write_setting_i(sesskey, "X11Forward", cfg->x11_forward);
- write_setting_s(sesskey, "X11Display", cfg->x11_display);
- write_setting_i(sesskey, "X11AuthType", cfg->x11_auth);
- write_setting_filename(sesskey, "X11AuthFile", cfg->xauthfile);
- write_setting_i(sesskey, "LocalPortAcceptAll", cfg->lport_acceptall);
- write_setting_i(sesskey, "RemotePortAcceptAll", cfg->rport_acceptall);
- wmap(sesskey, "PortForwardings", cfg->portfwd, lenof(cfg->portfwd));
- write_setting_i(sesskey, "BugIgnore1", 2-cfg->sshbug_ignore1);
- write_setting_i(sesskey, "BugPlainPW1", 2-cfg->sshbug_plainpw1);
- write_setting_i(sesskey, "BugRSA1", 2-cfg->sshbug_rsa1);
- write_setting_i(sesskey, "BugIgnore2", 2-cfg->sshbug_ignore2);
- write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2);
- write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
- write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
- write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
- write_setting_i(sesskey, "BugRekey2", 2-cfg->sshbug_rekey2);
- write_setting_i(sesskey, "BugMaxPkt2", 2-cfg->sshbug_maxpkt2);
- write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
- write_setting_i(sesskey, "LoginShell", cfg->login_shell);
- write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left);
- write_setting_fontspec(sesskey, "BoldFont", cfg->boldfont);
- write_setting_fontspec(sesskey, "WideFont", cfg->widefont);
- write_setting_fontspec(sesskey, "WideBoldFont", cfg->wideboldfont);
- write_setting_i(sesskey, "ShadowBold", cfg->shadowbold);
- write_setting_i(sesskey, "ShadowBoldOffset", cfg->shadowboldoffset);
- write_setting_s(sesskey, "SerialLine", cfg->serline);
- write_setting_i(sesskey, "SerialSpeed", cfg->serspeed);
- write_setting_i(sesskey, "SerialDataBits", cfg->serdatabits);
- write_setting_i(sesskey, "SerialStopHalfbits", cfg->serstopbits);
- write_setting_i(sesskey, "SerialParity", cfg->serparity);
- write_setting_i(sesskey, "SerialFlowControl", cfg->serflow);
- write_setting_s(sesskey, "WindowClass", cfg->winclass);
+ write_setting_s(sesskey, "LineCodePage", conf_get_str(conf, CONF_line_codepage));
+ write_setting_i(sesskey, "CJKAmbigWide", conf_get_int(conf, CONF_cjk_ambig_wide));
+ write_setting_i(sesskey, "UTF8Override", conf_get_int(conf, CONF_utf8_override));
+ write_setting_s(sesskey, "Printer", conf_get_str(conf, CONF_printer));
+ write_setting_i(sesskey, "CapsLockCyr", conf_get_int(conf, CONF_xlat_capslockcyr));
+ write_setting_i(sesskey, "ScrollBar", conf_get_int(conf, CONF_scrollbar));
+ write_setting_i(sesskey, "ScrollBarFullScreen", conf_get_int(conf, CONF_scrollbar_in_fullscreen));
+ write_setting_i(sesskey, "ScrollOnKey", conf_get_int(conf, CONF_scroll_on_key));
+ write_setting_i(sesskey, "ScrollOnDisp", conf_get_int(conf, CONF_scroll_on_disp));
+ write_setting_i(sesskey, "EraseToScrollback", conf_get_int(conf, CONF_erase_to_scrollback));
+ write_setting_i(sesskey, "LockSize", conf_get_int(conf, CONF_resize_action));
+ write_setting_i(sesskey, "BCE", conf_get_int(conf, CONF_bce));
+ write_setting_i(sesskey, "BlinkText", conf_get_int(conf, CONF_blinktext));
+ write_setting_i(sesskey, "X11Forward", conf_get_int(conf, CONF_x11_forward));
+ write_setting_s(sesskey, "X11Display", conf_get_str(conf, CONF_x11_display));
+ write_setting_i(sesskey, "X11AuthType", conf_get_int(conf, CONF_x11_auth));
+ write_setting_filename(sesskey, "X11AuthFile", *conf_get_filename(conf, CONF_xauthfile));
+ write_setting_i(sesskey, "LocalPortAcceptAll", conf_get_int(conf, CONF_lport_acceptall));
+ write_setting_i(sesskey, "RemotePortAcceptAll", conf_get_int(conf, CONF_rport_acceptall));
+ wmap(sesskey, "PortForwardings", conf, CONF_portfwd);
+ write_setting_i(sesskey, "BugIgnore1", 2-conf_get_int(conf, CONF_sshbug_ignore1));
+ write_setting_i(sesskey, "BugPlainPW1", 2-conf_get_int(conf, CONF_sshbug_plainpw1));
+ write_setting_i(sesskey, "BugRSA1", 2-conf_get_int(conf, CONF_sshbug_rsa1));
+ write_setting_i(sesskey, "BugIgnore2", 2-conf_get_int(conf, CONF_sshbug_ignore2));
+ write_setting_i(sesskey, "BugHMAC2", 2-conf_get_int(conf, CONF_sshbug_hmac2));
+ write_setting_i(sesskey, "BugDeriveKey2", 2-conf_get_int(conf, CONF_sshbug_derivekey2));
+ write_setting_i(sesskey, "BugRSAPad2", 2-conf_get_int(conf, CONF_sshbug_rsapad2));
+ write_setting_i(sesskey, "BugPKSessID2", 2-conf_get_int(conf, CONF_sshbug_pksessid2));
+ write_setting_i(sesskey, "BugRekey2", 2-conf_get_int(conf, CONF_sshbug_rekey2));
+ write_setting_i(sesskey, "BugMaxPkt2", 2-conf_get_int(conf, CONF_sshbug_maxpkt2));
+ write_setting_i(sesskey, "StampUtmp", conf_get_int(conf, CONF_stamp_utmp));
+ write_setting_i(sesskey, "LoginShell", conf_get_int(conf, CONF_login_shell));
+ write_setting_i(sesskey, "ScrollbarOnLeft", conf_get_int(conf, CONF_scrollbar_on_left));
+ write_setting_fontspec(sesskey, "BoldFont", *conf_get_fontspec(conf, CONF_boldfont));
+ write_setting_fontspec(sesskey, "WideFont", *conf_get_fontspec(conf, CONF_widefont));
+ write_setting_fontspec(sesskey, "WideBoldFont", *conf_get_fontspec(conf, CONF_wideboldfont));
+ write_setting_i(sesskey, "ShadowBold", conf_get_int(conf, CONF_shadowbold));
+ write_setting_i(sesskey, "ShadowBoldOffset", conf_get_int(conf, CONF_shadowboldoffset));
+ write_setting_s(sesskey, "SerialLine", conf_get_str(conf, CONF_serline));
+ write_setting_i(sesskey, "SerialSpeed", conf_get_int(conf, CONF_serspeed));
+ write_setting_i(sesskey, "SerialDataBits", conf_get_int(conf, CONF_serdatabits));
+ write_setting_i(sesskey, "SerialStopHalfbits", conf_get_int(conf, CONF_serstopbits));
+ write_setting_i(sesskey, "SerialParity", conf_get_int(conf, CONF_serparity));
+ write_setting_i(sesskey, "SerialFlowControl", conf_get_int(conf, CONF_serflow));
+ write_setting_s(sesskey, "WindowClass", conf_get_str(conf, CONF_winclass));
}
-void load_settings(char *section, Config * cfg)
+void load_settings(char *section, Conf *conf)
{
void *sesskey;
sesskey = open_settings_r(section);
- load_open_settings(sesskey, cfg);
+ load_open_settings(sesskey, conf);
close_settings_r(sesskey);
- if (cfg_launchable(cfg))
+ if (conf_launchable(conf))
add_session_to_jumplist(section);
}
-void load_open_settings(void *sesskey, Config *cfg)
+void load_open_settings(void *sesskey, Conf *conf)
{
int i;
- char prot[10];
-
- cfg->ssh_subsys = 0; /* FIXME: load this properly */
- cfg->remote_cmd_ptr = NULL;
- cfg->remote_cmd_ptr2 = NULL;
- cfg->ssh_nc_host[0] = '\0';
-
- gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
- gppfile(sesskey, "LogFileName", &cfg->logfilename);
- gppi(sesskey, "LogType", 0, &cfg->logtype);
- gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
- gppi(sesskey, "LogFlush", 1, &cfg->logflush);
- gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass);
- gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata);
-
- gpps(sesskey, "Protocol", "default", prot, 10);
- cfg->protocol = default_protocol;
- cfg->port = default_port;
+ char *prot;
+
+ conf_set_int(conf, CONF_ssh_subsys, 0); /* FIXME: load this properly */
+ conf_set_str(conf, CONF_remote_cmd, "");
+ conf_set_str(conf, CONF_remote_cmd2, "");
+ conf_set_str(conf, CONF_ssh_nc_host, "");
+
+ gpps(sesskey, "HostName", "", conf, CONF_host);
+ gppfile(sesskey, "LogFileName", conf, CONF_logfilename);
+ gppi(sesskey, "LogType", 0, conf, CONF_logtype);
+ gppi(sesskey, "LogFileClash", LGXF_ASK, conf, CONF_logxfovr);
+ gppi(sesskey, "LogFlush", 1, conf, CONF_logflush);
+ gppi(sesskey, "SSHLogOmitPasswords", 1, conf, CONF_logomitpass);
+ gppi(sesskey, "SSHLogOmitData", 0, conf, CONF_logomitdata);
+
+ prot = gpps_raw(sesskey, "Protocol", "default");
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
{
const Backend *b = backend_from_name(prot);
if (b) {
- cfg->protocol = b->protocol;
- gppi(sesskey, "PortNumber", default_port, &cfg->port);
+ conf_set_int(conf, CONF_protocol, b->protocol);
+ gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
}
}
+ sfree(prot);
/* Address family selection */
- gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
+ gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, conf, CONF_addressfamily);
/* The CloseOnExit numbers are arranged in a different order from
* the standard FORCE_ON / FORCE_OFF / AUTO. */
- gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
- gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close);
+ i = gppi_raw(sesskey, "CloseOnExit", 1); conf_set_int(conf, CONF_close_on_exit, (i+1)%3);
+ gppi(sesskey, "WarnOnClose", 1, conf, CONF_warn_on_close);
{
/* This is two values for backward compatibility with 0.50/0.51 */
int pingmin, pingsec;
- gppi(sesskey, "PingInterval", 0, &pingmin);
- gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
- cfg->ping_interval = pingmin * 60 + pingsec;
+ pingmin = gppi_raw(sesskey, "PingInterval", 0);
+ pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);
+ conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);
}
- gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
- gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives);
- gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
- sizeof(cfg->termtype));
- gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
- sizeof(cfg->termspeed));
- {
+ gppi(sesskey, "TCPNoDelay", 1, conf, CONF_tcp_nodelay);
+ gppi(sesskey, "TCPKeepalives", 0, conf, CONF_tcp_keepalives);
+ gpps(sesskey, "TerminalType", "xterm", conf, CONF_termtype);
+ gpps(sesskey, "TerminalSpeed", "38400,38400", conf, CONF_termspeed);
+ if (!gppmap(sesskey, "TerminalModes", conf, CONF_ttymodes)) {
/* This hardcodes a big set of defaults in any new saved
* sessions. Let's hope we don't change our mind. */
- int i;
- char *def = dupstr("");
- /* Default: all set to "auto" */
- for (i = 0; ttymodes[i]; i++) {
- char *def2 = dupprintf("%s%s=A,", def, ttymodes[i]);
- sfree(def);
- def = def2;
- }
- gppmap(sesskey, "TerminalModes", def,
- cfg->ttymodes, lenof(cfg->ttymodes));
- sfree(def);
+ for (i = 0; ttymodes[i]; i++)
+ conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");
}
/* proxy settings */
- gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list,
- sizeof(cfg->proxy_exclude_list));
- gppi(sesskey, "ProxyDNS", 1, &i); cfg->proxy_dns = (i+1)%3;
- gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost);
- gppi(sesskey, "ProxyMethod", -1, &cfg->proxy_type);
- if (cfg->proxy_type == -1) {
+ gpps(sesskey, "ProxyExcludeList", "", conf, CONF_proxy_exclude_list);
+ i = gppi_raw(sesskey, "ProxyDNS", 1); conf_set_int(conf, CONF_proxy_dns, (i+1)%3);
+ gppi(sesskey, "ProxyLocalhost", 0, conf, CONF_even_proxy_localhost);
+ gppi(sesskey, "ProxyMethod", -1, conf, CONF_proxy_type);
+ if (conf_get_int(conf, CONF_proxy_type) == -1) {
int i;
- gppi(sesskey, "ProxyType", 0, &i);
+ i = gppi_raw(sesskey, "ProxyType", 0);
if (i == 0)
- cfg->proxy_type = PROXY_NONE;
+ conf_set_int(conf, CONF_proxy_type, PROXY_NONE);
else if (i == 1)
- cfg->proxy_type = PROXY_HTTP;
+ conf_set_int(conf, CONF_proxy_type, PROXY_HTTP);
else if (i == 3)
- cfg->proxy_type = PROXY_TELNET;
+ conf_set_int(conf, CONF_proxy_type, PROXY_TELNET);
else if (i == 4)
- cfg->proxy_type = PROXY_CMD;
+ conf_set_int(conf, CONF_proxy_type, PROXY_CMD);
else {
- gppi(sesskey, "ProxySOCKSVersion", 5, &i);
+ i = gppi_raw(sesskey, "ProxySOCKSVersion", 5);
if (i == 5)
- cfg->proxy_type = PROXY_SOCKS5;
+ conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS5);
else
- cfg->proxy_type = PROXY_SOCKS4;
+ conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS4);
}
}
- gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,
- sizeof(cfg->proxy_host));
- gppi(sesskey, "ProxyPort", 80, &cfg->proxy_port);
- gpps(sesskey, "ProxyUsername", "", cfg->proxy_username,
- sizeof(cfg->proxy_username));
- gpps(sesskey, "ProxyPassword", "", cfg->proxy_password,
- sizeof(cfg->proxy_password));
+ gpps(sesskey, "ProxyHost", "proxy", conf, CONF_proxy_host);
+ gppi(sesskey, "ProxyPort", 80, conf, CONF_proxy_port);
+ gpps(sesskey, "ProxyUsername", "", conf, CONF_proxy_username);
+ gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);
gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
- cfg->proxy_telnet_command, sizeof(cfg->proxy_telnet_command));
- gppmap(sesskey, "Environment", "", cfg->environmt, lenof(cfg->environmt));
- gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
- gppi(sesskey, "UserNameFromEnvironment", 0, &cfg->username_from_env);
- gpps(sesskey, "LocalUserName", "", cfg->localusername,
- sizeof(cfg->localusername));
- gppi(sesskey, "NoPTY", 0, &cfg->nopty);
- gppi(sesskey, "Compression", 0, &cfg->compression);
- gppi(sesskey, "TryAgent", 1, &cfg->tryagent);
- gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd);
- gppi(sesskey, "ChangeUsername", 0, &cfg->change_username);
- gppi(sesskey, "GssapiFwd", 0, &cfg->gssapifwd);
+ conf, CONF_proxy_telnet_command);
+ gppmap(sesskey, "Environment", conf, CONF_environmt);
+ gpps(sesskey, "UserName", "", conf, CONF_username);
+ gppi(sesskey, "UserNameFromEnvironment", 0, conf, CONF_username_from_env);
+ gpps(sesskey, "LocalUserName", "", conf, CONF_localusername);
+ gppi(sesskey, "NoPTY", 0, conf, CONF_nopty);
+ gppi(sesskey, "Compression", 0, conf, CONF_compression);
+ gppi(sesskey, "TryAgent", 1, conf, CONF_tryagent);
+ gppi(sesskey, "AgentFwd", 0, conf, CONF_agentfwd);
+ gppi(sesskey, "ChangeUsername", 0, conf, CONF_change_username);
+ gppi(sesskey, "GssapiFwd", 0, conf, CONF_gssapifwd);
gprefs(sesskey, "Cipher", "\0",
- ciphernames, CIPHER_MAX, cfg->ssh_cipherlist);
+ ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
{
/* Backward-compatibility: we used to have an option to
* disable gex under the "bugs" panel after one report of
* a server which offered it then choked, but we never got
* a server version string or any other reports. */
char *default_kexes;
- gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i;
+ i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);
if (i == FORCE_ON)
default_kexes = "dh-group14-sha1,dh-group1-sha1,rsa,WARN,dh-gex-sha1";
else
default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN";
gprefs(sesskey, "KEX", default_kexes,
- kexnames, KEX_MAX, cfg->ssh_kexlist);
+ kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
}
- gppi(sesskey, "RekeyTime", 60, &cfg->ssh_rekey_time);
- gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data,
- sizeof(cfg->ssh_rekey_data));
- gppi(sesskey, "SshProt", 2, &cfg->sshprot);
- gpps(sesskey, "LogHost", "", cfg->loghost, sizeof(cfg->loghost));
- gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
- gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth);
- gppi(sesskey, "SshBanner", 1, &cfg->ssh_show_banner);
- gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
- gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth);
- gppi(sesskey, "AuthGSSAPI", 1, &cfg->try_gssapi_auth);
+ gppi(sesskey, "RekeyTime", 60, conf, CONF_ssh_rekey_time);
+ gpps(sesskey, "RekeyBytes", "1G", conf, CONF_ssh_rekey_data);
+ gppi(sesskey, "SshProt", 2, conf, CONF_sshprot);
+ gpps(sesskey, "LogHost", "", conf, CONF_loghost);
+ gppi(sesskey, "SSH2DES", 0, conf, CONF_ssh2_des_cbc);
+ gppi(sesskey, "SshNoAuth", 0, conf, CONF_ssh_no_userauth);
+ gppi(sesskey, "SshBanner", 1, conf, CONF_ssh_show_banner);
+ gppi(sesskey, "AuthTIS", 0, conf, CONF_try_tis_auth);
+ gppi(sesskey, "AuthKI", 1, conf, CONF_try_ki_auth);
+ gppi(sesskey, "AuthGSSAPI", 1, conf, CONF_try_gssapi_auth);
#ifndef NO_GSSAPI
gprefs(sesskey, "GSSLibs", "\0",
- gsslibkeywords, ngsslibs, cfg->ssh_gsslist);
- gppfile(sesskey, "GSSCustom", &cfg->ssh_gss_custom);
+ gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
+ gppfile(sesskey, "GSSCustom", conf, CONF_ssh_gss_custom);
#endif
- gppi(sesskey, "SshNoShell", 0, &cfg->ssh_no_shell);
- gppfile(sesskey, "PublicKeyFile", &cfg->keyfile);
- gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd,
- sizeof(cfg->remote_cmd));
- gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ);
- gppi(sesskey, "PassiveTelnet", 0, &cfg->passive_telnet);
- gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete);
- gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend);
- gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type);
- gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k);
- gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c);
- gppi(sesskey, "NoMouseReporting", 0, &cfg->no_mouse_rep);
- gppi(sesskey, "NoRemoteResize", 0, &cfg->no_remote_resize);
- gppi(sesskey, "NoAltScreen", 0, &cfg->no_alt_screen);
- gppi(sesskey, "NoRemoteWinTitle", 0, &cfg->no_remote_wintitle);
+ gppi(sesskey, "SshNoShell", 0, conf, CONF_ssh_no_shell);
+ gppfile(sesskey, "PublicKeyFile", conf, CONF_keyfile);
+ gpps(sesskey, "RemoteCommand", "", conf, CONF_remote_cmd);
+ gppi(sesskey, "RFCEnviron", 0, conf, CONF_rfc_environ);
+ gppi(sesskey, "PassiveTelnet", 0, conf, CONF_passive_telnet);
+ gppi(sesskey, "BackspaceIsDelete", 1, conf, CONF_bksp_is_delete);
+ gppi(sesskey, "RXVTHomeEnd", 0, conf, CONF_rxvt_homeend);
+ gppi(sesskey, "LinuxFunctionKeys", 0, conf, CONF_funky_type);
+ gppi(sesskey, "NoApplicationKeys", 0, conf, CONF_no_applic_k);
+ gppi(sesskey, "NoApplicationCursors", 0, conf, CONF_no_applic_c);
+ gppi(sesskey, "NoMouseReporting", 0, conf, CONF_no_mouse_rep);
+ gppi(sesskey, "NoRemoteResize", 0, conf, CONF_no_remote_resize);
+ gppi(sesskey, "NoAltScreen", 0, conf, CONF_no_alt_screen);
+ gppi(sesskey, "NoRemoteWinTitle", 0, conf, CONF_no_remote_wintitle);
{
/* Backward compatibility */
- int no_remote_qtitle;
- gppi(sesskey, "NoRemoteQTitle", 1, &no_remote_qtitle);
+ int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);
/* We deliberately interpret the old setting of "no response" as
* "empty string". This changes the behaviour, but hopefully for
* the better; the user can always recover the old behaviour. */
gppi(sesskey, "RemoteQTitleAction",
no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
- &cfg->remote_qtitle_action);
+ conf, CONF_remote_qtitle_action);
}
- gppi(sesskey, "NoDBackspace", 0, &cfg->no_dbackspace);
- gppi(sesskey, "NoRemoteCharset", 0, &cfg->no_remote_charset);
- gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor);
- gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad);
- gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad);
- gppi(sesskey, "AltF4", 1, &cfg->alt_f4);
- gppi(sesskey, "AltSpace", 0, &cfg->alt_space);
- gppi(sesskey, "AltOnly", 0, &cfg->alt_only);
- gppi(sesskey, "ComposeKey", 0, &cfg->compose_key);
- gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys);
- gppi(sesskey, "TelnetKey", 0, &cfg->telnet_keyboard);
- gppi(sesskey, "TelnetRet", 1, &cfg->telnet_newline);
- gppi(sesskey, "LocalEcho", AUTO, &cfg->localecho);
- gppi(sesskey, "LocalEdit", AUTO, &cfg->localedit);
- gpps(sesskey, "Answerback", "PuTTY", cfg->answerback,
- sizeof(cfg->answerback));
- gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop);
- gppi(sesskey, "FullScreenOnAltEnter", 0, &cfg->fullscreenonaltenter);
- gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr);
- gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge);
- gppi(sesskey, "WindowBorder", 1, &cfg->window_border);
- gppi(sesskey, "CurType", 0, &cfg->cursor_type);
- gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur);
- /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */
- gppi(sesskey, "Beep", 1, &cfg->beep);
- gppi(sesskey, "BeepInd", 0, &cfg->beep_ind);
- gppfile(sesskey, "BellWaveFile", &cfg->bell_wavefile);
- gppi(sesskey, "BellOverload", 1, &cfg->bellovl);
- gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n);
- gppi(sesskey, "BellOverloadT", 2*TICKSPERSEC
+ gppi(sesskey, "NoDBackspace", 0, conf, CONF_no_dbackspace);
+ gppi(sesskey, "NoRemoteCharset", 0, conf, CONF_no_remote_charset);
+ gppi(sesskey, "ApplicationCursorKeys", 0, conf, CONF_app_cursor);
+ gppi(sesskey, "ApplicationKeypad", 0, conf, CONF_app_keypad);
+ gppi(sesskey, "NetHackKeypad", 0, conf, CONF_nethack_keypad);
+ gppi(sesskey, "AltF4", 1, conf, CONF_alt_f4);
+ gppi(sesskey, "AltSpace", 0, conf, CONF_alt_space);
+ gppi(sesskey, "AltOnly", 0, conf, CONF_alt_only);
+ gppi(sesskey, "ComposeKey", 0, conf, CONF_compose_key);
+ gppi(sesskey, "CtrlAltKeys", 1, conf, CONF_ctrlaltkeys);
+ gppi(sesskey, "TelnetKey", 0, conf, CONF_telnet_keyboard);
+ gppi(sesskey, "TelnetRet", 1, conf, CONF_telnet_newline);
+ gppi(sesskey, "LocalEcho", AUTO, conf, CONF_localecho);
+ gppi(sesskey, "LocalEdit", AUTO, conf, CONF_localedit);
+ gpps(sesskey, "Answerback", "PuTTY", conf, CONF_answerback);
+ gppi(sesskey, "AlwaysOnTop", 0, conf, CONF_alwaysontop);
+ gppi(sesskey, "FullScreenOnAltEnter", 0, conf, CONF_fullscreenonaltenter);
+ gppi(sesskey, "HideMousePtr", 0, conf, CONF_hide_mouseptr);
+ gppi(sesskey, "SunkenEdge", 0, conf, CONF_sunken_edge);
+ gppi(sesskey, "WindowBorder", 1, conf, CONF_window_border);
+ gppi(sesskey, "CurType", 0, conf, CONF_cursor_type);
+ gppi(sesskey, "BlinkCur", 0, conf, CONF_blink_cur);
+ /* pedantic compiler tells me I can't use conf, CONF_beep as an int * :-) */
+ gppi(sesskey, "Beep", 1, conf, CONF_beep);
+ gppi(sesskey, "BeepInd", 0, conf, CONF_beep_ind);
+ gppfile(sesskey, "BellWaveFile", conf, CONF_bell_wavefile);
+ gppi(sesskey, "BellOverload", 1, conf, CONF_bellovl);
+ gppi(sesskey, "BellOverloadN", 5, conf, CONF_bellovl_n);
+ i = gppi_raw(sesskey, "BellOverloadT", 2*TICKSPERSEC
#ifdef PUTTY_UNIX_H
*1000
#endif
- , &i);
- cfg->bellovl_t = i
+ );
+ conf_set_int(conf, CONF_bellovl_t, i
#ifdef PUTTY_UNIX_H
- / 1000
+ / 1000
#endif
- ;
- gppi(sesskey, "BellOverloadS", 5*TICKSPERSEC
+ );
+ i = gppi_raw(sesskey, "BellOverloadS", 5*TICKSPERSEC
#ifdef PUTTY_UNIX_H
*1000
#endif
- , &i);
- cfg->bellovl_s = i
+ );
+ conf_set_int(conf, CONF_bellovl_s, i
#ifdef PUTTY_UNIX_H
- / 1000
+ / 1000
#endif
- ;
- gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines);
- gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om);
- gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode);
- gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr);
- gppi(sesskey, "CRImpliesLF", 0, &cfg->crhaslf);
- gppi(sesskey, "DisableArabicShaping", 0, &cfg->arabicshaping);
- gppi(sesskey, "DisableBidi", 0, &cfg->bidi);
- gppi(sesskey, "WinNameAlways", 1, &cfg->win_name_always);
- gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle));
- gppi(sesskey, "TermWidth", 80, &cfg->width);
- gppi(sesskey, "TermHeight", 24, &cfg->height);
- gppfont(sesskey, "Font", &cfg->font);
- gppi(sesskey, "FontQuality", FQ_DEFAULT, &cfg->font_quality);
- gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode);
- gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour);
- gppi(sesskey, "TryPalette", 0, &cfg->try_palette);
- gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour);
- gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour);
- gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
+ );
+ gppi(sesskey, "ScrollbackLines", 200, conf, CONF_savelines);
+ gppi(sesskey, "DECOriginMode", 0, conf, CONF_dec_om);
+ gppi(sesskey, "AutoWrapMode", 1, conf, CONF_wrap_mode);
+ gppi(sesskey, "LFImpliesCR", 0, conf, CONF_lfhascr);
+ gppi(sesskey, "CRImpliesLF", 0, conf, CONF_crhaslf);
+ gppi(sesskey, "DisableArabicShaping", 0, conf, CONF_arabicshaping);
+ gppi(sesskey, "DisableBidi", 0, conf, CONF_bidi);
+ gppi(sesskey, "WinNameAlways", 1, conf, CONF_win_name_always);
+ gpps(sesskey, "WinTitle", "", conf, CONF_wintitle);
+ gppi(sesskey, "TermWidth", 80, conf, CONF_width);
+ gppi(sesskey, "TermHeight", 24, conf, CONF_height);
+ gppfont(sesskey, "Font", conf, CONF_font);
+ gppi(sesskey, "FontQuality", FQ_DEFAULT, conf, CONF_font_quality);
+ gppi(sesskey, "FontVTMode", VT_UNICODE, conf, CONF_vtmode);
+ gppi(sesskey, "UseSystemColours", 0, conf, CONF_system_colour);
+ gppi(sesskey, "TryPalette", 0, conf, CONF_try_palette);
+ gppi(sesskey, "ANSIColour", 1, conf, CONF_ansi_colour);
+ gppi(sesskey, "Xterm256Colour", 1, conf, CONF_xterm_256_colour);
+ gppi(sesskey, "BoldAsColour", 1, conf, CONF_bold_colour);
for (i = 0; i < 22; i++) {
static const char *const defaults[] = {
"85,85,255", "187,0,187", "255,85,255", "0,187,187",
"85,255,255", "187,187,187", "255,255,255"
};
- char buf[20], buf2[30];
+ char buf[20], *buf2;
int c0, c1, c2;
sprintf(buf, "Colour%d", i);
- gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2));
+ buf2 = gpps_raw(sesskey, buf, defaults[i]);
if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
- cfg->colours[i][0] = c0;
- cfg->colours[i][1] = c1;
- cfg->colours[i][2] = c2;
+ conf_set_int_int(conf, CONF_colours, i*3+0, c0);
+ conf_set_int_int(conf, CONF_colours, i*3+1, c1);
+ conf_set_int_int(conf, CONF_colours, i*3+2, c2);
}
+ sfree(buf2);
}
- gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
- gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste);
- gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
- gppi(sesskey, "RectSelect", 0, &cfg->rect_select);
- gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override);
+ gppi(sesskey, "RawCNP", 0, conf, CONF_rawcnp);
+ gppi(sesskey, "PasteRTF", 0, conf, CONF_rtf_paste);
+ gppi(sesskey, "MouseIsXterm", 0, conf, CONF_mouse_is_xterm);
+ gppi(sesskey, "RectSelect", 0, conf, CONF_rect_select);
+ gppi(sesskey, "MouseOverride", 1, conf, CONF_mouse_override);
for (i = 0; i < 256; i += 32) {
static const char *const defaults[] = {
"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
};
- char buf[20], buf2[256], *p;
+ char buf[20], *buf2, *p;
int j;
sprintf(buf, "Wordness%d", i);
- gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2));
+ buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);
p = buf2;
for (j = i; j < i + 32; j++) {
char *q = p;
p++;
if (*p == ',')
*p++ = '\0';
- cfg->wordness[j] = atoi(q);
+ conf_set_int_int(conf, CONF_wordness, j, atoi(q));
}
+ sfree(buf2);
}
/*
* The empty default for LineCodePage will be converted later
* into a plausible default for the locale.
*/
- gpps(sesskey, "LineCodePage", "", cfg->line_codepage,
- sizeof(cfg->line_codepage));
- gppi(sesskey, "CJKAmbigWide", 0, &cfg->cjk_ambig_wide);
- gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override);
- gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer));
- gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
- gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
- gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen);
- gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key);
- gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp);
- gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback);
- gppi(sesskey, "LockSize", 0, &cfg->resize_action);
- gppi(sesskey, "BCE", 1, &cfg->bce);
- gppi(sesskey, "BlinkText", 0, &cfg->blinktext);
- gppi(sesskey, "X11Forward", 0, &cfg->x11_forward);
- gpps(sesskey, "X11Display", "", cfg->x11_display,
- sizeof(cfg->x11_display));
- gppi(sesskey, "X11AuthType", X11_MIT, &cfg->x11_auth);
- gppfile(sesskey, "X11AuthFile", &cfg->xauthfile);
-
- gppi(sesskey, "LocalPortAcceptAll", 0, &cfg->lport_acceptall);
- gppi(sesskey, "RemotePortAcceptAll", 0, &cfg->rport_acceptall);
- gppmap(sesskey, "PortForwardings", "", cfg->portfwd, lenof(cfg->portfwd));
- gppi(sesskey, "BugIgnore1", 0, &i); cfg->sshbug_ignore1 = 2-i;
- gppi(sesskey, "BugPlainPW1", 0, &i); cfg->sshbug_plainpw1 = 2-i;
- gppi(sesskey, "BugRSA1", 0, &i); cfg->sshbug_rsa1 = 2-i;
- gppi(sesskey, "BugIgnore2", 0, &i); cfg->sshbug_ignore2 = 2-i;
+ gpps(sesskey, "LineCodePage", "", conf, CONF_line_codepage);
+ gppi(sesskey, "CJKAmbigWide", 0, conf, CONF_cjk_ambig_wide);
+ gppi(sesskey, "UTF8Override", 1, conf, CONF_utf8_override);
+ gpps(sesskey, "Printer", "", conf, CONF_printer);
+ gppi(sesskey, "CapsLockCyr", 0, conf, CONF_xlat_capslockcyr);
+ gppi(sesskey, "ScrollBar", 1, conf, CONF_scrollbar);
+ gppi(sesskey, "ScrollBarFullScreen", 0, conf, CONF_scrollbar_in_fullscreen);
+ gppi(sesskey, "ScrollOnKey", 0, conf, CONF_scroll_on_key);
+ gppi(sesskey, "ScrollOnDisp", 1, conf, CONF_scroll_on_disp);
+ gppi(sesskey, "EraseToScrollback", 1, conf, CONF_erase_to_scrollback);
+ gppi(sesskey, "LockSize", 0, conf, CONF_resize_action);
+ gppi(sesskey, "BCE", 1, conf, CONF_bce);
+ gppi(sesskey, "BlinkText", 0, conf, CONF_blinktext);
+ gppi(sesskey, "X11Forward", 0, conf, CONF_x11_forward);
+ gpps(sesskey, "X11Display", "", conf, CONF_x11_display);
+ gppi(sesskey, "X11AuthType", X11_MIT, conf, CONF_x11_auth);
+ gppfile(sesskey, "X11AuthFile", conf, CONF_xauthfile);
+
+ gppi(sesskey, "LocalPortAcceptAll", 0, conf, CONF_lport_acceptall);
+ gppi(sesskey, "RemotePortAcceptAll", 0, conf, CONF_rport_acceptall);
+ gppmap(sesskey, "PortForwardings", conf, CONF_portfwd);
+ i = gppi_raw(sesskey, "BugIgnore1", 0); conf_set_int(conf, CONF_sshbug_ignore1, 2-i);
+ i = gppi_raw(sesskey, "BugPlainPW1", 0); conf_set_int(conf, CONF_sshbug_plainpw1, 2-i);
+ i = gppi_raw(sesskey, "BugRSA1", 0); conf_set_int(conf, CONF_sshbug_rsa1, 2-i);
+ i = gppi_raw(sesskey, "BugIgnore2", 0); conf_set_int(conf, CONF_sshbug_ignore2, 2-i);
{
int i;
- gppi(sesskey, "BugHMAC2", 0, &i); cfg->sshbug_hmac2 = 2-i;
- if (cfg->sshbug_hmac2 == AUTO) {
- gppi(sesskey, "BuggyMAC", 0, &i);
+ i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);
+ if (2-i == AUTO) {
+ i = gppi_raw(sesskey, "BuggyMAC", 0);
if (i == 1)
- cfg->sshbug_hmac2 = FORCE_ON;
+ conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);
}
}
- gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
- gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
- gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
- gppi(sesskey, "BugRekey2", 0, &i); cfg->sshbug_rekey2 = 2-i;
- gppi(sesskey, "BugMaxPkt2", 0, &i); cfg->sshbug_maxpkt2 = 2-i;
- cfg->ssh_simple = FALSE;
- gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
- gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
- gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left);
- gppi(sesskey, "ShadowBold", 0, &cfg->shadowbold);
- gppfont(sesskey, "BoldFont", &cfg->boldfont);
- gppfont(sesskey, "WideFont", &cfg->widefont);
- gppfont(sesskey, "WideBoldFont", &cfg->wideboldfont);
- gppi(sesskey, "ShadowBoldOffset", 1, &cfg->shadowboldoffset);
- gpps(sesskey, "SerialLine", "", cfg->serline, sizeof(cfg->serline));
- gppi(sesskey, "SerialSpeed", 9600, &cfg->serspeed);
- gppi(sesskey, "SerialDataBits", 8, &cfg->serdatabits);
- gppi(sesskey, "SerialStopHalfbits", 2, &cfg->serstopbits);
- gppi(sesskey, "SerialParity", SER_PAR_NONE, &cfg->serparity);
- gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, &cfg->serflow);
- gpps(sesskey, "WindowClass", "", cfg->winclass, sizeof(cfg->winclass));
+ i = gppi_raw(sesskey, "BugDeriveKey2", 0); conf_set_int(conf, CONF_sshbug_derivekey2, 2-i);
+ i = gppi_raw(sesskey, "BugRSAPad2", 0); conf_set_int(conf, CONF_sshbug_rsapad2, 2-i);
+ i = gppi_raw(sesskey, "BugPKSessID2", 0); conf_set_int(conf, CONF_sshbug_pksessid2, 2-i);
+ i = gppi_raw(sesskey, "BugRekey2", 0); conf_set_int(conf, CONF_sshbug_rekey2, 2-i);
+ i = gppi_raw(sesskey, "BugMaxPkt2", 0); conf_set_int(conf, CONF_sshbug_maxpkt2, 2-i);
+ conf_set_int(conf, CONF_ssh_simple, FALSE);
+ gppi(sesskey, "StampUtmp", 1, conf, CONF_stamp_utmp);
+ gppi(sesskey, "LoginShell", 1, conf, CONF_login_shell);
+ gppi(sesskey, "ScrollbarOnLeft", 0, conf, CONF_scrollbar_on_left);
+ gppi(sesskey, "ShadowBold", 0, conf, CONF_shadowbold);
+ gppfont(sesskey, "BoldFont", conf, CONF_boldfont);
+ gppfont(sesskey, "WideFont", conf, CONF_widefont);
+ gppfont(sesskey, "WideBoldFont", conf, CONF_wideboldfont);
+ gppi(sesskey, "ShadowBoldOffset", 1, conf, CONF_shadowboldoffset);
+ gpps(sesskey, "SerialLine", "", conf, CONF_serline);
+ gppi(sesskey, "SerialSpeed", 9600, conf, CONF_serspeed);
+ gppi(sesskey, "SerialDataBits", 8, conf, CONF_serdatabits);
+ gppi(sesskey, "SerialStopHalfbits", 2, conf, CONF_serstopbits);
+ gppi(sesskey, "SerialParity", SER_PAR_NONE, conf, CONF_serparity);
+ gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, conf, CONF_serflow);
+ gpps(sesskey, "WindowClass", "", conf, CONF_winclass);
}
-void do_defaults(char *session, Config * cfg)
+void do_defaults(char *session, Conf *conf)
{
- load_settings(session, cfg);
+ load_settings(session, conf);
}
static int sessioncmp(const void *av, const void *bv)
struct Packet *(*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.
+ * We maintain our own copy of a Conf structure here. 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;
+ Conf *conf;
+
+ /*
+ * Values cached out of conf so as to avoid the tree234 lookup
+ * cost every time they're used.
+ */
+ int logomitdata;
+
+ /*
+ * Dynamically allocated username string created during SSH
+ * login. Stored in here rather than in the coroutine state so
+ * that it'll be reliably freed if we shut down the SSH session
+ * at some unexpected moment.
+ */
+ char *username;
/*
* Used to transfer data back from async callbacks.
static void dont_log_password(Ssh ssh, struct Packet *pkt, int blanktype)
{
- if (ssh->cfg.logomitpass)
+ if (conf_get_int(ssh->conf, CONF_logomitpass))
pkt->logmode = blanktype;
}
static void dont_log_data(Ssh ssh, struct Packet *pkt, int blanktype)
{
- if (ssh->cfg.logomitdata)
+ if (ssh->logomitdata)
pkt->logmode = blanktype;
}
pkt->logmode = PKTLOG_EMIT;
}
-/* Helper function for common bits of parsing cfg.ttymodes. */
-static void parse_ttymodes(Ssh ssh, char *modes,
+/* Helper function for common bits of parsing ttymodes. */
+static void parse_ttymodes(Ssh ssh,
void (*do_mode)(void *data, char *mode, char *val),
void *data)
{
- while (*modes) {
- char *t = strchr(modes, '\t');
- char *m = snewn(t-modes+1, char);
- char *val;
- strncpy(m, modes, t-modes);
- m[t-modes] = '\0';
- if (*(t+1) == 'A')
- val = get_ttymode(ssh->frontend, m);
+ char *key, *val;
+
+ for (val = conf_get_str_strs(ssh->conf, CONF_ttymodes, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(ssh->conf, CONF_ttymodes, key, &key)) {
+ /*
+ * val[0] is either 'V', indicating that an explicit value
+ * follows it, or 'A' indicating that we should pass the
+ * value through from the local environment via get_ttymode.
+ */
+ if (val[0] == 'A')
+ val = get_ttymode(ssh->frontend, key);
else
- val = dupstr(t+2);
+ val++; /* skip the 'V' */
if (val)
- do_mode(data, m, val);
- sfree(m);
- sfree(val);
- modes += strlen(modes) + 1;
+ do_mode(data, key, val);
}
}
if (ssh->logctx) {
int nblanks = 0;
struct logblank_t blank;
- if (ssh->cfg.logomitdata) {
+ if (ssh->logomitdata) {
int do_blank = FALSE, blank_prefix = 0;
/* "Session data" packets - omit the data field */
if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||
if (ssh->logctx) {
int nblanks = 0;
struct logblank_t blank;
- if (ssh->cfg.logomitdata) {
+ if (ssh->logomitdata) {
int do_blank = FALSE, blank_prefix = 0;
/* "Session data" packets - omit the data field */
if (st->pktin->type == SSH2_MSG_CHANNEL_DATA) {
* with SSH1_MSG_IGNOREs -- but this string never seems to change,
* so we can't distinguish them.
*/
- if (ssh->cfg.sshbug_ignore1 == FORCE_ON ||
- (ssh->cfg.sshbug_ignore1 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_ignore1) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_ignore1) == 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") ||
logevent("We believe remote version has SSH-1 ignore bug");
}
- if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||
- (ssh->cfg.sshbug_plainpw1 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_plainpw1) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_plainpw1) == AUTO &&
(!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {
/*
* These versions need a plain password sent; they can't
logevent("We believe remote version needs a plain SSH-1 password");
}
- if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||
- (ssh->cfg.sshbug_rsa1 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_rsa1) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_rsa1) == AUTO &&
(!strcmp(imp, "Cisco-1.25")))) {
/*
* These versions apparently have no clue whatever about
logevent("We believe remote version can't handle SSH-1 RSA authentication");
}
- if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||
- (ssh->cfg.sshbug_hmac2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_hmac2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_hmac2) == AUTO &&
!wc_match("* VShell", imp) &&
(wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
logevent("We believe remote version has SSH-2 HMAC bug");
}
- if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||
- (ssh->cfg.sshbug_derivekey2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_derivekey2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_derivekey2) == AUTO &&
!wc_match("* VShell", imp) &&
(wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {
/*
logevent("We believe remote version has SSH-2 key-derivation bug");
}
- if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||
- (ssh->cfg.sshbug_rsapad2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == AUTO &&
(wc_match("OpenSSH_2.[5-9]*", imp) ||
wc_match("OpenSSH_3.[0-2]*", imp)))) {
/*
logevent("We believe remote version has SSH-2 RSA padding bug");
}
- if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||
- (ssh->cfg.sshbug_pksessid2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_pksessid2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_pksessid2) == AUTO &&
wc_match("OpenSSH_2.[0-2]*", imp))) {
/*
* These versions have the SSH-2 session-ID bug in
logevent("We believe remote version has SSH-2 public-key-session-ID bug");
}
- if (ssh->cfg.sshbug_rekey2 == FORCE_ON ||
- (ssh->cfg.sshbug_rekey2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_rekey2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_rekey2) == AUTO &&
(wc_match("DigiSSH_2.0", imp) ||
wc_match("OpenSSH_2.[0-4]*", imp) ||
wc_match("OpenSSH_2.5.[0-3]*", imp) ||
logevent("We believe remote version has SSH-2 rekey bug");
}
- if (ssh->cfg.sshbug_maxpkt2 == FORCE_ON ||
- (ssh->cfg.sshbug_maxpkt2 == AUTO &&
+ if (conf_get_int(ssh->conf, CONF_sshbug_maxpkt2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_maxpkt2) == AUTO &&
(wc_match("1.36_sshlib GlobalSCAPE", imp) ||
wc_match("1.36 sshlib: GlobalScape", imp)))) {
/*
logevent("We believe remote version ignores SSH-2 maximum packet size");
}
- if (ssh->cfg.sshbug_ignore2 == FORCE_ON) {
+ if (conf_get_int(ssh->conf, CONF_sshbug_ignore2) == FORCE_ON) {
/*
* Servers that don't support SSH2_MSG_IGNORE. Currently,
* none detected automatically.
/* Anything greater or equal to "1.99" means protocol 2 is supported. */
s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
- if (ssh->cfg.sshprot == 0 && !s->proto1) {
+ if (conf_get_int(ssh->conf, CONF_sshprot) == 0 && !s->proto1) {
bombout(("SSH protocol version 1 required by user but not provided by server"));
crStop(0);
}
- if (ssh->cfg.sshprot == 3 && !s->proto2) {
+ if (conf_get_int(ssh->conf, CONF_sshprot) == 3 && !s->proto2) {
bombout(("SSH protocol version 2 required by user but not provided by server"));
crStop(0);
}
- if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1))
+ if (s->proto2 && (conf_get_int(ssh->conf, CONF_sshprot) >= 2 || !s->proto1))
ssh->version = 2;
else
ssh->version = 1;
logeventf(ssh, "Using SSH protocol version %d", ssh->version);
/* Send the version string, if we haven't already */
- if (ssh->cfg.sshprot != 3)
+ if (conf_get_int(ssh->conf, CONF_sshprot) != 3)
ssh_send_verstring(ssh, s->version);
if (ssh->version == 2) {
update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE;
- ssh->pinger = pinger_new(&ssh->cfg, &ssh_backend, ssh);
+ ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh);
sfree(s->vstring);
SockAddr addr;
const char *err;
-
- if (*ssh->cfg.loghost) {
+ char *loghost;
+ int addressfamily, sshprot;
+
+ loghost = conf_get_str(ssh->conf, CONF_loghost);
+ if (*loghost) {
char *colon;
- ssh->savedhost = dupstr(ssh->cfg.loghost);
+ ssh->savedhost = dupstr(loghost);
ssh->savedport = 22; /* default ssh port */
/*
/*
* Try to find host.
*/
+ addressfamily = conf_get_int(ssh->conf, CONF_addressfamily);
logeventf(ssh, "Looking up host \"%s\"%s", host,
- (ssh->cfg.addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
- (ssh->cfg.addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
- addr = name_lookup(host, port, realhost, &ssh->cfg,
- ssh->cfg.addressfamily);
+ (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
+ (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
+ addr = name_lookup(host, port, realhost, ssh->conf, addressfamily);
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
*/
ssh->fn = &fn_table;
ssh->s = new_connection(addr, *realhost, port,
- 0, 1, nodelay, keepalive, (Plug) ssh, &ssh->cfg);
+ 0, 1, nodelay, keepalive, (Plug) ssh, ssh->conf);
if ((err = sk_socket_error(ssh->s)) != NULL) {
ssh->s = NULL;
notify_remote_exit(ssh->frontend);
* If the SSH version number's fixed, set it now, and if it's SSH-2,
* send the version string too.
*/
- if (ssh->cfg.sshprot == 0)
+ sshprot = conf_get_int(ssh->conf, CONF_sshprot);
+ if (sshprot == 0)
ssh->version = 1;
- if (ssh->cfg.sshprot == 3) {
+ if (sshprot == 3) {
ssh->version = 2;
ssh_send_verstring(ssh, NULL);
}
/*
* loghost, if configured, overrides realhost.
*/
- if (*ssh->cfg.loghost) {
+ if (*loghost) {
sfree(*realhost);
- *realhost = dupstr(ssh->cfg.loghost);
+ *realhost = dupstr(loghost);
}
return NULL;
int tis_auth_refused, ccard_auth_refused;
unsigned char session_id[16];
int cipher_type;
- char username[100];
void *publickey_blob;
int publickey_bloblen;
char *publickey_comment;
char *commentp;
int commentlen;
int dlgret;
+ Filename *keyfile;
};
crState(do_ssh1_login_state);
char *cipher_string = NULL;
int i;
for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
- int next_cipher = ssh->cfg.ssh_cipherlist[i];
+ int next_cipher = conf_get_int_int(ssh->conf,
+ CONF_ssh_cipherlist, i);
if (next_cipher == CIPHER_WARN) {
/* If/when we choose a cipher, warn about it */
warn = 1;
fflush(stdout); /* FIXME eh? */
{
- if (!get_remote_username(&ssh->cfg, s->username,
- sizeof(s->username))) {
+ if ((ssh->username = get_remote_username(ssh->conf)) == NULL) {
int ret; /* need not be kept over crReturn */
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
s->cur_prompt->name = dupstr("SSH login name");
- add_prompt(s->cur_prompt, dupstr("login as: "), TRUE,
- lenof(s->username));
+ /* 512 is an arbitrary upper limit on username size */
+ add_prompt(s->cur_prompt, dupstr("login as: "), TRUE, 512);
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
crStop(0);
}
- memcpy(s->username, s->cur_prompt->prompts[0]->result,
- lenof(s->username));
+ ssh->username = dupstr(s->cur_prompt->prompts[0]->result);
free_prompts(s->cur_prompt);
}
- send_packet(ssh, SSH1_CMSG_USER, PKT_STR, s->username, PKT_END);
+ send_packet(ssh, SSH1_CMSG_USER, PKT_STR, ssh->username, PKT_END);
{
- char *userlog = dupprintf("Sent username \"%s\"", s->username);
+ char *userlog = dupprintf("Sent username \"%s\"", ssh->username);
logevent(userlog);
if (flags & FLAG_INTERACTIVE &&
(!((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)))) {
/*
* Load the public half of any configured keyfile for later use.
*/
- if (!filename_is_null(ssh->cfg.keyfile)) {
+ s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
+ if (!filename_is_null(*s->keyfile)) {
int keytype;
logeventf(ssh, "Reading private key file \"%.150s\"",
- filename_to_str(&ssh->cfg.keyfile));
- keytype = key_type(&ssh->cfg.keyfile);
+ filename_to_str(s->keyfile));
+ keytype = key_type(s->keyfile);
if (keytype == SSH_KEYTYPE_SSH1) {
const char *error;
- if (rsakey_pubblob(&ssh->cfg.keyfile,
+ if (rsakey_pubblob(s->keyfile,
&s->publickey_blob, &s->publickey_bloblen,
&s->publickey_comment, &error)) {
- s->publickey_encrypted = rsakey_encrypted(&ssh->cfg.keyfile,
+ s->publickey_encrypted = rsakey_encrypted(s->keyfile,
NULL);
} else {
char *msgbuf;
logeventf(ssh, "Unable to load private key (%s)", error);
msgbuf = dupprintf("Unable to load private key file "
"\"%.150s\" (%s)\r\n",
- filename_to_str(&ssh->cfg.keyfile),
+ filename_to_str(s->keyfile),
error);
c_write_str(ssh, msgbuf);
sfree(msgbuf);
key_type_to_str(keytype));
msgbuf = dupprintf("Unable to use key file \"%.150s\""
" (%s)\r\n",
- filename_to_str(&ssh->cfg.keyfile),
+ filename_to_str(s->keyfile),
key_type_to_str(keytype));
c_write_str(ssh, msgbuf);
sfree(msgbuf);
while (pktin->type == SSH1_SMSG_FAILURE) {
s->pwpkt_type = SSH1_CMSG_AUTH_PASSWORD;
- if (ssh->cfg.tryagent && agent_exists() && !s->tried_agent) {
+ if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists() && !s->tried_agent) {
/*
* Attempt RSA authentication using Pageant.
*/
int got_passphrase; /* need not be kept over crReturn */
if (flags & FLAG_VERBOSE)
c_write_str(ssh, "Trying public key authentication.\r\n");
+ s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
logeventf(ssh, "Trying public key \"%s\"",
- filename_to_str(&ssh->cfg.keyfile));
+ filename_to_str(s->keyfile));
s->tried_publickey = 1;
got_passphrase = FALSE;
while (!got_passphrase) {
/*
* Try decrypting key with passphrase.
*/
- ret = loadrsakey(&ssh->cfg.keyfile, &s->key, passphrase,
+ s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
+ ret = loadrsakey(s->keyfile, &s->key, passphrase,
&error);
if (passphrase) {
memset(passphrase, 0, strlen(passphrase));
got_passphrase = TRUE;
} else if (ret == 0) {
c_write_str(ssh, "Couldn't load private key from ");
- c_write_str(ssh, filename_to_str(&ssh->cfg.keyfile));
+ c_write_str(ssh, filename_to_str(s->keyfile));
c_write_str(ssh, " (");
c_write_str(ssh, error);
c_write_str(ssh, ").\r\n");
*/
s->cur_prompt = new_prompts(ssh->frontend);
- if (ssh->cfg.try_tis_auth &&
+ if (conf_get_int(ssh->conf, CONF_try_tis_auth) &&
(s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
!s->tis_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
sfree(instr_suf);
}
}
- if (ssh->cfg.try_tis_auth &&
+ if (conf_get_int(ssh->conf, CONF_try_tis_auth) &&
(s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
!s->ccard_auth_refused) {
s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
}
s->cur_prompt->to_server = TRUE;
s->cur_prompt->name = dupstr("SSH password");
- add_prompt(s->cur_prompt, dupprintf("%.90s@%.90s's password: ",
- s->username, ssh->savedhost),
+ add_prompt(s->cur_prompt, dupprintf("%s@%s's password: ",
+ ssh->username, ssh->savedhost),
FALSE, SSH_MAX_PASSWORD_LEN);
}
}
}
-static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
+static void ssh_setup_portfwd(Ssh ssh, Conf *conf)
{
- const char *portfwd_strptr = cfg->portfwd;
struct ssh_portfwd *epf;
int i;
+ char *key, *val;
if (!ssh->portfwds) {
ssh->portfwds = newtree234(ssh_portcmp);
epf->status = DESTROY;
}
- while (*portfwd_strptr) {
+ for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
+ char *kp, *kp2, *vp, *vp2;
char address_family, type;
int sport,dport,sserv,dserv;
- char sports[256], dports[256], saddr[256], host[256];
- int n;
+ char *sports, *dports, *saddr, *host;
+
+ kp = key;
address_family = 'A';
type = 'L';
- if (*portfwd_strptr == 'A' ||
- *portfwd_strptr == '4' ||
- *portfwd_strptr == '6')
- address_family = *portfwd_strptr++;
- if (*portfwd_strptr == 'L' ||
- *portfwd_strptr == 'R' ||
- *portfwd_strptr == 'D')
- type = *portfwd_strptr++;
-
- saddr[0] = '\0';
-
- n = 0;
- while (*portfwd_strptr && *portfwd_strptr != '\t') {
- if (*portfwd_strptr == ':') {
- /*
- * We've seen a colon in the middle of the
- * source port number. This means that
- * everything we've seen until now is the
- * source _address_, so we'll move it into
- * saddr and start sports from the beginning
- * again.
- */
- portfwd_strptr++;
- sports[n] = '\0';
- if (ssh->version == 1 && type == 'R') {
- logeventf(ssh, "SSH-1 cannot handle remote source address "
- "spec \"%s\"; ignoring", sports);
- } else
- strcpy(saddr, sports);
- n = 0;
- }
- if (n < lenof(sports)-1) sports[n++] = *portfwd_strptr++;
- }
- sports[n] = 0;
- if (type != 'D') {
- if (*portfwd_strptr == '\t')
- portfwd_strptr++;
- n = 0;
- while (*portfwd_strptr && *portfwd_strptr != ':') {
- if (n < lenof(host)-1) host[n++] = *portfwd_strptr++;
- }
- host[n] = 0;
- if (*portfwd_strptr == ':')
- portfwd_strptr++;
- n = 0;
- while (*portfwd_strptr) {
- if (n < lenof(dports)-1) dports[n++] = *portfwd_strptr++;
- }
- dports[n] = 0;
- portfwd_strptr++;
- dport = atoi(dports);
- dserv = 0;
- if (dport == 0) {
- dserv = 1;
- dport = net_service_lookup(dports);
- if (!dport) {
- logeventf(ssh, "Service lookup failed for destination"
- " port \"%s\"", dports);
- }
- }
+ if (*kp == 'A' || *kp == '4' || *kp == '6')
+ address_family = *kp++;
+ if (*kp == 'L' || *kp == 'R')
+ type = *kp++;
+
+ if ((kp2 = strchr(kp, ':')) != NULL) {
+ /*
+ * There's a colon in the middle of the source port
+ * string, which means that the part before it is
+ * actually a source address.
+ */
+ saddr = dupprintf("%.*s", (int)(kp2 - kp), kp);
+ sports = kp2+1;
} else {
- while (*portfwd_strptr) portfwd_strptr++;
- host[0] = 0;
- dports[0] = 0;
- dport = dserv = -1;
- portfwd_strptr++; /* eat the NUL and move to next one */
+ saddr = NULL;
+ sports = kp;
}
sport = atoi(sports);
sserv = 0;
" port \"%s\"", sports);
}
}
+
+ if (type == 'L' && !strcmp(val, "D")) {
+ /* dynamic forwarding */
+ host = NULL;
+ dports = NULL;
+ dport = -1;
+ dserv = 0;
+ type = 'D';
+ } else {
+ /* ordinary forwarding */
+ vp = val;
+ vp2 = vp + strcspn(vp, ":");
+ host = dupprintf("%.*s", (int)(vp2 - vp), vp);
+ if (vp2)
+ vp2++;
+ dports = vp2;
+ dport = atoi(dports);
+ dserv = 0;
+ if (dport == 0) {
+ dserv = 1;
+ dport = net_service_lookup(dports);
+ if (!dport) {
+ logeventf(ssh, "Service lookup failed for destination"
+ " port \"%s\"", dports);
+ }
+ }
+ }
+
if (sport && dport) {
/* Set up a description of the source port. */
struct ssh_portfwd *pfrec, *epfrec;
pfrec = snew(struct ssh_portfwd);
pfrec->type = type;
- pfrec->saddr = *saddr ? dupstr(saddr) : NULL;
+ pfrec->saddr = saddr;
pfrec->sserv = sserv ? dupstr(sports) : NULL;
pfrec->sport = sport;
- pfrec->daddr = *host ? dupstr(host) : NULL;
+ pfrec->daddr = host;
pfrec->dserv = dserv ? dupstr(dports) : NULL;
pfrec->dport = dport;
pfrec->local = NULL;
} else {
pfrec->status = CREATE;
}
+ } else {
+ sfree(saddr);
+ sfree(host);
}
}
ssh2_pkt_addbool(pktout, 0);/* _don't_ want reply */
if (epf->saddr) {
ssh2_pkt_addstring(pktout, epf->saddr);
- } else if (ssh->cfg.rport_acceptall) {
- /* XXX: ssh->cfg.rport_acceptall may not represent
+ } else if (conf_get_int(conf, CONF_rport_acceptall)) {
+ /* XXX: rport_acceptall may not represent
* what was used to open the original connection,
* since it's reconfigurable. */
ssh2_pkt_addstring(pktout, "0.0.0.0");
if (epf->type == 'L') {
const char *err = pfd_addforward(epf->daddr, epf->dport,
epf->saddr, epf->sport,
- ssh, cfg,
+ ssh, conf,
&epf->local,
epf->addressfamily);
} else if (epf->type == 'D') {
const char *err = pfd_addforward(NULL, -1,
epf->saddr, epf->sport,
- ssh, cfg,
+ ssh, conf,
&epf->local,
epf->addressfamily);
ssh2_pkt_addbool(pktout, 1);/* want reply */
if (epf->saddr) {
ssh2_pkt_addstring(pktout, epf->saddr);
- } else if (cfg->rport_acceptall) {
+ } else if (conf_get_int(conf, CONF_rport_acceptall)) {
ssh2_pkt_addstring(pktout, "0.0.0.0");
} else {
ssh2_pkt_addstring(pktout, "127.0.0.1");
c->ssh = ssh;
if (x11_init(&c->u.x11.s, ssh->x11disp, c,
- NULL, -1, &ssh->cfg) != NULL) {
+ NULL, -1, ssh->conf) != NULL) {
logevent("Opening X11 forward connection failed");
sfree(c);
send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
logeventf(ssh, "Received remote port open request for %s:%d",
pf.dhost, port);
e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
- c, &ssh->cfg, pfp->pfrec->addressfamily);
+ c, ssh->conf, pfp->pfrec->addressfamily);
if (e != NULL) {
logeventf(ssh, "Port open failed: %s", e);
sfree(c);
ssh->packet_dispatch[SSH1_MSG_CHANNEL_DATA] = ssh1_msg_channel_data;
ssh->packet_dispatch[SSH1_SMSG_EXIT_STATUS] = ssh1_smsg_exit_status;
- if (ssh->cfg.agentfwd && agent_exists()) {
+ if (conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists()) {
logevent("Requesting agent forwarding");
send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do {
}
}
- if (ssh->cfg.x11_forward &&
- (ssh->x11disp = x11_setup_display(ssh->cfg.x11_display,
- ssh->cfg.x11_auth, &ssh->cfg))) {
+ if (conf_get_int(ssh->conf, CONF_x11_forward) &&
+ (ssh->x11disp = x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
+ conf_get_int(ssh->conf, CONF_x11_auth), ssh->conf))) {
logevent("Requesting X11 forwarding");
/*
* Note that while we blank the X authentication data here, we don't
}
}
- ssh_setup_portfwd(ssh, &ssh->cfg);
+ ssh_setup_portfwd(ssh, ssh->conf);
ssh->packet_dispatch[SSH1_MSG_PORT_OPEN] = ssh1_msg_port_open;
- if (!ssh->cfg.nopty) {
+ if (!conf_get_int(ssh->conf, CONF_nopty)) {
struct Packet *pkt;
/* Unpick the terminal-speed string. */
/* XXX perhaps we should allow no speeds to be sent. */
ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
- sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
+ sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed);
/* Send the pty request. */
pkt = ssh1_pkt_init(SSH1_CMSG_REQUEST_PTY);
- ssh_pkt_addstring(pkt, ssh->cfg.termtype);
+ ssh_pkt_addstring(pkt, conf_get_str(ssh->conf, CONF_termtype));
ssh_pkt_adduint32(pkt, ssh->term_height);
ssh_pkt_adduint32(pkt, ssh->term_width);
ssh_pkt_adduint32(pkt, 0); /* width in pixels */
ssh_pkt_adduint32(pkt, 0); /* height in pixels */
- parse_ttymodes(ssh, ssh->cfg.ttymodes,
- ssh1_send_ttymode, (void *)pkt);
+ parse_ttymodes(ssh, ssh1_send_ttymode, (void *)pkt);
ssh_pkt_addbyte(pkt, SSH1_TTY_OP_ISPEED);
ssh_pkt_adduint32(pkt, ssh->ispeed);
ssh_pkt_addbyte(pkt, SSH1_TTY_OP_OSPEED);
ssh->editing = ssh->echoing = 1;
}
- if (ssh->cfg.compression) {
+ if (conf_get_int(ssh->conf, CONF_compression)) {
send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
do {
crReturnV;
* exists, we fall straight back to that.
*/
{
- char *cmd = ssh->cfg.remote_cmd_ptr;
-
- if (!cmd) cmd = ssh->cfg.remote_cmd;
+ char *cmd = conf_get_str(ssh->conf, CONF_remote_cmd);
- if (ssh->cfg.ssh_subsys && ssh->cfg.remote_cmd_ptr2) {
- cmd = ssh->cfg.remote_cmd_ptr2;
+ if (conf_get_int(ssh->conf, CONF_ssh_subsys) &&
+ conf_get_str(ssh->conf, CONF_remote_cmd2)) {
+ cmd = conf_get_str(ssh->conf, CONF_remote_cmd2);
ssh->fallback_cmd = TRUE;
}
if (*cmd)
*/
s->n_preferred_kex = 0;
for (i = 0; i < KEX_MAX; i++) {
- switch (ssh->cfg.ssh_kexlist[i]) {
+ switch (conf_get_int_int(ssh->conf, CONF_ssh_kexlist, i)) {
case KEX_DHGEX:
s->preferred_kex[s->n_preferred_kex++] =
&ssh_diffiehellman_gex;
*/
s->n_preferred_ciphers = 0;
for (i = 0; i < CIPHER_MAX; i++) {
- switch (ssh->cfg.ssh_cipherlist[i]) {
+ switch (conf_get_int_int(ssh->conf, CONF_ssh_cipherlist, i)) {
case CIPHER_BLOWFISH:
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;
break;
case CIPHER_DES:
- if (ssh->cfg.ssh2_des_cbc) {
+ if (conf_get_int(ssh->conf, CONF_ssh2_des_cbc)) {
s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;
}
break;
/*
* Set up preferred compression.
*/
- if (ssh->cfg.compression)
+ if (conf_get_int(ssh->conf, CONF_compression))
s->preferred_comp = &ssh_zlib;
else
s->preferred_comp = &ssh_comp_none;
*/
ssh->kex_in_progress = FALSE;
ssh->last_rekey = GETTICKCOUNT();
- if (ssh->cfg.ssh_rekey_time != 0)
- ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
+ if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0)
+ ssh->next_rekey = schedule_timer(conf_get_int(ssh->conf, CONF_ssh_rekey_time)*60*TICKSPERSEC,
ssh2_timer, ssh);
/*
* hit the event log _too_ often. */
ssh->outgoing_data_size = 0;
ssh->incoming_data_size = 0;
- if (ssh->cfg.ssh_rekey_time != 0) {
+ if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0) {
ssh->next_rekey =
- schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
+ schedule_timer(conf_get_int(ssh->conf, CONF_ssh_rekey_time)*60*TICKSPERSEC,
ssh2_timer, ssh);
}
goto wait_for_rekey; /* this is still utterly horrid */
c->pending_close = FALSE;
c->throttling_conn = FALSE;
c->v.v2.locwindow = c->v.v2.locmaxwin = c->v.v2.remlocwin =
- ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
+ conf_get_int(ssh->conf, CONF_ssh_simple) ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
c->v.v2.winadj_head = c->v.v2.winadj_tail = NULL;
c->v.v2.throttle_state = UNTHROTTLED;
bufchain_init(&c->v.v2.outbuffer);
* throttle the whole channel.
*/
if ((bufsize > c->v.v2.locmaxwin ||
- (ssh->cfg.ssh_simple && bufsize > 0)) &&
+ (conf_get_int(ssh->conf, CONF_ssh_simple) && bufsize > 0)) &&
!c->throttling_conn) {
c->throttling_conn = 1;
ssh_throttle_conn(ssh, +1);
* (This is only our termination condition if we're
* not running in -N mode.)
*/
- if (!ssh->cfg.ssh_no_shell && count234(ssh->channels) == 0) {
+ if (!conf_get_int(ssh->conf, CONF_ssh_no_shell) && count234(ssh->channels) == 0) {
/*
* We used to send SSH_MSG_DISCONNECT here,
* because I'd believed that _every_ conforming
if (!ssh->X11_fwd_enabled)
error = "X11 forwarding is not enabled";
else if ((x11err = x11_init(&c->u.x11.s, ssh->x11disp, c,
- addrstr, peerport, &ssh->cfg)) != NULL) {
+ addrstr, peerport, ssh->conf)) != NULL) {
logeventf(ssh, "Local X11 connection failed: %s", x11err);
error = "Unable to open an X11 connection";
} else {
const char *e = pfd_newconnect(&c->u.pfd.s,
realpf->dhost,
realpf->dport, c,
- &ssh->cfg,
+ ssh->conf,
realpf->pfrec->addressfamily);
logeventf(ssh, "Attempting to forward remote port to "
"%s:%d", realpf->dhost, realpf->dport);
static void ssh2_msg_userauth_banner(Ssh ssh, struct Packet *pktin)
{
/* Arbitrary limit to prevent unbounded inflation of buffer */
- if (ssh->cfg.ssh_show_banner &&
+ if (conf_get_int(ssh->conf, CONF_ssh_show_banner) &&
bufchain_size(&ssh->banner) <= 131072) {
char *banner = NULL;
int size = 0;
int we_are_in, userauth_success;
prompts_t *cur_prompt;
int num_prompts;
- char username[100];
+ char *username;
char *password;
int got_username;
void *publickey_blob;
int try_send;
int num_env, env_left, env_ok;
struct Packet *pktout;
+ Filename *keyfile;
#ifndef NO_GSSAPI
struct ssh_gss_library *gsslib;
Ssh_gss_ctx gss_ctx;
s->tried_gssapi = FALSE;
#endif
- if (!ssh->cfg.ssh_no_userauth) {
+ if (!conf_get_int(ssh->conf, CONF_ssh_no_userauth)) {
/*
* Request userauth protocol, and await a response to it.
*/
* Load the public half of any configured public key file
* for later use.
*/
- if (!filename_is_null(ssh->cfg.keyfile)) {
+ s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
+ if (!filename_is_null(*s->keyfile)) {
int keytype;
logeventf(ssh, "Reading private key file \"%.150s\"",
- filename_to_str(&ssh->cfg.keyfile));
- keytype = key_type(&ssh->cfg.keyfile);
+ filename_to_str(s->keyfile));
+ keytype = key_type(s->keyfile);
if (keytype == SSH_KEYTYPE_SSH2) {
const char *error;
s->publickey_blob =
- ssh2_userkey_loadpub(&ssh->cfg.keyfile,
+ ssh2_userkey_loadpub(s->keyfile,
&s->publickey_algorithm,
&s->publickey_bloblen,
&s->publickey_comment, &error);
if (s->publickey_blob) {
s->publickey_encrypted =
- ssh2_userkey_encrypted(&ssh->cfg.keyfile, NULL);
+ ssh2_userkey_encrypted(s->keyfile, NULL);
} else {
char *msgbuf;
logeventf(ssh, "Unable to load private key (%s)",
error);
msgbuf = dupprintf("Unable to load private key file "
"\"%.150s\" (%s)\r\n",
- filename_to_str(&ssh->cfg.keyfile),
+ filename_to_str(s->keyfile),
error);
c_write_str(ssh, msgbuf);
sfree(msgbuf);
key_type_to_str(keytype));
msgbuf = dupprintf("Unable to use key file \"%.150s\""
" (%s)\r\n",
- filename_to_str(&ssh->cfg.keyfile),
+ filename_to_str(s->keyfile),
key_type_to_str(keytype));
c_write_str(ssh, msgbuf);
sfree(msgbuf);
s->nkeys = 0;
s->agent_response = NULL;
s->pkblob_in_agent = NULL;
- if (ssh->cfg.tryagent && agent_exists()) {
+ if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
void *r;
* the username they will want to be able to get back and
* retype it!
*/
- s->username[0] = '\0';
s->got_username = FALSE;
while (!s->we_are_in) {
/*
* Get a username.
*/
- if (s->got_username && !ssh->cfg.change_username) {
+ if (s->got_username && !conf_get_int(ssh->conf, CONF_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.
*/
- } else if (!get_remote_username(&ssh->cfg, s->username,
- sizeof(s->username))) {
+ } else if ((ssh->username = get_remote_username(ssh->conf)) == NULL) {
int ret; /* need not be kept over crReturn */
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
s->cur_prompt->name = dupstr("SSH login name");
- add_prompt(s->cur_prompt, dupstr("login as: "), TRUE,
- lenof(s->username));
+ /* 512 is an arbitrary limit :-( */
+ add_prompt(s->cur_prompt, dupstr("login as: "), TRUE, 512);
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
crStopV;
}
- memcpy(s->username, s->cur_prompt->prompts[0]->result,
- lenof(s->username));
+ ssh->username = dupstr(s->cur_prompt->prompts[0]->result);
free_prompts(s->cur_prompt);
} else {
char *stuff;
if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
- stuff = dupprintf("Using username \"%s\".\r\n", s->username);
+ stuff = dupprintf("Using username \"%s\".\r\n", ssh->username);
c_write_str(ssh, stuff);
sfree(stuff);
}
ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");/* service requested */
ssh2_pkt_addstring(s->pktout, "none"); /* method */
ssh2_pkt_send(ssh, s->pktout);
c_write_str(ssh, "Access denied\r\n");
logevent("Access denied");
if (s->type == AUTH_TYPE_PASSWORD &&
- ssh->cfg.change_username) {
+ conf_get_int(ssh->conf, CONF_change_username)) {
/* XXX perhaps we should allow
* keyboard-interactive to do this too? */
s->we_are_in = FALSE;
in_commasep_string("publickey", methods, methlen);
s->can_passwd =
in_commasep_string("password", methods, methlen);
- s->can_keyb_inter = ssh->cfg.try_ki_auth &&
+ s->can_keyb_inter = conf_get_int(ssh->conf, CONF_try_ki_auth) &&
in_commasep_string("keyboard-interactive", methods, methlen);
#ifndef NO_GSSAPI
if (!ssh->gsslibs)
- ssh->gsslibs = ssh_gss_setup(&ssh->cfg);
- s->can_gssapi = ssh->cfg.try_gssapi_auth &&
+ ssh->gsslibs = ssh_gss_setup(ssh->conf);
+ s->can_gssapi = conf_get_int(ssh->conf, CONF_try_gssapi_auth) &&
in_commasep_string("gssapi-with-mic", methods, methlen) &&
ssh->gsslibs->nlibraries > 0;
#endif
/* See if server will accept it */
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "publickey");
* Construct a SIGN_REQUEST.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "publickey");
* willing to accept it.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
/*
* Try decrypting the key.
*/
- key = ssh2_load_userkey(&ssh->cfg.keyfile, passphrase,
- &error);
+ s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
+ key = ssh2_load_userkey(s->keyfile, passphrase, &error);
if (passphrase) {
/* burn the evidence */
memset(passphrase, 0, strlen(passphrase));
* Hallelujah. Generate a signature and send it.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "publickey");
int i, j;
s->gsslib = NULL;
for (i = 0; i < ngsslibs; i++) {
- int want_id = ssh->cfg.ssh_gsslist[i];
+ int want_id = conf_get_int_int(ssh->conf,
+ CONF_ssh_gsslist, i);
for (j = 0; j < ssh->gsslibs->nlibraries; j++)
if (ssh->gsslibs->libraries[j].id == want_id) {
s->gsslib = &ssh->gsslibs->libraries[j];
/* Sending USERAUTH_REQUEST with "gssapi-with-mic" method */
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
ssh2_pkt_addstring(s->pktout, "gssapi-with-mic");
(s->gsslib,
&s->gss_ctx,
s->gss_srv_name,
- ssh->cfg.gssapifwd,
+ conf_get_int(ssh->conf, CONF_gssapifwd),
&s->gss_rcvtok,
&s->gss_sndtok);
ssh_pkt_addstring_start(s->pktout);
ssh_pkt_addstring_data(s->pktout, (char *)ssh->v2_session_id, ssh->v2_session_id_len);
ssh_pkt_addbyte(s->pktout, SSH2_MSG_USERAUTH_REQUEST);
- ssh_pkt_addstring(s->pktout, s->username);
+ ssh_pkt_addstring(s->pktout, ssh->username);
ssh_pkt_addstring(s->pktout, "ssh-connection");
ssh_pkt_addstring(s->pktout, "gssapi-with-mic");
ssh->pkt_actx = SSH2_PKTCTX_KBDINTER;
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "keyboard-interactive");
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
s->cur_prompt->name = dupstr("SSH password");
- add_prompt(s->cur_prompt, dupprintf("%.90s@%.90s's password: ",
- s->username,
+ add_prompt(s->cur_prompt, dupprintf("%s@%s's password: ",
+ ssh->username,
ssh->savedhost),
FALSE, SSH_MAX_PASSWORD_LEN);
* people who find out how long their password is!
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "password");
* (see above for padding rationale)
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, ssh->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "password");
/*
* Create the main session channel.
*/
- if (ssh->cfg.ssh_no_shell) {
+ if (conf_get_int(ssh->conf, CONF_ssh_no_shell)) {
ssh->mainchan = NULL;
- } else if (*ssh->cfg.ssh_nc_host) {
+ } else if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) {
/*
* Just start a direct-tcpip channel and use it as the main
* channel.
ssh2_channel_init(ssh->mainchan);
logeventf(ssh,
"Opening direct-tcpip channel to %s:%d in place of session",
- ssh->cfg.ssh_nc_host, ssh->cfg.ssh_nc_port);
+ conf_get_str(ssh->conf, CONF_ssh_nc_host),
+ conf_get_int(ssh->conf, CONF_ssh_nc_port));
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
ssh2_pkt_addstring(s->pktout, "direct-tcpip");
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT); /* our max pkt size */
- ssh2_pkt_addstring(s->pktout, ssh->cfg.ssh_nc_host);
- ssh2_pkt_adduint32(s->pktout, ssh->cfg.ssh_nc_port);
+ ssh2_pkt_addstring(s->pktout, conf_get_str(ssh->conf, CONF_ssh_nc_host));
+ ssh2_pkt_adduint32(s->pktout, conf_get_int(ssh->conf, CONF_ssh_nc_port));
/*
* There's nothing meaningful to put in the originator
* fields, but some servers insist on syntactically correct
ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] =
ssh2_msg_channel_open;
- if (ssh->mainchan && ssh->cfg.ssh_simple) {
+ if (ssh->mainchan && conf_get_int(ssh->conf, CONF_ssh_simple)) {
/*
* This message indicates to the server that we promise
* not to try to run any other channel in parallel with
/*
* Potentially enable X11 forwarding.
*/
- if (ssh->mainchan && !ssh->ncmode && ssh->cfg.x11_forward &&
- (ssh->x11disp = x11_setup_display(ssh->cfg.x11_display,
- ssh->cfg.x11_auth, &ssh->cfg))) {
+ if (ssh->mainchan && !ssh->ncmode && conf_get_int(ssh->conf, CONF_x11_forward) &&
+ (ssh->x11disp = x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
+ conf_get_int(ssh->conf, CONF_x11_auth), ssh->conf))) {
logevent("Requesting X11 forwarding");
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
/*
* Enable port forwardings.
*/
- ssh_setup_portfwd(ssh, &ssh->cfg);
+ ssh_setup_portfwd(ssh, ssh->conf);
/*
* Potentially enable agent forwarding.
*/
- if (ssh->mainchan && !ssh->ncmode && ssh->cfg.agentfwd && agent_exists()) {
+ if (ssh->mainchan && !ssh->ncmode && conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists()) {
logevent("Requesting OpenSSH-style agent forwarding");
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
/*
* Now allocate a pty for the session.
*/
- if (ssh->mainchan && !ssh->ncmode && !ssh->cfg.nopty) {
+ if (ssh->mainchan && !ssh->ncmode && !conf_get_int(ssh->conf, CONF_nopty)) {
/* Unpick the terminal-speed string. */
/* XXX perhaps we should allow no speeds to be sent. */
ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
- sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
+ sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed);
/* Build the pty request. */
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid); /* recipient channel */
ssh2_pkt_addstring(s->pktout, "pty-req");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
- ssh2_pkt_addstring(s->pktout, ssh->cfg.termtype);
+ ssh2_pkt_addstring(s->pktout, conf_get_str(ssh->conf, CONF_termtype));
ssh2_pkt_adduint32(s->pktout, ssh->term_width);
ssh2_pkt_adduint32(s->pktout, ssh->term_height);
ssh2_pkt_adduint32(s->pktout, 0); /* pixel width */
ssh2_pkt_adduint32(s->pktout, 0); /* pixel height */
ssh2_pkt_addstring_start(s->pktout);
- parse_ttymodes(ssh, ssh->cfg.ttymodes,
- ssh2_send_ttymode, (void *)s->pktout);
+ parse_ttymodes(ssh, ssh2_send_ttymode, (void *)s->pktout);
ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_ISPEED);
ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_OSPEED);
* Simplest thing here is to send all the requests at once, and
* then wait for a whole bunch of successes or failures.
*/
- if (ssh->mainchan && !ssh->ncmode && *ssh->cfg.environmt) {
- char *e = ssh->cfg.environmt;
- char *var, *varend, *val;
+ if (ssh->mainchan && !ssh->ncmode) {
+ char *key, *val;
s->num_env = 0;
- while (*e) {
- var = e;
- while (*e && *e != '\t') e++;
- varend = e;
- if (*e == '\t') e++;
- val = e;
- while (*e) e++;
- e++;
-
+ for (val = conf_get_str_strs(ssh->conf, CONF_environmt, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(ssh->conf, CONF_environmt, key, &key)) {
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
ssh2_pkt_addstring(s->pktout, "env");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
- ssh2_pkt_addstring_start(s->pktout);
- ssh2_pkt_addstring_data(s->pktout, var, varend-var);
+ ssh2_pkt_addstring(s->pktout, key);
ssh2_pkt_addstring(s->pktout, val);
ssh2_pkt_send(ssh, s->pktout);
s->num_env++;
}
- logeventf(ssh, "Sent %d environment variables", s->num_env);
+ if (s->num_env) {
+ logeventf(ssh, "Sent %d environment variables", s->num_env);
- s->env_ok = 0;
- s->env_left = s->num_env;
+ s->env_ok = 0;
+ s->env_left = s->num_env;
- while (s->env_left > 0) {
- crWaitUntilV(pktin);
+ while (s->env_left > 0) {
+ crWaitUntilV(pktin);
- if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
- if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
- bombout(("Unexpected response to environment request:"
- " packet type %d", pktin->type));
- crStopV;
+ if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
+ if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
+ bombout(("Unexpected response to environment request:"
+ " packet type %d", pktin->type));
+ crStopV;
+ }
+ } else {
+ s->env_ok++;
}
- } else {
- s->env_ok++;
- }
- s->env_left--;
- }
+ s->env_left--;
+ }
- if (s->env_ok == s->num_env) {
- logevent("All environment variables successfully set");
- } else if (s->env_ok == 0) {
- logevent("All environment variables refused");
- c_write_str(ssh, "Server refused to set environment variables\r\n");
- } else {
- logeventf(ssh, "%d environment variables refused",
- s->num_env - s->env_ok);
- c_write_str(ssh, "Server refused to set all environment variables\r\n");
+ if (s->env_ok == s->num_env) {
+ logevent("All environment variables successfully set");
+ } else if (s->env_ok == 0) {
+ logevent("All environment variables refused");
+ c_write_str(ssh, "Server refused to set environment variables\r\n");
+ } else {
+ logeventf(ssh, "%d environment variables refused",
+ s->num_env - s->env_ok);
+ c_write_str(ssh, "Server refused to set all environment variables\r\n");
+ }
}
}
char *cmd;
if (ssh->fallback_cmd) {
- subsys = ssh->cfg.ssh_subsys2;
- cmd = ssh->cfg.remote_cmd_ptr2;
+ subsys = conf_get_int(ssh->conf, CONF_ssh_subsys2);
+ cmd = conf_get_str(ssh->conf, CONF_remote_cmd2);
} else {
- subsys = ssh->cfg.ssh_subsys;
- cmd = ssh->cfg.remote_cmd_ptr;
- if (!cmd) cmd = ssh->cfg.remote_cmd;
+ subsys = conf_get_int(ssh->conf, CONF_ssh_subsys);
+ cmd = conf_get_str(ssh->conf, CONF_remote_cmd);
}
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
* not, and if the fallback command exists, try falling
* back to it before complaining.
*/
- if (!ssh->fallback_cmd && ssh->cfg.remote_cmd_ptr2 != NULL) {
+ if (!ssh->fallback_cmd &&
+ *conf_get_str(ssh->conf, CONF_remote_cmd2)) {
logevent("Primary command failed; attempting fallback");
ssh->fallback_cmd = TRUE;
continue;
if (ssh->state == SSH_STATE_CLOSED)
return;
- if (!ssh->kex_in_progress && ssh->cfg.ssh_rekey_time != 0 &&
+ if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 &&
now - ssh->next_rekey >= 0) {
do_ssh2_transport(ssh, "timeout", -1, NULL);
}
}
}
+static void ssh_cache_conf_values(Ssh ssh)
+{
+ ssh->logomitdata = conf_get_int(ssh->conf, CONF_logomitdata);
+}
+
/*
* Called to set up the connection.
*
* Returns an error message, or NULL on success.
*/
static const char *ssh_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
- char *host, int port, char **realhost, int nodelay,
- int keepalive)
+ Conf *conf, char *host, int port, char **realhost,
+ int nodelay, int keepalive)
{
const char *p;
Ssh ssh;
ssh = snew(struct ssh_tag);
- ssh->cfg = *cfg; /* STRUCTURE COPY */
+ ssh->conf = conf_copy(conf);
+ ssh_cache_conf_values(ssh);
ssh->version = 0; /* when not ready yet */
ssh->s = NULL;
ssh->cipher = NULL;
ssh->deferred_rekey_reason = NULL;
bufchain_init(&ssh->queued_incoming_data);
ssh->frozen = FALSE;
+ ssh->username = NULL;
*backend_handle = ssh;
#endif
ssh->frontend = frontend_handle;
- ssh->term_width = ssh->cfg.width;
- ssh->term_height = ssh->cfg.height;
+ ssh->term_width = conf_get_int(ssh->conf, CONF_width);
+ ssh->term_height = conf_get_int(ssh->conf, CONF_height);
ssh->channels = NULL;
ssh->rportfwds = NULL;
ssh->incoming_data_size = ssh->outgoing_data_size =
ssh->deferred_data_size = 0L;
- ssh->max_data_size = parse_blocksize(ssh->cfg.ssh_rekey_data);
+ ssh->max_data_size = parse_blocksize(conf_get_str(ssh->conf,
+ CONF_ssh_rekey_data));
ssh->kex_in_progress = FALSE;
#ifndef NO_GSSAPI
if (ssh->pinger)
pinger_free(ssh->pinger);
bufchain_clear(&ssh->queued_incoming_data);
+ sfree(ssh->username);
+ conf_free(ssh->conf);
#ifndef NO_GSSAPI
if (ssh->gsslibs)
ssh_gss_cleanup(ssh->gsslibs);
/*
* Reconfigure the SSH backend.
*/
-static void ssh_reconfig(void *handle, Config *cfg)
+static void ssh_reconfig(void *handle, Conf *conf)
{
Ssh ssh = (Ssh) handle;
char *rekeying = NULL, rekey_mandatory = FALSE;
unsigned long old_max_data_size;
+ int i, rekey_time;
- pinger_reconfig(ssh->pinger, &ssh->cfg, cfg);
+ pinger_reconfig(ssh->pinger, ssh->conf, conf);
if (ssh->portfwds)
- ssh_setup_portfwd(ssh, cfg);
+ ssh_setup_portfwd(ssh, conf);
- if (ssh->cfg.ssh_rekey_time != cfg->ssh_rekey_time &&
- cfg->ssh_rekey_time != 0) {
- long new_next = ssh->last_rekey + cfg->ssh_rekey_time*60*TICKSPERSEC;
+ rekey_time = conf_get_int(conf, CONF_ssh_rekey_time);
+ if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time &&
+ rekey_time != 0) {
+ long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
long now = GETTICKCOUNT();
if (new_next - now < 0) {
}
old_max_data_size = ssh->max_data_size;
- ssh->max_data_size = parse_blocksize(cfg->ssh_rekey_data);
+ ssh->max_data_size = parse_blocksize(conf_get_str(ssh->conf,
+ CONF_ssh_rekey_data));
if (old_max_data_size != ssh->max_data_size &&
ssh->max_data_size != 0) {
if (ssh->outgoing_data_size > ssh->max_data_size ||
rekeying = "data limit lowered";
}
- if (ssh->cfg.compression != cfg->compression) {
+ if (conf_get_int(ssh->conf, CONF_compression) !=
+ conf_get_int(conf, CONF_compression)) {
rekeying = "compression setting changed";
rekey_mandatory = TRUE;
}
- if (ssh->cfg.ssh2_des_cbc != cfg->ssh2_des_cbc ||
- memcmp(ssh->cfg.ssh_cipherlist, cfg->ssh_cipherlist,
- sizeof(ssh->cfg.ssh_cipherlist))) {
+ for (i = 0; i < CIPHER_MAX; i++)
+ if (conf_get_int_int(ssh->conf, CONF_ssh_cipherlist, i) !=
+ conf_get_int_int(conf, CONF_ssh_cipherlist, i)) {
+ rekeying = "cipher settings changed";
+ rekey_mandatory = TRUE;
+ }
+ if (conf_get_int(ssh->conf, CONF_ssh2_des_cbc) !=
+ conf_get_int(conf, CONF_ssh2_des_cbc)) {
rekeying = "cipher settings changed";
rekey_mandatory = TRUE;
}
- ssh->cfg = *cfg; /* STRUCTURE COPY */
+ conf_free(ssh->conf);
+ ssh->conf = conf_copy(conf);
+ ssh_cache_conf_values(ssh);
if (rekeying) {
if (!ssh->kex_in_progress) {
ssh->size_needed = TRUE; /* buffer for later */
break;
case SSH_STATE_SESSION:
- if (!ssh->cfg.nopty) {
+ if (!conf_get_int(ssh->conf, CONF_nopty)) {
if (ssh->version == 1) {
send_packet(ssh, SSH1_CMSG_WINDOW_SIZE,
PKT_INT, ssh->term_height,
ssh2_set_window(ssh->mainchan,
bufsize < ssh->mainchan->v.v2.locmaxwin ?
ssh->mainchan->v.v2.locmaxwin - bufsize : 0);
- if (ssh->cfg.ssh_simple)
+ if (conf_get_int(ssh->conf, CONF_ssh_simple))
buflimit = 0;
else
buflimit = ssh->mainchan->v.v2.locmaxwin;
/* Exports from portfwd.c */
extern const char *pfd_newconnect(Socket * s, char *hostname, int port,
- void *c, const Config *cfg,
- int addressfamily);
+ void *c, Conf *conf, int addressfamily);
/* desthost == NULL indicates dynamic (SOCKS) port forwarding */
extern const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
- int port, void *backhandle,
- const Config *cfg, void **sockdata,
- int address_family);
+ int port, void *backhandle, Conf *conf,
+ void **sockdata, int address_family);
extern void pfd_close(Socket s);
extern void pfd_terminate(void *sockdata);
extern int pfd_send(Socket s, char *data, int len);
* details are looked up by calling platform_get_x11_auth.
*/
extern struct X11Display *x11_setup_display(char *display, int authtype,
- const Config *);
+ Conf *);
void x11_free_display(struct X11Display *disp);
extern const char *x11_init(Socket *, struct X11Display *, void *,
- const char *, int, const Config *);
+ const char *, int, Conf *);
extern void x11_close(Socket);
extern int x11_send(Socket, char *, int);
extern void x11_unthrottle(Socket s);
extern void x11_override_throttle(Socket s, int enable);
char *x11_display(const char *display);
/* Platform-dependent X11 functions */
-extern void platform_get_x11_auth(struct X11Display *display,
- const Config *);
+extern void platform_get_x11_auth(struct X11Display *display, Conf *);
/* examine a mostly-filled-in X11Display and fill in localauth* */
extern const int platform_uses_x11_unix_by_default;
/* choose default X transport in the absence of a specified one */
struct ssh_gss_library *libraries;
int nlibraries;
};
-struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg);
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf);
void ssh_gss_cleanup(struct ssh_gss_liblist *list);
/*
/* For platforms not supporting GSSAPI */
-struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
{
struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist *);
list->libraries = NULL;
/* ----------------------------------------------------------------------
* Functions to save and restore PuTTY sessions. Note that this is
* only the low-level code to do the reading and writing. The
- * higher-level code that translates a Config structure into a set
- * of (key,value) pairs is elsewhere, since it doesn't (mostly)
- * change between platforms.
+ * higher-level code that translates an internal Conf structure into
+ * a set of (key,value) pairs in their external storage format is
+ * elsewhere, since it doesn't (mostly) change between platforms.
*/
/*
* number of calls to read_setting_s() and read_setting_i(), and
* then close it using close_settings_r().
*
- * read_setting_s() writes into the provided buffer and returns a
- * pointer to the same buffer.
+ * read_setting_s() returns a dynamically allocated string which the
+ * caller must free.
*
* If a particular string setting is not present in the session,
* read_setting_s() can return NULL, in which case the caller
* the provided buffer, and return zero if they failed to.
*/
void *open_settings_r(const char *sessionname);
-char *read_setting_s(void *handle, const char *key, char *buffer, int buflen);
+char *read_setting_s(void *handle, const char *key);
int read_setting_i(void *handle, const char *key, int defvalue);
int read_setting_filename(void *handle, const char *key, Filename *value);
int read_setting_fontspec(void *handle, const char *key, FontSpec *font);
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} state;
- Config cfg;
+ Conf *conf;
Pinger pinger;
} *Telnet;
static void process_subneg(Telnet telnet)
{
- unsigned char b[2048], *p, *q;
- int var, value, n;
- char *e;
+ unsigned char *b, *p, *q;
+ int var, value, n, bsize;
+ char *e, *eval, *ekey, *user;
switch (telnet->sb_opt) {
case TELOPT_TSPEED:
if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) {
char *logbuf;
+ char *termspeed = conf_get_str(telnet->conf, CONF_termspeed);
+ b = snewn(20 + strlen(termspeed), unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
- strcpy((char *)(b + 4), telnet->cfg.termspeed);
- n = 4 + strlen(telnet->cfg.termspeed);
+ strcpy((char *)(b + 4), termspeed);
+ n = 4 + strlen(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");
- logbuf = dupprintf("client:\tSB TSPEED IS %s", telnet->cfg.termspeed);
+ logbuf = dupprintf("client:\tSB TSPEED IS %s", termspeed);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
+ sfree(b);
} else
logevent(telnet->frontend, "server:\tSB TSPEED <something weird>");
break;
case TELOPT_TTYPE:
if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) {
char *logbuf;
+ char *termtype = conf_get_str(telnet->conf, CONF_termtype);
+ b = snewn(20 + strlen(termtype), unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
- 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]);
+ for (n = 0; termtype[n]; n++)
+ b[n + 4] = (termtype[n] >= 'a' && termtype[n] <= 'z' ?
+ termtype[n] + 'A' - 'a' :
+ termtype[n]);
b[n + 4] = IAC;
b[n + 5] = SE;
telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6);
logbuf = dupprintf("client:\tSB TTYPE IS %s", b + 4);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
+ sfree(b);
} else
logevent(telnet->frontend, "server:\tSB TTYPE <something weird>\r\n");
break;
logevent(telnet->frontend, logbuf);
sfree(logbuf);
if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
- if (telnet->cfg.rfc_environ) {
+ if (conf_get_str(telnet->conf, CONF_rfc_environ)) {
value = RFC_VALUE;
var = RFC_VAR;
} else {
value = RFC_VALUE;
var = RFC_VAR;
}
+ bsize = 20;
+ for (eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ NULL, &ekey);
+ eval != NULL;
+ eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ ekey, &ekey))
+ bsize += strlen(ekey) + strlen(eval) + 2;
+ user = get_remote_username(telnet->conf);
+ if (user)
+ bsize += 6 + strlen(user);
+
+ b = snewn(bsize, unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = telnet->sb_opt;
b[3] = TELQUAL_IS;
n = 4;
- e = telnet->cfg.environmt;
- while (*e) {
+ for (eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ NULL, &ekey);
+ eval != NULL;
+ eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ ekey, &ekey)) {
b[n++] = var;
- while (*e && *e != '\t')
- b[n++] = *e++;
- if (*e == '\t')
- e++;
+ for (e = ekey; *e; e++)
+ b[n++] = *e;
b[n++] = value;
- while (*e)
- b[n++] = *e++;
- e++;
+ for (e = eval; *e; e++)
+ b[n++] = *e;
}
- {
- char user[sizeof(telnet->cfg.username)];
- (void) get_remote_username(&telnet->cfg, user, sizeof(user));
- if (*user) {
- b[n++] = var;
- b[n++] = 'U';
- b[n++] = 'S';
- b[n++] = 'E';
- b[n++] = 'R';
- b[n++] = value;
- e = user;
- while (*e)
- b[n++] = *e++;
- }
- b[n++] = IAC;
- b[n++] = SE;
- telnet->bufsize = sk_write(telnet->s, (char *)b, n);
- logbuf = dupprintf("client:\tSB %s IS %s%s%s%s",
- telopt(telnet->sb_opt),
- *user ? "USER=" : "",
- user,
- *user ? " " : "",
- n == 6 ? "<nothing>" :
- (*telnet->cfg.environmt ? "<stuff>" : ""));
+ if (user) {
+ b[n++] = var;
+ b[n++] = 'U';
+ b[n++] = 'S';
+ b[n++] = 'E';
+ b[n++] = 'R';
+ b[n++] = value;
+ for (e = user; *e; e++)
+ b[n++] = *e;
+ }
+ b[n++] = IAC;
+ b[n++] = SE;
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n);
+ if (n == 6) {
+ logbuf = dupprintf("client:\tSB %s IS <nothing>",
+ telopt(telnet->sb_opt));
logevent(telnet->frontend, logbuf);
sfree(logbuf);
+ } else {
+ logbuf = dupprintf("client:\tSB %s IS:",
+ telopt(telnet->sb_opt));
+ logevent(telnet->frontend, logbuf);
+ sfree(logbuf);
+ for (eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ NULL, &ekey);
+ eval != NULL;
+ eval = conf_get_str_strs(telnet->conf, CONF_environmt,
+ ekey, &ekey)) {
+ logbuf = dupprintf("\t%s=%s", ekey, eval);
+ logevent(telnet->frontend, logbuf);
+ sfree(logbuf);
+ }
+ if (user) {
+ logbuf = dupprintf("\tUSER=%s", user);
+ logevent(telnet->frontend, logbuf);
+ sfree(logbuf);
+ }
}
+ sfree(b);
+ sfree(user);
}
break;
}
* freed by the caller.
*/
static const char *telnet_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
- char *host, int port, char **realhost,
- int nodelay, int keepalive)
+ Conf *conf, char *host, int port,
+ char **realhost, int nodelay, int keepalive)
{
static const struct plug_function_table fn_table = {
telnet_log,
SockAddr addr;
const char *err;
Telnet telnet;
+ char *loghost;
+ int addressfamily;
telnet = snew(struct telnet_tag);
telnet->fn = &fn_table;
- telnet->cfg = *cfg; /* STRUCTURE COPY */
+ telnet->conf = conf_copy(conf);
telnet->s = NULL;
telnet->echoing = TRUE;
telnet->editing = TRUE;
telnet->sb_buf = NULL;
telnet->sb_size = 0;
telnet->frontend = frontend_handle;
- telnet->term_width = telnet->cfg.width;
- telnet->term_height = telnet->cfg.height;
+ telnet->term_width = conf_get_int(telnet->conf, CONF_width);
+ telnet->term_height = conf_get_int(telnet->conf, CONF_height);
telnet->state = TOP_LEVEL;
telnet->ldisc = NULL;
telnet->pinger = NULL;
*/
{
char *buf;
+ addressfamily = conf_get_int(telnet->conf, CONF_addressfamily);
buf = dupprintf("Looking up host \"%s\"%s", host,
- (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
- (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
+ (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
+ (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
"")));
logevent(telnet->frontend, buf);
sfree(buf);
}
- addr = name_lookup(host, port, realhost, &telnet->cfg, cfg->addressfamily);
+ addr = name_lookup(host, port, realhost, telnet->conf, addressfamily);
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
* Open socket.
*/
telnet->s = new_connection(addr, *realhost, port, 0, 1,
- nodelay, keepalive, (Plug) telnet, &telnet->cfg);
+ nodelay, keepalive, (Plug) telnet, telnet->conf);
if ((err = sk_socket_error(telnet->s)) != NULL)
return err;
- telnet->pinger = pinger_new(&telnet->cfg, &telnet_backend, telnet);
+ telnet->pinger = pinger_new(telnet->conf, &telnet_backend, telnet);
/*
* Initialise option states.
*/
- if (telnet->cfg.passive_telnet) {
+ if (conf_get_int(telnet->conf, CONF_passive_telnet)) {
const struct Opt *const *o;
for (o = opts; *o; o++)
/*
* loghost overrides realhost, if specified.
*/
- if (*telnet->cfg.loghost) {
+ loghost = conf_get_str(telnet->conf, CONF_loghost);
+ if (*loghost) {
char *colon;
sfree(*realhost);
- *realhost = dupstr(telnet->cfg.loghost);
+ *realhost = dupstr(loghost);
colon = strrchr(*realhost, ':');
if (colon) {
/*
sk_close(telnet->s);
if (telnet->pinger)
pinger_free(telnet->pinger);
+ conf_free(telnet->conf);
sfree(telnet);
}
/*
* necessary, in this backend: we just save the fresh config for
* any subsequent negotiations.
*/
-static void telnet_reconfig(void *handle, Config *cfg)
+static void telnet_reconfig(void *handle, Conf *conf)
{
Telnet telnet = (Telnet) handle;
- pinger_reconfig(telnet->pinger, &telnet->cfg, cfg);
- telnet->cfg = *cfg; /* STRUCTURE COPY */
+ pinger_reconfig(telnet->pinger, telnet->conf, conf);
+ conf_free(telnet->conf);
+ telnet->conf = conf_copy(conf);
}
/*
static int sblines(Terminal *term)
{
int sblines = count234(term->scrollback);
- if (term->cfg.erase_to_scrollback &&
+ if (term->erase_to_scrollback &&
term->alt_which && term->alt_screen) {
sblines += term->alt_sblines;
}
assert(!screen);
- if (term->cfg.erase_to_scrollback &&
+ if (term->erase_to_scrollback &&
term->alt_which && term->alt_screen) {
altlines = term->alt_sblines;
}
*/
static void term_schedule_cblink(Terminal *term)
{
- if (term->cfg.blink_cur && term->has_focus) {
+ if (term->blink_cur && term->has_focus) {
if (!term->cblink_pending)
term->next_cblink = schedule_timer(CBLINK_DELAY, term_timer, term);
term->cblink_pending = TRUE;
for (i = 0; i < term->cols; i++)
term->tabs[i] = (i % 8 == 0 ? TRUE : FALSE);
}
- term->alt_om = term->dec_om = term->cfg.dec_om;
+ term->alt_om = term->dec_om = conf_get_int(term->conf, CONF_dec_om);
term->alt_ins = term->insert = FALSE;
term->alt_wnext = term->wrapnext =
term->save_wnext = term->alt_save_wnext = FALSE;
- term->alt_wrap = term->wrap = term->cfg.wrap_mode;
+ term->alt_wrap = term->wrap = conf_get_int(term->conf, CONF_wrap_mode);
term->alt_cset = term->cset = term->save_cset = term->alt_save_cset = 0;
term->alt_utf = term->utf = term->save_utf = term->alt_save_utf = 0;
term->utf_state = 0;
term->default_attr = term->save_attr =
term->alt_save_attr = term->curr_attr = ATTR_DEFAULT;
term->term_editing = term->term_echoing = FALSE;
- term->app_cursor_keys = term->cfg.app_cursor;
- term->app_keypad_keys = term->cfg.app_keypad;
- term->use_bce = term->cfg.bce;
- term->blink_is_real = term->cfg.blinktext;
+ term->app_cursor_keys = conf_get_int(term->conf, CONF_app_cursor);
+ term->app_keypad_keys = conf_get_int(term->conf, CONF_app_keypad);
+ term->use_bce = conf_get_int(term->conf, CONF_bce);
+ term->blink_is_real = conf_get_int(term->conf, CONF_blinktext);
term->erase_char = term->basic_erase_char;
term->alt_which = 0;
term_print_finish(term);
{
int i;
for (i = 0; i < 256; i++)
- term->wordness[i] = term->cfg.wordness[i];
+ term->wordness[i] = conf_get_int_int(term->conf, CONF_wordness, i);
}
if (term->screen) {
swap_screen(term, 1, FALSE, FALSE);
ctx = get_ctx(term->frontend);
if (ctx) {
int need_sbar_update = term->seen_disp_event;
- if (term->seen_disp_event && term->cfg.scroll_on_disp) {
+ if (term->seen_disp_event && term->scroll_on_disp) {
term->disptop = 0; /* return to main screen */
term->seen_disp_event = 0;
need_sbar_update = TRUE;
/*
* Reset the scrollback on keypress, if we're doing that.
*/
- if (term->cfg.scroll_on_key) {
+ if (term->scroll_on_key) {
term->disptop = 0; /* return to main screen */
seen_disp_event(term);
}
}
/*
+ * We copy a bunch of stuff out of the Conf structure into local
+ * fields in the Terminal structure, to avoid the repeated tree234
+ * lookups which would be involved in fetching them from the former
+ * every time.
+ */
+void term_copy_stuff_from_conf(Terminal *term)
+{
+ term->ansi_colour = conf_get_int(term->conf, CONF_ansi_colour);
+ term->arabicshaping = conf_get_int(term->conf, CONF_arabicshaping);
+ term->beep = conf_get_int(term->conf, CONF_beep);
+ term->bellovl = conf_get_int(term->conf, CONF_bellovl);
+ term->bellovl_n = conf_get_int(term->conf, CONF_bellovl_n);
+ term->bellovl_s = conf_get_int(term->conf, CONF_bellovl_s);
+ term->bellovl_t = conf_get_int(term->conf, CONF_bellovl_t);
+ term->bidi = conf_get_int(term->conf, CONF_bidi);
+ term->bksp_is_delete = conf_get_int(term->conf, CONF_bksp_is_delete);
+ term->blink_cur = conf_get_int(term->conf, CONF_blink_cur);
+ term->blinktext = conf_get_int(term->conf, CONF_blinktext);
+ term->cjk_ambig_wide = conf_get_int(term->conf, CONF_cjk_ambig_wide);
+ term->conf_height = conf_get_int(term->conf, CONF_height);
+ term->conf_width = conf_get_int(term->conf, CONF_width);
+ term->crhaslf = conf_get_int(term->conf, CONF_crhaslf);
+ term->erase_to_scrollback = conf_get_int(term->conf, CONF_erase_to_scrollback);
+ term->funky_type = conf_get_int(term->conf, CONF_funky_type);
+ term->lfhascr = conf_get_int(term->conf, CONF_lfhascr);
+ term->logflush = conf_get_int(term->conf, CONF_logflush);
+ term->logtype = conf_get_int(term->conf, CONF_logtype);
+ term->mouse_override = conf_get_int(term->conf, CONF_mouse_override);
+ term->nethack_keypad = conf_get_int(term->conf, CONF_nethack_keypad);
+ term->no_alt_screen = conf_get_int(term->conf, CONF_no_alt_screen);
+ term->no_applic_c = conf_get_int(term->conf, CONF_no_applic_c);
+ term->no_applic_k = conf_get_int(term->conf, CONF_no_applic_k);
+ term->no_dbackspace = conf_get_int(term->conf, CONF_no_dbackspace);
+ term->no_mouse_rep = conf_get_int(term->conf, CONF_no_mouse_rep);
+ term->no_remote_charset = conf_get_int(term->conf, CONF_no_remote_charset);
+ term->no_remote_resize = conf_get_int(term->conf, CONF_no_remote_resize);
+ term->no_remote_wintitle = conf_get_int(term->conf, CONF_no_remote_wintitle);
+ term->rawcnp = conf_get_int(term->conf, CONF_rawcnp);
+ term->rect_select = conf_get_int(term->conf, CONF_rect_select);
+ term->remote_qtitle_action = conf_get_int(term->conf, CONF_remote_qtitle_action);
+ term->rxvt_homeend = conf_get_int(term->conf, CONF_rxvt_homeend);
+ term->scroll_on_disp = conf_get_int(term->conf, CONF_scroll_on_disp);
+ term->scroll_on_key = conf_get_int(term->conf, CONF_scroll_on_key);
+ term->xterm_256_colour = conf_get_int(term->conf, CONF_xterm_256_colour);
+
+ /*
+ * Parse the control-character escapes in the configured
+ * answerback string.
+ */
+ {
+ char *answerback = conf_get_str(term->conf, CONF_answerback);
+ int maxlen = strlen(answerback);
+
+ term->answerback = snewn(maxlen, char);
+ term->answerbacklen = 0;
+
+ while (*answerback) {
+ char *n;
+ char c = ctrlparse(answerback, &n);
+ if (n) {
+ term->answerback[term->answerbacklen++] = c;
+ answerback = n;
+ } else {
+ term->answerback[term->answerbacklen++] = *answerback++;
+ }
+ }
+ }
+}
+
+/*
* When the user reconfigures us, we need to check the forbidden-
* alternate-screen config option, disable raw mouse mode if the
* user has disabled mouse reporting, and abandon a print job if
* the user has disabled printing.
*/
-void term_reconfig(Terminal *term, Config *cfg)
+void term_reconfig(Terminal *term, Conf *conf)
{
/*
* Before adopting the new config, check all those terminal
int reset_wrap, reset_decom, reset_bce, reset_tblink, reset_charclass;
int i;
- reset_wrap = (term->cfg.wrap_mode != cfg->wrap_mode);
- reset_decom = (term->cfg.dec_om != cfg->dec_om);
- reset_bce = (term->cfg.bce != cfg->bce);
- reset_tblink = (term->cfg.blinktext != cfg->blinktext);
+ reset_wrap = (conf_get_int(term->conf, CONF_wrap_mode) !=
+ conf_get_int(conf, CONF_wrap_mode));
+ reset_decom = (conf_get_int(term->conf, CONF_dec_om) !=
+ conf_get_int(conf, CONF_dec_om));
+ reset_bce = (conf_get_int(term->conf, CONF_bce) !=
+ conf_get_int(conf, CONF_bce));
+ reset_tblink = (conf_get_int(term->conf, CONF_blinktext) !=
+ conf_get_int(conf, CONF_blinktext));
reset_charclass = 0;
- for (i = 0; i < lenof(term->cfg.wordness); i++)
- if (term->cfg.wordness[i] != cfg->wordness[i])
+ for (i = 0; i < 256; i++)
+ if (conf_get_int_int(term->conf, CONF_wordness, i) !=
+ conf_get_int_int(conf, CONF_wordness, i))
reset_charclass = 1;
/*
* If the bidi or shaping settings have changed, flush the bidi
* cache completely.
*/
- if (term->cfg.arabicshaping != cfg->arabicshaping ||
- term->cfg.bidi != cfg->bidi) {
+ if (conf_get_int(term->conf, CONF_arabicshaping) !=
+ conf_get_int(conf, CONF_arabicshaping) ||
+ conf_get_int(term->conf, CONF_bidi) !=
+ conf_get_int(conf, CONF_bidi)) {
for (i = 0; i < term->bidi_cache_size; i++) {
sfree(term->pre_bidi_cache[i].chars);
sfree(term->post_bidi_cache[i].chars);
}
}
- term->cfg = *cfg; /* STRUCTURE COPY */
+ conf_free(term->conf);
+ term->conf = conf_copy(conf);
if (reset_wrap)
- term->alt_wrap = term->wrap = term->cfg.wrap_mode;
+ term->alt_wrap = term->wrap = conf_get_int(term->conf, CONF_wrap_mode);
if (reset_decom)
- term->alt_om = term->dec_om = term->cfg.dec_om;
+ term->alt_om = term->dec_om = conf_get_int(term->conf, CONF_dec_om);
if (reset_bce) {
- term->use_bce = term->cfg.bce;
+ term->use_bce = conf_get_int(term->conf, CONF_bce);
set_erase_char(term);
}
if (reset_tblink) {
- term->blink_is_real = term->cfg.blinktext;
+ term->blink_is_real = conf_get_int(term->conf, CONF_blinktext);
}
if (reset_charclass)
for (i = 0; i < 256; i++)
- term->wordness[i] = term->cfg.wordness[i];
+ term->wordness[i] = conf_get_int_int(term->conf, CONF_wordness, i);
- if (term->cfg.no_alt_screen)
+ if (conf_get_int(term->conf, CONF_no_alt_screen))
swap_screen(term, 0, FALSE, FALSE);
- if (term->cfg.no_mouse_rep) {
+ if (conf_get_int(term->conf, CONF_no_mouse_rep)) {
term->xterm_mouse = 0;
set_raw_mouse_mode(term->frontend, 0);
}
- if (term->cfg.no_remote_charset) {
+ if (conf_get_int(term->conf, CONF_no_remote_charset)) {
term->cset_attr[0] = term->cset_attr[1] = CSET_ASCII;
term->sco_acs = term->alt_sco_acs = 0;
term->utf = 0;
}
- if (!*term->cfg.printer) {
+ if (!conf_get_str(term->conf, CONF_printer)) {
term_print_finish(term);
}
term_schedule_tblink(term);
term_schedule_cblink(term);
+ term_copy_stuff_from_conf(term);
}
/*
/*
* Initialise the terminal.
*/
-Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata,
+Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata,
void *frontend)
{
Terminal *term;
term = snew(Terminal);
term->frontend = frontend;
term->ucsdata = ucsdata;
- term->cfg = *mycfg; /* STRUCTURE COPY */
+ term->conf = conf_copy(myconf);
term->logctx = NULL;
term->compatibility_level = TM_PUTTY;
strcpy(term->id_string, "\033[?6c");
term->basic_erase_char.cc_next = 0;
term->erase_char = term->basic_erase_char;
+ term_copy_stuff_from_conf(term);
+
return term;
}
expire_timer_context(term);
+ conf_free(term->conf);
+
sfree(term);
}
if (start.y == 0 && start.x == 0 && end.x == 0 && erase_lattr)
erasing_lines_from_top = 1;
- if (term->cfg.erase_to_scrollback && erasing_lines_from_top) {
+ if (term->erase_to_scrollback && erasing_lines_from_top) {
/* If it's a whole number of lines, starting at the top, and
* we're fully erasing them, erase by scrolling and keep the
* lines in the scrollback. */
term->blink_is_real = FALSE;
term->vt52_bold = FALSE;
} else {
- term->blink_is_real = term->cfg.blinktext;
+ term->blink_is_real = term->blinktext;
}
term_schedule_tblink(term);
break;
case 3: /* DECCOLM: 80/132 columns */
deselect(term);
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend, state ? 132 : 80, term->rows);
term->reset_132 = state;
term->alt_t = term->marg_t = 0;
case 47: /* alternate screen */
compatibility(OTHER);
deselect(term);
- swap_screen(term, term->cfg.no_alt_screen ? 0 : state, FALSE, FALSE);
+ swap_screen(term, term->no_alt_screen ? 0 : state, FALSE, FALSE);
term->disptop = 0;
break;
case 1000: /* xterm mouse 1 (normal) */
case 1047: /* alternate screen */
compatibility(OTHER);
deselect(term);
- swap_screen(term, term->cfg.no_alt_screen ? 0 : state, TRUE, TRUE);
+ swap_screen(term, term->no_alt_screen ? 0 : state, TRUE, TRUE);
term->disptop = 0;
break;
case 1048: /* save/restore cursor */
- if (!term->cfg.no_alt_screen)
+ if (!term->no_alt_screen)
save_cursor(term, state);
if (!state) seen_disp_event(term);
break;
case 1049: /* cursor & alternate screen */
- if (state && !term->cfg.no_alt_screen)
+ if (state && !term->no_alt_screen)
save_cursor(term, state);
if (!state) seen_disp_event(term);
compatibility(OTHER);
deselect(term);
- swap_screen(term, term->cfg.no_alt_screen ? 0 : state, TRUE, FALSE);
- if (!state && !term->cfg.no_alt_screen)
+ swap_screen(term, term->no_alt_screen ? 0 : state, TRUE, FALSE);
+ if (!state && !term->no_alt_screen)
save_cursor(term, state);
term->disptop = 0;
break;
switch (term->esc_args[0]) {
case 0:
case 1:
- if (!term->cfg.no_remote_wintitle)
+ if (!term->no_remote_wintitle)
set_icon(term->frontend, term->osc_string);
if (term->esc_args[0] == 1)
break;
/* fall through: parameter 0 means set both */
case 2:
case 21:
- if (!term->cfg.no_remote_wintitle)
+ if (!term->no_remote_wintitle)
set_title(term->frontend, term->osc_string);
break;
}
/*
* ANSI printing routines.
*/
-static void term_print_setup(Terminal *term)
+static void term_print_setup(Terminal *term, char *printer)
{
bufchain_clear(&term->printer_buf);
- term->print_job = printer_start_job(term->cfg.printer);
+ term->print_job = printer_start_job(printer);
}
static void term_print_flush(Terminal *term)
{
* Optionally log the session traffic to a file. Useful for
* debugging and possibly also useful for actual logging.
*/
- if (term->cfg.logtype == LGTYP_DEBUG && term->logctx)
+ if (term->logtype == LGTYP_DEBUG && term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_DEBUG);
} else {
c = unget;
term->curs.x--;
term->wrapnext = FALSE;
/* destructive backspace might be disabled */
- if (!term->cfg.no_dbackspace) {
+ if (!term->no_dbackspace) {
check_boundary(term, term->curs.x, term->curs.y);
check_boundary(term, term->curs.x+1, term->curs.y);
copy_termchar(scrlineptr(term->curs.y),
*/
compatibility(ANSIMIN);
if (term->ldisc) {
- char abuf[lenof(term->cfg.answerback)], *s, *d;
- for (s = term->cfg.answerback, d = abuf; *s;) {
- char *n;
- char c = ctrlparse(s, &n);
- if (n) {
- *d++ = c;
- s = n;
- } else {
- *d++ = *s++;
- }
- }
lpage_send(term->ldisc, DEFAULT_CODEPAGE,
- abuf, d - abuf, 0);
+ term->answerback, term->answerbacklen, 0);
}
break;
case '\007': /* BEL: Bell */
* t seconds ago.
*/
while (term->beephead &&
- term->beephead->ticks < ticks - term->cfg.bellovl_t) {
+ term->beephead->ticks < ticks - term->bellovl_t) {
struct beeptime *tmp = term->beephead;
term->beephead = tmp->next;
sfree(tmp);
term->nbeeps--;
}
- if (term->cfg.bellovl && term->beep_overloaded &&
- ticks - term->lastbeep >= (unsigned)term->cfg.bellovl_s) {
+ if (term->bellovl && term->beep_overloaded &&
+ ticks - term->lastbeep >= (unsigned)term->bellovl_s) {
/*
* If we're currently overloaded and the
* last beep was more than s seconds ago,
* leave overload mode.
*/
term->beep_overloaded = FALSE;
- } else if (term->cfg.bellovl && !term->beep_overloaded &&
- term->nbeeps >= term->cfg.bellovl_n) {
+ } else if (term->bellovl && !term->beep_overloaded &&
+ term->nbeeps >= term->bellovl_n) {
/*
* Now, if we have n or more beeps
* remaining in the queue, go into overload
/*
* Perform an actual beep if we're not overloaded.
*/
- if (!term->cfg.bellovl || !term->beep_overloaded) {
- do_beep(term->frontend, term->cfg.beep);
+ if (!term->bellovl || !term->beep_overloaded) {
+ do_beep(term->frontend, term->beep);
- if (term->cfg.beep == BELL_VISUAL) {
+ if (term->beep == BELL_VISUAL) {
term_schedule_vbell(term, FALSE, 0);
}
}
seen_disp_event(term);
term->paste_hold = 0;
- if (term->cfg.crhaslf) {
- if (term->curs.y == term->marg_b)
- scroll(term, term->marg_t, term->marg_b, 1, TRUE);
- else if (term->curs.y < term->rows - 1)
- term->curs.y++;
- }
+ if (term->crhaslf) {
+ if (term->curs.y == term->marg_b)
+ scroll(term, term->marg_t, term->marg_b, 1, TRUE);
+ else if (term->curs.y < term->rows - 1)
+ term->curs.y++;
+ }
if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break;
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
- if (term->cfg.lfhascr)
+ if (term->lfhascr)
term->curs.x = 0;
term->wrapnext = FALSE;
seen_disp_event(term);
if (DIRECT_CHAR(c))
width = 1;
if (!width)
- width = (term->cfg.cjk_ambig_wide ?
+ width = (term->cjk_ambig_wide ?
mk_wcwidth_cjk((wchar_t) c) :
mk_wcwidth((wchar_t) c));
if (term->ldisc) /* cause ldisc to notice changes */
ldisc_send(term->ldisc, NULL, 0, 0);
if (term->reset_132) {
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend, 80, term->rows);
term->reset_132 = 0;
}
/* GZD4: G0 designate 94-set */
case ANSI('A', '('):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[0] = CSET_GBCHR;
break;
case ANSI('B', '('):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[0] = CSET_ASCII;
break;
case ANSI('0', '('):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[0] = CSET_LINEDRW;
break;
case ANSI('U', '('):
compatibility(OTHER);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[0] = CSET_SCOACS;
break;
/* G1D4: G1-designate 94-set */
case ANSI('A', ')'):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[1] = CSET_GBCHR;
break;
case ANSI('B', ')'):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[1] = CSET_ASCII;
break;
case ANSI('0', ')'):
compatibility(VT100);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[1] = CSET_LINEDRW;
break;
case ANSI('U', ')'):
compatibility(OTHER);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->cset_attr[1] = CSET_SCOACS;
break;
/* DOCS: Designate other coding system */
case ANSI('8', '%'): /* Old Linux code */
case ANSI('G', '%'):
compatibility(OTHER);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->utf = 1;
break;
case ANSI('@', '%'):
compatibility(OTHER);
- if (!term->cfg.no_remote_charset)
+ if (!term->no_remote_charset)
term->utf = 0;
break;
}
case ANSI_QUE('i'):
compatibility(VT100);
{
+ char *printer;
if (term->esc_nargs != 1) break;
- if (term->esc_args[0] == 5 && *term->cfg.printer) {
+ if (term->esc_args[0] == 5 &&
+ (printer = conf_get_str(term->conf,
+ CONF_printer))[0]) {
term->printing = TRUE;
term->only_printing = !term->esc_query;
term->print_state = 0;
- term_print_setup(term);
+ term_print_setup(term, printer);
} else if (term->esc_args[0] == 4 &&
term->printing) {
term_print_finish(term);
break;
case 10: /* SCO acs off */
compatibility(SCOANSI);
- if (term->cfg.no_remote_charset) break;
+ if (term->no_remote_charset) break;
term->sco_acs = 0; break;
case 11: /* SCO acs on */
compatibility(SCOANSI);
- if (term->cfg.no_remote_charset) break;
+ if (term->no_remote_charset) break;
term->sco_acs = 1; break;
case 12: /* SCO acs on, |0x80 */
compatibility(SCOANSI);
- if (term->cfg.no_remote_charset) break;
+ if (term->no_remote_charset) break;
term->sco_acs = 2; break;
case 22: /* disable bold */
compatibility2(OTHER, VT220);
&& (term->esc_args[0] < 1 ||
term->esc_args[0] >= 24)) {
compatibility(VT340TEXT);
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend, term->cols,
def(term->esc_args[0], 24));
deselect(term);
break;
case 3:
if (term->esc_nargs >= 3) {
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
move_window(term->frontend,
def(term->esc_args[1], 0),
def(term->esc_args[2], 0));
break;
case 8:
if (term->esc_nargs >= 3) {
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend,
- def(term->esc_args[2], term->cfg.width),
- def(term->esc_args[1], term->cfg.height));
+ def(term->esc_args[2], term->conf_width),
+ def(term->esc_args[1], term->conf_height));
}
break;
case 9:
break;
case 20:
if (term->ldisc &&
- term->cfg.remote_qtitle_action != TITLE_NONE) {
- if(term->cfg.remote_qtitle_action == TITLE_REAL)
+ term->remote_qtitle_action != TITLE_NONE) {
+ if(term->remote_qtitle_action == TITLE_REAL)
p = get_window_title(term->frontend, TRUE);
else
p = EMPTY_WINDOW_TITLE;
break;
case 21:
if (term->ldisc &&
- term->cfg.remote_qtitle_action != TITLE_NONE) {
- if(term->cfg.remote_qtitle_action == TITLE_REAL)
+ term->remote_qtitle_action != TITLE_NONE) {
+ if(term->remote_qtitle_action == TITLE_REAL)
p = get_window_title(term->frontend, FALSE);
else
p = EMPTY_WINDOW_TITLE;
*/
compatibility(VT420);
if (term->esc_nargs == 1 && term->esc_args[0] > 0) {
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend, term->cols,
def(term->esc_args[0],
- term->cfg.height));
+ term->conf_height));
deselect(term);
}
break;
*/
compatibility(VT340TEXT);
if (term->esc_nargs <= 1) {
- if (!term->cfg.no_remote_resize)
+ if (!term->no_remote_resize)
request_resize(term->frontend,
def(term->esc_args[0],
- term->cfg.width), term->rows);
+ term->conf_width),
+ term->rows);
deselect(term);
}
break;
* Well we should do a soft reset at this point ...
*/
if (!has_compat(VT420) && has_compat(VT100)) {
- if (!term->cfg.no_remote_resize) {
+ if (!term->no_remote_resize) {
if (term->reset_132)
request_resize(132, 24);
else
* emulation.
*/
term->vt52_mode = FALSE;
- term->blink_is_real = term->cfg.blinktext;
+ term->blink_is_real = term->blinktext;
term_schedule_tblink(term);
break;
#if 0
}
term_print_flush(term);
- if (term->cfg.logflush)
+ if (term->logflush)
logflush(term->logctx);
}
int it;
/* Do Arabic shaping and bidi. */
- if(!term->cfg.bidi || !term->cfg.arabicshaping) {
+ if(!term->bidi || !term->arabicshaping) {
if (!term_bidi_cache_hit(term, scr_y, ldata->chars, term->cols)) {
switch (uc & CSET_MASK) {
case CSET_LINEDRW:
- if (!term->cfg.rawcnp) {
+ if (!term->rawcnp) {
uc = term->ucsdata->unitab_xterm[uc & 0xFF];
break;
}
term->wcFrom[it].index = it;
}
- if(!term->cfg.bidi)
+ if(!term->bidi)
do_bidi(term->wcFrom, term->cols);
/* this is saved iff done from inside the shaping */
- if(!term->cfg.bidi && term->cfg.arabicshaping)
+ if(!term->bidi && term->arabicshaping)
for(it=0; it<term->cols; it++)
term->wcTo[it] = term->wcFrom[it];
- if(!term->cfg.arabicshaping)
+ if(!term->arabicshaping)
do_shape(term->wcFrom, term->wcTo, term->cols);
if (term->ltemp_size < ldata->size) {
/* Depends on:
* screen array, disptop, scrtop,
* selection, rv,
- * cfg.blinkpc, blink_is_real, tblinker,
- * curs.y, curs.x, cblinker, cfg.blink_cur, cursor_on, has_focus, wrapnext
+ * blinkpc, blink_is_real, tblinker,
+ * curs.y, curs.x, cblinker, blink_cur, cursor_on, has_focus, wrapnext
*/
/* Has the cursor position or type changed ? */
if (term->cursor_on) {
if (term->has_focus) {
- if (term->cblinker || !term->cfg.blink_cur)
+ if (term->cblinker || !term->blink_cur)
cursor = TATTR_ACTCURS;
else
cursor = 0;
tchar = d->chr;
tattr = d->attr;
- if (!term->cfg.ansi_colour)
+ if (!term->ansi_colour)
tattr = (tattr & ~(ATTR_FGMASK | ATTR_BGMASK)) |
ATTR_DEFFG | ATTR_DEFBG;
- if (!term->cfg.xterm_256_colour) {
+ if (!term->xterm_256_colour) {
int colour;
colour = (tattr & ATTR_FGMASK) >> ATTR_FGSHIFT;
if (colour >= 16 && colour < 256)
switch (uc & CSET_MASK) {
case CSET_LINEDRW:
- if (!term->cfg.rawcnp) {
+ if (!term->rawcnp) {
uc = term->ucsdata->unitab_xterm[uc & 0xFF];
break;
}
pos selpoint;
termline *ldata;
int raw_mouse = (term->xterm_mouse &&
- !term->cfg.no_mouse_rep &&
- !(term->cfg.mouse_override && shift));
+ !term->no_mouse_rep &&
+ !(term->mouse_override && shift));
int default_seltype;
if (y < 0) {
* Set the selection type (rectangular or normal) at the start
* of a selection attempt, from the state of Alt.
*/
- if (!alt ^ !term->cfg.rect_select)
+ if (!alt ^ !term->rect_select)
default_seltype = RECTANGULAR;
else
default_seltype = LEXICOGRAPHIC;
if (term->vt52_mode)
p += sprintf((char *) p, "\x1B%c", xkey);
else {
- int app_flg = (term->app_cursor_keys && !term->cfg.no_applic_c);
+ int app_flg = (term->app_cursor_keys && !term->no_applic_c);
#if 0
/*
* RDB: VT100 & VT102 manuals both state the app cursor
}
/* Nethack keypad */
- if (term->cfg.nethack_keypad) {
+ if (term->nethack_keypad) {
char c = 0;
switch (keysym) {
case PK_KP1: c = 'b'; break;
* In VT400 mode, PFn always emits an escape sequence. In
* Linux and tilde modes, this only happens in app keypad mode.
*/
- if (term->cfg.funky_type == FUNKY_VT400 ||
- ((term->cfg.funky_type == FUNKY_LINUX ||
- term->cfg.funky_type == FUNKY_TILDE) &&
- term->app_keypad_keys && !term->cfg.no_applic_k)) {
+ if (term->funky_type == FUNKY_VT400 ||
+ ((term->funky_type == FUNKY_LINUX ||
+ term->funky_type == FUNKY_TILDE) &&
+ term->app_keypad_keys && !term->no_applic_k)) {
switch (keysym) {
case PK_PF1: xkey = 'P'; break;
case PK_PF2: xkey = 'Q'; break;
default: break; /* else gcc warns `enum value not used' */
}
}
- if (term->app_keypad_keys && !term->cfg.no_applic_k) {
+ if (term->app_keypad_keys && !term->no_applic_k) {
switch (keysym) {
case PK_KP0: xkey = 'p'; break;
case PK_KP1: xkey = 'q'; break;
case PK_KPENTER: xkey = 'M'; break;
default: break; /* else gcc warns `enum value not used' */
}
- if (term->cfg.funky_type == FUNKY_XTERM && tlen > 0) {
+ if (term->funky_type == FUNKY_XTERM && tlen > 0) {
/*
* xterm can't see the layout of the keypad, so it has
* to rely on the X keysyms returned by the keys.
goto done;
case PK_BACKSPACE:
if (modifiers == 0)
- *p++ = (term->cfg.bksp_is_delete ? 0x7F : 0x08);
+ *p++ = (term->bksp_is_delete ? 0x7F : 0x08);
else if (modifiers == PKM_SHIFT)
/* We do the opposite of what is configured */
- *p++ = (term->cfg.bksp_is_delete ? 0x08 : 0x7F);
+ *p++ = (term->bksp_is_delete ? 0x08 : 0x7F);
else break;
goto done;
case PK_TAB:
}
/* SCO function keys and editing keys */
- if (term->cfg.funky_type == FUNKY_SCO) {
+ if (term->funky_type == FUNKY_SCO) {
if (PK_ISFKEY(keysym) && keysym <= PK_F12) {
static char const codes[] =
"MNOPQRSTUVWX" "YZabcdefghij" "klmnopqrstuv" "wxyz@[\\]^_`{";
if (PK_ISEDITING(keysym) && (modifiers & PKM_SHIFT) == 0) {
int code;
- if (term->cfg.funky_type == FUNKY_XTERM) {
+ if (term->funky_type == FUNKY_XTERM) {
/* Xterm shuffles these keys, apparently. */
switch (keysym) {
case PK_HOME: keysym = PK_INSERT; break;
}
/* RXVT Home/End */
- if (term->cfg.rxvt_homeend &&
+ if (term->rxvt_homeend &&
(keysym == PK_HOME || keysym == PK_END)) {
p += sprintf((char *) p, keysym == PK_HOME ? "\x1B[H" : "\x1BOw");
goto done;
/* Map Shift+F1-F10 to F11-F20 */
if (keysym >= PK_F1 && keysym <= PK_F10 && (modifiers & PKM_SHIFT))
keysym += 10;
- if ((term->vt52_mode || term->cfg.funky_type == FUNKY_VT100P) &&
+ if ((term->vt52_mode || term->funky_type == FUNKY_VT100P) &&
keysym <= PK_F14) {
/* XXX This overrides the XTERM/VT52 mode below */
int offt = 0;
'P' + keysym - PK_F1 - offt);
goto done;
}
- if (term->cfg.funky_type == FUNKY_LINUX && keysym <= PK_F5) {
+ if (term->funky_type == FUNKY_LINUX && keysym <= PK_F5) {
p += sprintf((char *) p, "\x1B[[%c", 'A' + keysym - PK_F1);
goto done;
}
- if (term->cfg.funky_type == FUNKY_XTERM && keysym <= PK_F4) {
+ if (term->funky_type == FUNKY_XTERM && keysym <= PK_F4) {
if (term->vt52_mode)
p += sprintf((char *) p, "\x1B%c", 'P' + keysym - PK_F1);
else
{
char *val = NULL;
if (strcmp(mode, "ERASE") == 0) {
- val = term->cfg.bksp_is_delete ? "^?" : "^H";
+ val = term->bksp_is_delete ? "^?" : "^H";
}
- /* FIXME: perhaps we should set ONLCR based on cfg.lfhascr as well? */
+ /* FIXME: perhaps we should set ONLCR based on lfhascr as well? */
/* FIXME: or ECHO and friends based on local echo state? */
return dupstr(val);
}
struct unicode_data *ucsdata;
/*
- * 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
- * adjust the _current_ setting of (e.g.) auto wrap mode rather
- * than only the default.
+ * We maintain a full copy of a Conf here, not merely a pointer
+ * to it. That way, when we're passed a new one for
+ * reconfiguration, we can check the differences and adjust the
+ * _current_ setting of (e.g.) auto wrap mode rather than only
+ * the default.
*/
- Config cfg;
+ Conf *conf;
/*
* from_backend calls term_out, but it can also be called from
int wcFromTo_size;
struct bidi_cache_entry *pre_bidi_cache, *post_bidi_cache;
int bidi_cache_size;
+
+ /*
+ * We copy a bunch of stuff out of the Conf structure into local
+ * fields in the Terminal structure, to avoid the repeated
+ * tree234 lookups which would be involved in fetching them from
+ * the former every time.
+ */
+ int ansi_colour;
+ char *answerback;
+ int answerbacklen;
+ int arabicshaping;
+ int beep;
+ int bellovl;
+ int bellovl_n;
+ int bellovl_s;
+ int bellovl_t;
+ int bidi;
+ int bksp_is_delete;
+ int blink_cur;
+ int blinktext;
+ int cjk_ambig_wide;
+ int conf_height;
+ int conf_width;
+ int crhaslf;
+ int erase_to_scrollback;
+ int funky_type;
+ int lfhascr;
+ int logflush;
+ int logtype;
+ int mouse_override;
+ int nethack_keypad;
+ int no_alt_screen;
+ int no_applic_c;
+ int no_applic_k;
+ int no_dbackspace;
+ int no_mouse_rep;
+ int no_remote_charset;
+ int no_remote_resize;
+ int no_remote_wintitle;
+ int rawcnp;
+ int rect_select;
+ int remote_qtitle_action;
+ int rxvt_homeend;
+ int scroll_on_disp;
+ int scroll_on_key;
+ int xterm_256_colour;
};
#define in_utf(term) ((term)->utf || (term)->ucsdata->line_codepage==CP_UTF8)
#include "putty.h"
-static const char *null_init(void *, void **, Config *, char *, int, char **,
+static const char *null_init(void *, void **, Conf *, char *, int, char **,
int, int);
-static const char *loop_init(void *, void **, Config *, char *, int, char **,
+static const char *loop_init(void *, void **, Conf *, char *, int, char **,
int, int);
static void null_free(void *);
static void loop_free(void *);
-static void null_reconfig(void *, Config *);
+static void null_reconfig(void *, Conf *);
static int null_send(void *, char *, int);
static int loop_send(void *, char *, int);
static int null_sendbuffer(void *);
};
static const char *null_init(void *frontend_handle, void **backend_handle,
- Config *cfg, char *host, int port,
+ Conf *conf, char *host, int port,
char **realhost, int nodelay, int keepalive) {
return NULL;
}
static const char *loop_init(void *frontend_handle, void **backend_handle,
- Config *cfg, char *host, int port,
+ Conf *conf, char *host, int port,
char **realhost, int nodelay, int keepalive) {
struct loop_state *st = snew(struct loop_state);
sfree(handle);
}
-static void null_reconfig(void *handle, Config *cfg) {
+static void null_reconfig(void *handle, Conf *conf) {
}
"Control the scrollback in the window");
ctrl_checkbox(s, "Scrollbar on left", 'l',
HELPCTX(no_help),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,scrollbar_on_left)));
+ conf_checkbox_handler,
+ I(CONF_scrollbar_on_left));
/*
* Really this wants to go just after `Display scrollbar'. See
* if we can find that control, and do some shuffling.
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_CHECKBOX &&
- c->generic.context.i == offsetof(Config,scrollbar)) {
+ c->generic.context.i == CONF_scrollbar) {
/*
* Control i is the scrollbar checkbox.
* Control s->ncontrols-1 is the scrollbar-on-left one.
"Fonts for displaying non-bold text");
ctrl_fontsel(s, "Font used for ordinary text", 'f',
HELPCTX(no_help),
- dlg_stdfontsel_handler, I(offsetof(Config,font)));
+ conf_fontsel_handler, I(CONF_font));
ctrl_fontsel(s, "Font used for wide (CJK) text", 'w',
HELPCTX(no_help),
- dlg_stdfontsel_handler, I(offsetof(Config,widefont)));
+ conf_fontsel_handler, I(CONF_widefont));
s = ctrl_getset(b, "Window/Fonts", "fontbold",
"Fonts for displaying bolded text");
ctrl_fontsel(s, "Font used for bolded text", 'b',
HELPCTX(no_help),
- dlg_stdfontsel_handler, I(offsetof(Config,boldfont)));
+ conf_fontsel_handler, I(CONF_boldfont));
ctrl_fontsel(s, "Font used for bold wide text", 'i',
HELPCTX(no_help),
- dlg_stdfontsel_handler, I(offsetof(Config,wideboldfont)));
+ conf_fontsel_handler, I(CONF_wideboldfont));
ctrl_checkbox(s, "Use shadow bold instead of bold fonts", 'u',
HELPCTX(no_help),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,shadowbold)));
+ conf_checkbox_handler,
+ I(CONF_shadowbold));
ctrl_text(s, "(Note that bold fonts or shadow bolding are only"
" used if you have not requested bolding to be done by"
" changing the text colour.)",
HELPCTX(no_help));
ctrl_editbox(s, "Horizontal offset for shadow bold:", 'z', 20,
- HELPCTX(no_help), dlg_stdeditbox_handler,
- I(offsetof(Config,shadowboldoffset)), I(-1));
+ HELPCTX(no_help), conf_editbox_handler,
+ I(CONF_shadowboldoffset), I(-1));
/*
* Markus Kuhn feels, not totally unreasonably, that it's good
"Character set translation on received data");
ctrl_checkbox(s, "Override with UTF-8 if locale says so", 'l',
HELPCTX(translation_utf8_override),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,utf8_override)));
+ conf_checkbox_handler,
+ I(CONF_utf8_override));
if (!midsession) {
/*
s = ctrl_getset(b, "Window/Behaviour", "x11",
"X Window System settings");
ctrl_editbox(s, "Window class name:", 'z', 50,
- HELPCTX(no_help), dlg_stdeditbox_handler,
- I(offsetof(Config,winclass)),
- I(sizeof(((Config *)0)->winclass)));
+ HELPCTX(no_help), conf_editbox_handler,
+ I(CONF_winclass), I(1));
}
}
* The first call to "changed", if allowed to proceed normally,
* will cause an EVENT_VALCHANGE event on the edit box, causing
* a call to dlg_editbox_get() which will read the empty string
- * out of the GtkEntry - and promptly write it straight into
- * the Config structure, which is precisely where our `text'
- * pointer is probably pointing, so the second editing
- * operation will insert that instead of the string we
- * originally asked for.
+ * out of the GtkEntry - and promptly write it straight into the
+ * Conf structure, which is precisely where our `text' pointer
+ * is probably pointing, so the second editing operation will
+ * insert that instead of the string we originally asked for.
*
* Hence, we must take our own copy of the text before we do
* this.
sfree(tmpstring);
}
-void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
+char *dlg_editbox_get(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
#if GTK_CHECK_VERSION(2,4,0)
if (uc->combo) {
#if GTK_CHECK_VERSION(2,6,0)
- strncpy(buffer,
- gtk_combo_box_get_active_text(GTK_COMBO_BOX(uc->combo)),
- length);
+ return dupstr(gtk_combo_box_get_active_text(GTK_COMBO_BOX(uc->combo)));
#else
- strncpy(buffer,
- gtk_entry_get_text
- (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uc->combo)))),
- length);
+ return dupstr(gtk_entry_get_text
+ (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uc->combo)))));
#endif
- buffer[length-1] = '\0';
- return;
}
#endif
if (uc->entry) {
- strncpy(buffer, gtk_entry_get_text(GTK_ENTRY(uc->entry)),
- length);
- buffer[length-1] = '\0';
- return;
+ return dupstr(gtk_entry_get_text(GTK_ENTRY(uc->entry)));
}
assert(!"We shouldn't get here");
#endif
}
-int do_config_box(const char *title, Config *cfg, int midsession,
+int do_config_box(const char *title, Conf *conf, int midsession,
int protcfginfo)
{
GtkWidget *window, *hbox, *vbox, *cols, *label,
*tree, *treescroll, *panels, *panelvbox;
- int index, level;
+ int index, level, protocol;
struct controlbox *ctrlbox;
char *path;
#if GTK_CHECK_VERSION(2,0,0)
window = gtk_dialog_new();
ctrlbox = ctrl_new_box();
- setup_config_box(ctrlbox, midsession, cfg->protocol, protcfginfo);
- unix_setup_config_box(ctrlbox, midsession, cfg->protocol);
+ protocol = conf_get_int(conf, CONF_protocol);
+ setup_config_box(ctrlbox, midsession, protocol, protcfginfo);
+ unix_setup_config_box(ctrlbox, midsession, protocol);
gtk_setup_config_box(ctrlbox, midsession, window);
gtk_window_set_title(GTK_WINDOW(window), title);
}
#endif
- dp.data = cfg;
+ dp.data = conf;
dlg_refresh(NULL, &dp);
dp.shortcuts = &selparams[0].shortcuts;
#endif
/* Colours come in two flavours: configurable, and xterm-extended. */
-#define NCFGCOLOURS (lenof(((Config *)0)->colours))
#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
guint term_exit_idle_id;
int alt_keycode;
int alt_digits;
- char wintitle[sizeof(((Config *)0)->wintitle)];
- char icontitle[sizeof(((Config *)0)->wintitle)];
+ char *wintitle;
+ char *icontitle;
int master_fd, master_func_id;
void *ldisc;
Backend *back;
void *logctx;
int exited;
struct unicode_data ucsdata;
- Config cfg;
+ Conf *conf;
void *eventlogstuff;
char *progname, **gtkargvstart;
int ngtkargs;
guint32 input_event_time; /* Timestamp of the most recent input event. */
int reconfiguring;
+ /* Cached things out of conf that we refer to a lot */
+ int bold_colour;
+ int window_border;
+ int cursor_type;
};
+static void cache_conf_values(struct gui_data *inst)
+{
+ inst->bold_colour = conf_get_int(inst->conf, CONF_bold_colour);
+ inst->window_border = conf_get_int(inst->conf, CONF_window_border);
+ inst->cursor_type = conf_get_int(inst->conf, CONF_cursor_type);
+}
+
struct draw_ctx {
GdkGC *gc;
struct gui_data *inst;
inst->exited = TRUE;
fatal_message_box(inst->window, msg);
sfree(msg);
- if (inst->cfg.close_on_exit == FORCE_ON)
+ if (conf_get_int(inst->conf, CONF_close_on_exit) == FORCE_ON)
cleanup_exit(1);
}
gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
- if (!inst->exited && inst->cfg.warn_on_close) {
+ if (!inst->exited && conf_get_int(inst->conf, CONF_warn_on_close)) {
if (!reallyclose(inst))
return TRUE;
}
static void show_mouseptr(struct gui_data *inst, int show)
{
- if (!inst->cfg.hide_mouseptr)
+ if (!conf_get_int(inst->conf, CONF_hide_mouseptr))
show = 1;
inst->mouseptr_visible = show;
update_mouseptr(inst);
GdkGC *gc = gdk_gc_new(inst->area->window);
gdk_gc_set_foreground(gc, &inst->cols[258]); /* default background */
gdk_draw_rectangle(inst->pixmap, gc, 1, 0, 0,
- inst->cfg.width * inst->font_width + 2*inst->cfg.window_border,
- inst->cfg.height * inst->font_height + 2*inst->cfg.window_border);
+ inst->width * inst->font_width + 2*inst->window_border,
+ inst->height * inst->font_height + 2*inst->window_border);
gdk_gc_unref(gc);
}
* See if the terminal size has changed, in which case we must
* let the terminal know.
*/
- w = (event->width - 2*inst->cfg.window_border) / inst->font_width;
- h = (event->height - 2*inst->cfg.window_border) / inst->font_height;
+ w = (event->width - 2*inst->window_border) / inst->font_width;
+ h = (event->height - 2*inst->window_border) / inst->font_height;
if (w != inst->width || h != inst->height) {
- inst->cfg.width = inst->width = w;
- inst->cfg.height = inst->height = h;
+ inst->width = w;
+ inst->height = h;
+ conf_set_int(inst->conf, CONF_width, inst->width);
+ conf_set_int(inst->conf, CONF_height, inst->height);
need_size = 1;
}
}
inst->pixmap = gdk_pixmap_new(widget->window,
- (inst->cfg.width * inst->font_width +
- 2*inst->cfg.window_border),
- (inst->cfg.height * inst->font_height +
- 2*inst->cfg.window_border), -1);
+ (w * inst->font_width + 2*inst->window_border),
+ (h * inst->font_height + 2*inst->window_border), -1);
draw_backing_rect(inst);
if (need_size && inst->term) {
- term_size(inst->term, h, w, inst->cfg.savelines);
+ term_size(inst->term, h, w, conf_get_int(inst->conf, CONF_savelines));
}
if (inst->term)
* at all.
*/
if (event->keyval == GDK_Page_Up && (event->state & GDK_SHIFT_MASK)) {
- term_scroll(inst->term, 0, -inst->cfg.height/2);
+ term_scroll(inst->term, 0, -inst->height/2);
return TRUE;
}
if (event->keyval == GDK_Page_Up && (event->state & GDK_CONTROL_MASK)) {
return TRUE;
}
if (event->keyval == GDK_Page_Down && (event->state & GDK_SHIFT_MASK)) {
- term_scroll(inst->term, 0, +inst->cfg.height/2);
+ term_scroll(inst->term, 0, +inst->height/2);
return TRUE;
}
if (event->keyval == GDK_Page_Down && (event->state & GDK_CONTROL_MASK)) {
/* We don't let GTK tell us what Backspace is! We know better. */
if (event->keyval == GDK_BackSpace &&
!(event->state & GDK_SHIFT_MASK)) {
- output[1] = inst->cfg.bksp_is_delete ? '\x7F' : '\x08';
+ output[1] = conf_get_int(inst->conf, CONF_bksp_is_delete) ?
+ '\x7F' : '\x08';
use_ucsoutput = FALSE;
end = 2;
special = TRUE;
/* For Shift Backspace, do opposite of what is configured. */
if (event->keyval == GDK_BackSpace &&
(event->state & GDK_SHIFT_MASK)) {
- output[1] = inst->cfg.bksp_is_delete ? '\x08' : '\x7F';
+ output[1] = conf_get_int(inst->conf, CONF_bksp_is_delete) ?
+ '\x08' : '\x7F';
use_ucsoutput = FALSE;
end = 2;
special = TRUE;
/*
* NetHack keypad mode.
*/
- if (inst->cfg.nethack_keypad) {
+ if (conf_get_int(inst->conf, CONF_nethack_keypad)) {
char *keys = NULL;
switch (event->keyval) {
case GDK_KP_1: case GDK_KP_End: keys = "bB\002"; break;
/*
* Application keypad mode.
*/
- if (inst->term->app_keypad_keys && !inst->cfg.no_applic_k) {
+ if (inst->term->app_keypad_keys &&
+ !conf_get_int(inst->conf, CONF_no_applic_k)) {
int xkey = 0;
switch (event->keyval) {
case GDK_Num_Lock: xkey = 'P'; break;
* in xterm function key mode we change which two...
*/
case GDK_KP_Add:
- if (inst->cfg.funky_type == FUNKY_XTERM) {
+ if (conf_get_int(inst->conf, CONF_funky_type) == FUNKY_XTERM) {
if (event->state & GDK_SHIFT_MASK)
xkey = 'l';
else
*/
{
int code = 0;
+ int funky_type = conf_get_int(inst->conf, CONF_funky_type);
switch (event->keyval) {
case GDK_F1:
code = (event->state & GDK_SHIFT_MASK ? 23 : 11);
break;
}
/* Reorder edit keys to physical order */
- if (inst->cfg.funky_type == FUNKY_VT400 && code <= 6)
+ if (funky_type == FUNKY_VT400 && code <= 6)
code = "\0\2\1\4\5\3\6"[code];
if (inst->term->vt52_mode && code > 0 && code <= 6) {
goto done;
}
- if (inst->cfg.funky_type == FUNKY_SCO && /* SCO function keys */
+ if (funky_type == FUNKY_SCO && /* SCO function keys */
code >= 11 && code <= 34) {
char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
int index = 0;
use_ucsoutput = FALSE;
goto done;
}
- if (inst->cfg.funky_type == FUNKY_SCO && /* SCO small keypad */
+ if (funky_type == FUNKY_SCO && /* SCO small keypad */
code >= 1 && code <= 6) {
char codes[] = "HL.FIG";
if (code == 3) {
use_ucsoutput = FALSE;
goto done;
}
- if ((inst->term->vt52_mode || inst->cfg.funky_type == FUNKY_VT100P) &&
+ if ((inst->term->vt52_mode || funky_type == FUNKY_VT100P) &&
code >= 11 && code <= 24) {
int offt = 0;
if (code > 15)
use_ucsoutput = FALSE;
goto done;
}
- if (inst->cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
+ if (funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11);
use_ucsoutput = FALSE;
goto done;
}
- if (inst->cfg.funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
+ if (funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
if (inst->term->vt52_mode)
end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11);
else
use_ucsoutput = FALSE;
goto done;
}
- if (inst->cfg.rxvt_homeend && (code == 1 || code == 4)) {
+ if ((code == 1 || code == 4) &&
+ conf_get_int(inst->conf, CONF_rxvt_homeend)) {
end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw");
use_ucsoutput = FALSE;
goto done;
default: return FALSE; /* don't know this event type */
}
- if (send_raw_mouse && !(inst->cfg.mouse_override && shift) &&
+ if (send_raw_mouse && !(shift && conf_get_int(inst->conf,
+ CONF_mouse_override)) &&
act != MA_CLICK && act != MA_RELEASE)
return TRUE; /* we ignore these in raw mouse mode */
- x = (ex - inst->cfg.window_border) / inst->font_width;
- y = (ey - inst->cfg.window_border) / inst->font_height;
+ x = (ex - inst->window_border) / inst->font_width;
+ y = (ey - inst->window_border) / inst->font_height;
term_mouse(inst->term, button, translate_button(button), act,
x, y, shift, ctrl, alt);
else
return FALSE; /* don't even know what button! */
- x = (event->x - inst->cfg.window_border) / inst->font_width;
- y = (event->y - inst->cfg.window_border) / inst->font_height;
+ x = (event->x - inst->window_border) / inst->font_width;
+ y = (event->y - inst->window_border) / inst->font_height;
term_mouse(inst->term, button, translate_button(button), MA_DRAG,
x, y, shift, ctrl, alt);
static gint idle_exit_func(gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
- int exitcode;
+ int exitcode, close_on_exit;
if (!inst->exited &&
(exitcode = inst->back->exitcode(inst->backhandle)) >= 0) {
inst->exited = TRUE;
- if (inst->cfg.close_on_exit == FORCE_ON ||
- (inst->cfg.close_on_exit == AUTO && exitcode == 0))
+ close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit);
+ if (close_on_exit == FORCE_ON ||
+ (close_on_exit == AUTO && exitcode == 0))
gtk_main_quit(); /* just go */
if (inst->ldisc) {
ldisc_free(inst->ldisc);
void set_raw_mouse_mode(void *frontend, int activate)
{
struct gui_data *inst = (struct gui_data *)frontend;
- activate = activate && !inst->cfg.no_mouse_rep;
+ activate = activate && !conf_get_int(inst->conf, CONF_no_mouse_rep);
send_raw_mouse = activate;
update_mouseptr(inst);
}
offset_x = outer.width - inner.width;
offset_y = outer.height - inner.height;
- area_x = inst->font_width * w + 2*inst->cfg.window_border;
- area_y = inst->font_height * h + 2*inst->cfg.window_border;
+ area_x = inst->font_width * w + 2*inst->window_border;
+ area_y = inst->font_height * h + 2*inst->window_border;
/*
* Now we must set the size request on the drawing area back to
void palette_reset(void *frontend)
{
struct gui_data *inst = (struct gui_data *)frontend;
- /* This maps colour indices in inst->cfg to those used in inst->cols. */
+ /* This maps colour indices in inst->conf to those used in inst->cols. */
static const int ww[] = {
256, 257, 258, 259, 260, 261,
0, 8, 1, 9, 2, 10, 3, 11,
}
for (i = 0; i < NCFGCOLOURS; i++) {
- inst->cols[ww[i]].red = inst->cfg.colours[i][0] * 0x0101;
- inst->cols[ww[i]].green = inst->cfg.colours[i][1] * 0x0101;
- inst->cols[ww[i]].blue = inst->cfg.colours[i][2] * 0x0101;
+ inst->cols[ww[i]].red =
+ conf_get_int_int(inst->conf, CONF_colours, i*3+0) * 0x0101;
+ inst->cols[ww[i]].green =
+ conf_get_int_int(inst->conf, CONF_colours, i*3+1) * 0x0101;
+ inst->cols[ww[i]].blue =
+ conf_get_int_int(inst->conf, CONF_colours, i*3+2) * 0x0101;
}
for (i = 0; i < NEXTCOLOURS; i++) {
for (i = 0; i < NALLCOLOURS; i++) {
if (!success[i])
g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
- appname, i, inst->cfg.colours[i][0],
- inst->cfg.colours[i][1], inst->cfg.colours[i][2]);
+ appname, i,
+ conf_get_int_int(inst->conf, CONF_colours, i*3+0),
+ conf_get_int_int(inst->conf, CONF_colours, i*3+1),
+ conf_get_int_int(inst->conf, CONF_colours, i*3+2));
}
/* Since Default Background may have changed, ensure that space
* is life.
*/
gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
- if (!inst->cfg.win_name_always)
+ if (!conf_get_int(inst->conf, CONF_win_name_always))
gdk_window_set_icon_name(inst->window->window, inst->icontitle);
}
void set_title(void *frontend, char *title)
{
struct gui_data *inst = (struct gui_data *)frontend;
- strncpy(inst->wintitle, title, lenof(inst->wintitle));
- inst->wintitle[lenof(inst->wintitle)-1] = '\0';
+ sfree(inst->wintitle);
+ inst->wintitle = dupstr(title);
set_window_titles(inst);
}
void set_icon(void *frontend, char *title)
{
struct gui_data *inst = (struct gui_data *)frontend;
- strncpy(inst->icontitle, title, lenof(inst->icontitle));
- inst->icontitle[lenof(inst->icontitle)-1] = '\0';
+ sfree(inst->icontitle);
+ inst->icontitle = dupstr(title);
+ set_window_titles(inst);
+}
+
+void set_title_and_icon(void *frontend, char *title, char *icon)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ sfree(inst->wintitle);
+ inst->wintitle = dupstr(title);
+ sfree(inst->icontitle);
+ inst->icontitle = dupstr(icon);
set_window_titles(inst);
}
void set_sbar(void *frontend, int total, int start, int page)
{
struct gui_data *inst = (struct gui_data *)frontend;
- if (!inst->cfg.scrollbar)
+ if (!conf_get_int(inst->conf, CONF_scrollbar))
return;
inst->sbar_adjust->lower = 0;
inst->sbar_adjust->upper = total;
{
struct gui_data *inst = (struct gui_data *)data;
- if (!inst->cfg.scrollbar)
+ if (!conf_get_int(inst->conf, CONF_scrollbar))
return;
if (!inst->ignore_sbar)
term_scroll(inst->term, 1, (int)adj->value);
nfg = nbg;
nbg = t;
}
- if (inst->cfg.bold_colour && (attr & ATTR_BOLD)) {
+ if (inst->bold_colour && (attr & ATTR_BOLD)) {
if (nfg < 16) nfg |= 8;
else if (nfg >= 256) nfg |= 1;
}
- if (inst->cfg.bold_colour && (attr & ATTR_BLINK)) {
+ if (inst->bold_colour && (attr & ATTR_BLINK)) {
if (nbg < 16) nbg |= 8;
else if (nbg >= 256) nbg |= 1;
}
widefactor = 1;
}
- if ((attr & ATTR_BOLD) && !inst->cfg.bold_colour) {
+ if ((attr & ATTR_BOLD) && !inst->bold_colour) {
bold = 1;
fontid |= 1;
} else {
{
GdkRectangle r;
- r.x = x*inst->font_width+inst->cfg.window_border;
- r.y = y*inst->font_height+inst->cfg.window_border;
+ r.x = x*inst->font_width+inst->window_border;
+ r.y = y*inst->font_height+inst->window_border;
r.width = rlen*widefactor*inst->font_width;
r.height = inst->font_height;
gdk_gc_set_clip_rectangle(gc, &r);
gdk_gc_set_foreground(gc, &inst->cols[nbg]);
gdk_draw_rectangle(inst->pixmap, gc, 1,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, inst->font_height);
gdk_gc_set_foreground(gc, &inst->cols[nfg]);
text + combining, len, gcs, len*10+1, ".",
NULL, NULL);
unifont_draw_text(inst->pixmap, gc, inst->fonts[fontid],
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border+inst->fonts[0]->ascent,
gcs, mblen, widefactor > 1, bold, inst->font_width);
}
int uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
uheight = inst->font_height - 1;
- gdk_draw_line(inst->pixmap, gc, x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height + uheight + inst->cfg.window_border,
- (x+len)*widefactor*inst->font_width-1+inst->cfg.window_border,
- y*inst->font_height + uheight + inst->cfg.window_border);
+ gdk_draw_line(inst->pixmap, gc, x*inst->font_width+inst->window_border,
+ y*inst->font_height + uheight + inst->window_border,
+ (x+len)*widefactor*inst->font_width-1+inst->window_border,
+ y*inst->font_height + uheight + inst->window_border);
}
if ((lattr & LATTR_MODE) != LATTR_NORM) {
int i;
for (i = 0; i < len * widefactor * inst->font_width; i++) {
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
- x*inst->font_width+inst->cfg.window_border + 2*i,
- y*inst->font_height+inst->cfg.window_border,
- x*inst->font_width+inst->cfg.window_border + 2*i+1,
- y*inst->font_height+inst->cfg.window_border,
+ x*inst->font_width+inst->window_border + 2*i,
+ y*inst->font_height+inst->window_border,
+ x*inst->font_width+inst->window_border + 2*i+1,
+ y*inst->font_height+inst->window_border,
len * widefactor * inst->font_width - i, inst->font_height);
}
len *= 2;
dt = 1, db = 0;
for (i = 0; i < inst->font_height; i+=2) {
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border+dt*i+db,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border+dt*(i+1),
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border+dt*i+db,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border+dt*(i+1),
len * widefactor * inst->font_width, inst->font_height-i-1);
}
}
}
gdk_draw_pixmap(inst->area->window, gc, inst->pixmap,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width, inst->font_height);
}
passive = 1;
} else
passive = 0;
- if ((attr & TATTR_ACTCURS) && inst->cfg.cursor_type != 0) {
+ if ((attr & TATTR_ACTCURS) && inst->cursor_type != 0) {
attr &= ~TATTR_ACTCURS;
active = 1;
} else
len *= 2;
}
- if (inst->cfg.cursor_type == 0) {
+ if (inst->cursor_type == 0) {
/*
* An active block cursor will already have been done by
* the above do_text call, so we only need to do anything
if (passive) {
gdk_gc_set_foreground(gc, &inst->cols[261]);
gdk_draw_rectangle(inst->pixmap, gc, 0,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width-1, inst->font_height-1);
}
} else {
else
char_width = inst->font_width;
- if (inst->cfg.cursor_type == 1) {
+ if (inst->cursor_type == 1) {
uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
uheight = inst->font_height - 1;
- startx = x * inst->font_width + inst->cfg.window_border;
- starty = y * inst->font_height + inst->cfg.window_border + uheight;
+ startx = x * inst->font_width + inst->window_border;
+ starty = y * inst->font_height + inst->window_border + uheight;
dx = 1;
dy = 0;
length = len * widefactor * char_width;
int xadjust = 0;
if (attr & TATTR_RIGHTCURS)
xadjust = char_width - 1;
- startx = x * inst->font_width + inst->cfg.window_border + xadjust;
- starty = y * inst->font_height + inst->cfg.window_border;
+ startx = x * inst->font_width + inst->window_border + xadjust;
+ starty = y * inst->font_height + inst->window_border;
dx = 0;
dy = 1;
length = inst->font_height;
}
gdk_draw_pixmap(inst->area->window, gc, inst->pixmap,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
- x*inst->font_width+inst->cfg.window_border,
- y*inst->font_height+inst->cfg.window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width, inst->font_height);
}
}
int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch,
- struct gui_data *inst, Config *cfg)
+ struct gui_data *inst, Conf *conf)
{
int err = 0;
char *val;
p = "-title";
ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
- do_everything ? 1 : -1, cfg);
+ do_everything ? 1 : -1, conf);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", p);
}
if (!strcmp(p, "-fn") || !strcmp(p, "-font")) {
+ FontSpec fs;
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->font.name, val, sizeof(cfg->font.name));
- cfg->font.name[sizeof(cfg->font.name)-1] = '\0';
+ strncpy(fs.name, val, sizeof(fs.name));
+ fs.name[sizeof(fs.name)-1] = '\0';
+ conf_set_fontspec(conf, CONF_font, &fs);
} else if (!strcmp(p, "-fb")) {
+ FontSpec fs;
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->boldfont.name, val, sizeof(cfg->boldfont.name));
- cfg->boldfont.name[sizeof(cfg->boldfont.name)-1] = '\0';
+ strncpy(fs.name, val, sizeof(fs.name));
+ fs.name[sizeof(fs.name)-1] = '\0';
+ conf_set_fontspec(conf, CONF_boldfont, &fs);
} else if (!strcmp(p, "-fw")) {
+ FontSpec fs;
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->widefont.name, val, sizeof(cfg->widefont.name));
- cfg->widefont.name[sizeof(cfg->widefont.name)-1] = '\0';
+ strncpy(fs.name, val, sizeof(fs.name));
+ fs.name[sizeof(fs.name)-1] = '\0';
+ conf_set_fontspec(conf, CONF_widefont, &fs);
} else if (!strcmp(p, "-fwb")) {
+ FontSpec fs;
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->wideboldfont.name, val, sizeof(cfg->wideboldfont.name));
- cfg->wideboldfont.name[sizeof(cfg->wideboldfont.name)-1] = '\0';
+ strncpy(fs.name, val, sizeof(fs.name));
+ fs.name[sizeof(fs.name)-1] = '\0';
+ conf_set_fontspec(conf, CONF_wideboldfont, &fs);
} else if (!strcmp(p, "-cs")) {
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->line_codepage, val, sizeof(cfg->line_codepage));
- cfg->line_codepage[sizeof(cfg->line_codepage)-1] = '\0';
+ conf_set_str(conf, CONF_line_codepage, val);
} else if (!strcmp(p, "-geometry")) {
int flags, x, y;
flags = XParseGeometry(val, &x, &y, &w, &h);
if (flags & WidthValue)
- cfg->width = (int)w;
+ conf_set_int(conf, CONF_width, w);
if (flags & HeightValue)
- cfg->height = (int)h;
+ conf_set_int(conf, CONF_height, h);
if (flags & (XValue | YValue)) {
inst->xpos = x;
} else if (!strcmp(p, "-sl")) {
EXPECTS_ARG;
SECOND_PASS_ONLY;
- cfg->savelines = atoi(val);
+ conf_set_int(conf, CONF_savelines, atoi(val));
} else if (!strcmp(p, "-fg") || !strcmp(p, "-bg") ||
!strcmp(p, "-bfg") || !strcmp(p, "-bbg") ||
!strcmp(p, "-cfg") ? 4 :
!strcmp(p, "-cbg") ? 5 : -1);
assert(index != -1);
- cfg->colours[index][0] = col.red / 256;
- cfg->colours[index][1] = col.green / 256;
- cfg->colours[index][2] = col.blue / 256;
+ conf_set_int_int(conf, CONF_colours, index*3+0, col.red / 256);
+ conf_set_int_int(conf, CONF_colours, index*3+1,col.green/ 256);
+ conf_set_int_int(conf, CONF_colours, index*3+2, col.blue/ 256);
}
} else if (use_pty_argv && !strcmp(p, "-e")) {
} else if (!strcmp(p, "-title")) {
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->wintitle, val, sizeof(cfg->wintitle));
- cfg->wintitle[sizeof(cfg->wintitle)-1] = '\0';
+ conf_set_str(conf, CONF_wintitle, val);
} else if (!strcmp(p, "-log")) {
+ Filename fn;
EXPECTS_ARG;
SECOND_PASS_ONLY;
- strncpy(cfg->logfilename.path, val, sizeof(cfg->logfilename.path));
- cfg->logfilename.path[sizeof(cfg->logfilename.path)-1] = '\0';
- cfg->logtype = LGTYP_DEBUG;
+ strncpy(fn.path, val, sizeof(fn.path));
+ fn.path[sizeof(fn.path)-1] = '\0';
+ conf_set_filename(conf, CONF_logfilename, &fn);
+ conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
} else if (!strcmp(p, "-ut-") || !strcmp(p, "+ut")) {
SECOND_PASS_ONLY;
- cfg->stamp_utmp = 0;
+ conf_set_int(conf, CONF_stamp_utmp, 0);
} else if (!strcmp(p, "-ut")) {
SECOND_PASS_ONLY;
- cfg->stamp_utmp = 1;
+ conf_set_int(conf, CONF_stamp_utmp, 1);
} else if (!strcmp(p, "-ls-") || !strcmp(p, "+ls")) {
SECOND_PASS_ONLY;
- cfg->login_shell = 0;
+ conf_set_int(conf, CONF_login_shell, 0);
} else if (!strcmp(p, "-ls")) {
SECOND_PASS_ONLY;
- cfg->login_shell = 1;
+ conf_set_int(conf, CONF_login_shell, 1);
} else if (!strcmp(p, "-nethack")) {
SECOND_PASS_ONLY;
- cfg->nethack_keypad = 1;
+ conf_set_int(conf, CONF_nethack_keypad, 1);
} else if (!strcmp(p, "-sb-") || !strcmp(p, "+sb")) {
SECOND_PASS_ONLY;
- cfg->scrollbar = 0;
+ conf_set_int(conf, CONF_scrollbar, 0);
} else if (!strcmp(p, "-sb")) {
SECOND_PASS_ONLY;
- cfg->scrollbar = 0;
+ conf_set_int(conf, CONF_scrollbar, 1);
} else if (!strcmp(p, "-name")) {
EXPECTS_ARG;
exit(1);
} else if(p[0] != '-' && (!do_everything ||
- process_nonoption_arg(p, cfg,
+ process_nonoption_arg(p, conf,
allow_launch))) {
/* do nothing */
void setup_fonts_ucs(struct gui_data *inst)
{
+ int shadowbold = conf_get_int(inst->conf, CONF_shadowbold);
+ int shadowboldoffset = conf_get_int(inst->conf, CONF_shadowboldoffset);
+ FontSpec *fs;
+
if (inst->fonts[0])
unifont_destroy(inst->fonts[0]);
if (inst->fonts[1])
if (inst->fonts[3])
unifont_destroy(inst->fonts[3]);
- inst->fonts[0] = unifont_create(inst->area, inst->cfg.font.name,
- FALSE, FALSE,
- inst->cfg.shadowboldoffset,
- inst->cfg.shadowbold);
+ fs = conf_get_fontspec(inst->conf, CONF_font);
+ inst->fonts[0] = unifont_create(inst->area, fs->name, FALSE, FALSE,
+ shadowboldoffset, shadowbold);
if (!inst->fonts[0]) {
fprintf(stderr, "%s: unable to load font \"%s\"\n", appname,
- inst->cfg.font.name);
+ fs->name);
exit(1);
}
- if (inst->cfg.shadowbold || !inst->cfg.boldfont.name[0]) {
+ fs = conf_get_fontspec(inst->conf, CONF_boldfont);
+ if (shadowbold || !fs->name[0]) {
inst->fonts[1] = NULL;
} else {
- inst->fonts[1] = unifont_create(inst->area, inst->cfg.boldfont.name,
- FALSE, TRUE,
- inst->cfg.shadowboldoffset,
- inst->cfg.shadowbold);
+ inst->fonts[1] = unifont_create(inst->area, fs->name, FALSE, TRUE,
+ shadowboldoffset, shadowbold);
if (!inst->fonts[1]) {
fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname,
- inst->cfg.boldfont.name);
+ fs->name);
exit(1);
}
}
- if (inst->cfg.widefont.name[0]) {
- inst->fonts[2] = unifont_create(inst->area, inst->cfg.widefont.name,
- TRUE, FALSE,
- inst->cfg.shadowboldoffset,
- inst->cfg.shadowbold);
+ fs = conf_get_fontspec(inst->conf, CONF_widefont);
+ if (fs->name[0]) {
+ inst->fonts[2] = unifont_create(inst->area, fs->name, TRUE, FALSE,
+ shadowboldoffset, shadowbold);
if (!inst->fonts[2]) {
fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname,
- inst->cfg.widefont.name);
+ fs->name);
exit(1);
}
} else {
inst->fonts[2] = NULL;
}
- if (inst->cfg.shadowbold || !inst->cfg.wideboldfont.name[0]) {
+ fs = conf_get_fontspec(inst->conf, CONF_wideboldfont);
+ if (shadowbold || !fs->name[0]) {
inst->fonts[3] = NULL;
} else {
- inst->fonts[3] = unifont_create(inst->area,
- inst->cfg.wideboldfont.name, TRUE,
- TRUE, inst->cfg.shadowboldoffset,
- inst->cfg.shadowbold);
+ inst->fonts[3] = unifont_create(inst->area, fs->name, TRUE, TRUE,
+ shadowboldoffset, shadowbold);
if (!inst->fonts[3]) {
fprintf(stderr, "%s: unable to load wide bold font \"%s\"\n", appname,
- inst->cfg.boldfont.name);
+ fs->name);
exit(1);
}
}
inst->font_width = inst->fonts[0]->width;
inst->font_height = inst->fonts[0]->height;
- inst->direct_to_font = init_ucs(&inst->ucsdata, inst->cfg.line_codepage,
- inst->cfg.utf8_override,
+ inst->direct_to_font = init_ucs(&inst->ucsdata,
+ conf_get_str(inst->conf, CONF_line_codepage),
+ conf_get_int(inst->conf, CONF_utf8_override),
inst->fonts[0]->public_charset,
- inst->cfg.vtmode);
+ conf_get_int(inst->conf, CONF_vtmode));
}
void set_geom_hints(struct gui_data *inst)
{
GdkGeometry geom;
- geom.min_width = inst->font_width + 2*inst->cfg.window_border;
- geom.min_height = inst->font_height + 2*inst->cfg.window_border;
+ geom.min_width = inst->font_width + 2*inst->window_border;
+ geom.min_height = inst->font_height + 2*inst->window_border;
geom.max_width = geom.max_height = -1;
- geom.base_width = 2*inst->cfg.window_border;
- geom.base_height = 2*inst->cfg.window_border;
+ geom.base_width = 2*inst->window_border;
+ geom.base_height = 2*inst->window_border;
geom.width_inc = inst->font_width;
geom.height_inc = inst->font_height;
geom.min_aspect = geom.max_aspect = 0;
void change_settings_menuitem(GtkMenuItem *item, gpointer data)
{
- /* This maps colour indices in inst->cfg to those used in inst->cols. */
+ /* This maps colour indices in inst->conf to those used in inst->cols. */
static const int ww[] = {
256, 257, 258, 259, 260, 261,
0, 8, 1, 9, 2, 10, 3, 11,
};
struct gui_data *inst = (struct gui_data *)data;
char *title = dupcat(appname, " Reconfiguration", NULL);
- Config cfg2, oldcfg;
- int i, need_size;
+ Conf *oldconf, *newconf;
+ int i, j, need_size;
assert(lenof(ww) == NCFGCOLOURS);
else
inst->reconfiguring = TRUE;
- cfg2 = inst->cfg; /* structure copy */
+ oldconf = inst->conf;
+ newconf = conf_copy(inst->conf);
- if (do_config_box(title, &cfg2, 1,
+ if (do_config_box(title, newconf, 1,
inst->back?inst->back->cfg_info(inst->backhandle):0)) {
-
- oldcfg = inst->cfg; /* structure copy */
- inst->cfg = cfg2; /* structure copy */
+ inst->conf = newconf;
/* Pass new config data to the logging module */
- log_reconfig(inst->logctx, &cfg2);
+ log_reconfig(inst->logctx, inst->conf);
/*
* Flush the line discipline's edit buffer in the case
* where local editing has just been disabled.
*/
+ ldisc_configure(inst->ldisc, inst->conf);
if (inst->ldisc)
ldisc_send(inst->ldisc, NULL, 0, 0);
/* Pass new config data to the terminal */
- term_reconfig(inst->term, &cfg2);
+ term_reconfig(inst->term, inst->conf);
/* Pass new config data to the back end */
if (inst->back)
- inst->back->reconfig(inst->backhandle, &cfg2);
+ inst->back->reconfig(inst->backhandle, inst->conf);
+
+ cache_conf_values(inst);
/*
- * Just setting inst->cfg is sufficient to cause colour
+ * Just setting inst->conf is sufficient to cause colour
* setting changes to appear on the next ESC]R palette
* reset. But we should also check whether any colour
- * settings have been changed, and revert the ones that
- * have to the new default, on the assumption that the user
- * is most likely to want an immediate update.
+ * settings have been changed, and revert the ones that have
+ * to the new default, on the assumption that the user is
+ * most likely to want an immediate update.
*/
for (i = 0; i < NCFGCOLOURS; i++) {
- if (oldcfg.colours[i][0] != cfg2.colours[i][0] ||
- oldcfg.colours[i][1] != cfg2.colours[i][1] ||
- oldcfg.colours[i][2] != cfg2.colours[i][2]) {
- real_palette_set(inst, ww[i], cfg2.colours[i][0],
- cfg2.colours[i][1],
- cfg2.colours[i][2]);
+ for (j = 0; j < 3; j++)
+ if (conf_get_int_int(oldconf, CONF_colours, i*3+j) !=
+ conf_get_int_int(newconf, CONF_colours, i*3+j))
+ break;
+ if (j < 3) {
+ real_palette_set(inst, ww[i],
+ conf_get_int_int(newconf,CONF_colours,i*3+0),
+ conf_get_int_int(newconf,CONF_colours,i*3+1),
+ conf_get_int_int(newconf,CONF_colours,i*3+2));
/*
* If the default background has changed, we must
* If the scrollbar needs to be shown, hidden, or moved
* from one end to the other of the window, do so now.
*/
- if (oldcfg.scrollbar != cfg2.scrollbar) {
- if (cfg2.scrollbar)
+ if (conf_get_int(oldconf, CONF_scrollbar) !=
+ conf_get_int(newconf, CONF_scrollbar)) {
+ if (conf_get_int(newconf, CONF_scrollbar))
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
}
- if (oldcfg.scrollbar_on_left != cfg2.scrollbar_on_left) {
+ if (conf_get_int(oldconf, CONF_scrollbar_on_left) !=
+ conf_get_int(newconf, CONF_scrollbar_on_left)) {
gtk_box_reorder_child(inst->hbox, inst->sbar,
- cfg2.scrollbar_on_left ? 0 : 1);
+ conf_get_int(newconf, CONF_scrollbar_on_left)
+ ? 0 : 1);
}
/*
* Change the window title, if required.
*/
- if (strcmp(oldcfg.wintitle, cfg2.wintitle))
- set_title(inst, cfg2.wintitle);
+ if (strcmp(conf_get_str(oldconf, CONF_wintitle),
+ conf_get_str(newconf, CONF_wintitle)))
+ set_title(inst, conf_get_str(oldconf, CONF_wintitle));
set_window_titles(inst);
/*
* Redo the whole tangled fonts and Unicode mess if
* necessary.
*/
- if (strcmp(oldcfg.font.name, cfg2.font.name) ||
- strcmp(oldcfg.boldfont.name, cfg2.boldfont.name) ||
- strcmp(oldcfg.widefont.name, cfg2.widefont.name) ||
- strcmp(oldcfg.wideboldfont.name, cfg2.wideboldfont.name) ||
- strcmp(oldcfg.line_codepage, cfg2.line_codepage) ||
- oldcfg.vtmode != cfg2.vtmode ||
- oldcfg.shadowbold != cfg2.shadowbold) {
+ if (strcmp(conf_get_fontspec(oldconf, CONF_font)->name,
+ conf_get_fontspec(newconf, CONF_font)->name) ||
+ strcmp(conf_get_fontspec(oldconf, CONF_boldfont)->name,
+ conf_get_fontspec(newconf, CONF_boldfont)->name) ||
+ strcmp(conf_get_fontspec(oldconf, CONF_widefont)->name,
+ conf_get_fontspec(newconf, CONF_widefont)->name) ||
+ strcmp(conf_get_fontspec(oldconf, CONF_wideboldfont)->name,
+ conf_get_fontspec(newconf, CONF_wideboldfont)->name) ||
+ strcmp(conf_get_str(oldconf, CONF_line_codepage),
+ conf_get_str(newconf, CONF_line_codepage)) ||
+ conf_get_int(oldconf, CONF_vtmode) !=
+ conf_get_int(newconf, CONF_vtmode) ||
+ conf_get_int(oldconf, CONF_shadowbold) !=
+ conf_get_int(newconf, CONF_shadowbold) ||
+ conf_get_int(oldconf, CONF_shadowboldoffset) !=
+ conf_get_int(newconf, CONF_shadowboldoffset)) {
setup_fonts_ucs(inst);
need_size = 1;
} else
/*
* Resize the window.
*/
- if (oldcfg.width != cfg2.width || oldcfg.height != cfg2.height ||
- oldcfg.window_border != cfg2.window_border || need_size) {
+ if (conf_get_int(oldconf, CONF_width) !=
+ conf_get_int(newconf, CONF_width) ||
+ conf_get_int(oldconf, CONF_height) !=
+ conf_get_int(newconf, CONF_height) ||
+ conf_get_int(oldconf, CONF_window_border) !=
+ conf_get_int(newconf, CONF_window_border) ||
+ need_size) {
set_geom_hints(inst);
- request_resize(inst, cfg2.width, cfg2.height);
+ request_resize(inst, conf_get_int(newconf, CONF_width),
+ conf_get_int(newconf, CONF_height));
} else {
/*
* The above will have caused a call to term_size() for
* happened and we will need an explicit term_size()
* here.
*/
- if (oldcfg.savelines != cfg2.savelines)
+ if (conf_get_int(oldconf, CONF_savelines) !=
+ conf_get_int(newconf, CONF_savelines))
term_size(inst->term, inst->term->rows, inst->term->cols,
- cfg2.savelines);
+ conf_get_int(newconf, CONF_savelines));
}
term_invalidate(inst->term);
* border has been redrawn as well as the text area.
*/
gtk_widget_queue_draw(inst->area);
+
+ conf_free(oldconf);
+ } else {
+ conf_free(newconf);
}
sfree(title);
inst->reconfiguring = FALSE;
{
struct gui_data *inst = (struct gui_data *)gdata;
/*
- * For this feature we must marshal cfg and (possibly) pty_argv
+ * For this feature we must marshal conf and (possibly) pty_argv
* into a byte stream, create a pipe, and send this byte stream
* to the child through the pipe.
*/
- int i, ret, size;
+ int i, ret, sersize, size;
char *data;
char option[80];
int pipefd[2];
return;
}
- size = sizeof(inst->cfg);
+ size = sersize = conf_serialised_size(inst->conf);
if (use_pty_argv && pty_argv) {
for (i = 0; pty_argv[i]; i++)
size += strlen(pty_argv[i]) + 1;
}
data = snewn(size, char);
- memcpy(data, &inst->cfg, sizeof(inst->cfg));
+ conf_serialise(inst->conf, data);
if (use_pty_argv && pty_argv) {
- int p = sizeof(inst->cfg);
+ int p = sersize;
for (i = 0; pty_argv[i]; i++) {
strcpy(data + p, pty_argv[i]);
p += strlen(pty_argv[i]) + 1;
sfree(data);
}
-int read_dupsession_data(struct gui_data *inst, Config *cfg, char *arg)
+int read_dupsession_data(struct gui_data *inst, Conf *conf, char *arg)
{
- int fd, i, ret, size;
+ int fd, i, ret, size, size_used;
char *data;
if (sscanf(arg, "---[%d,%d]", &fd, &size) != 2) {
exit(1);
}
- memcpy(cfg, data, sizeof(Config));
- if (use_pty_argv && size > sizeof(Config)) {
+ size_used = conf_deserialise(conf, data, size);
+ if (use_pty_argv && size > size_used) {
int n = 0;
- i = sizeof(Config);
+ i = size_used;
while (i < size) {
while (i < size && data[i]) i++;
if (i >= size) {
pty_argv = snewn(n+1, char *);
pty_argv[n] = NULL;
n = 0;
- i = sizeof(Config);
+ i = size_used;
while (i < size) {
char *p = data + i;
while (i < size && data[i]) i++;
static void start_backend(struct gui_data *inst)
{
- extern Backend *select_backend(Config *cfg);
+ extern Backend *select_backend(Conf *conf);
char *realhost;
const char *error;
+ char *s;
- inst->back = select_backend(&inst->cfg);
+ inst->back = select_backend(inst->conf);
error = inst->back->init((void *)inst, &inst->backhandle,
- &inst->cfg, inst->cfg.host, inst->cfg.port,
- &realhost, inst->cfg.tcp_nodelay,
- inst->cfg.tcp_keepalives);
+ inst->conf,
+ conf_get_str(inst->conf, CONF_host),
+ conf_get_int(inst->conf, CONF_port),
+ &realhost,
+ conf_get_int(inst->conf, CONF_tcp_nodelay),
+ conf_get_int(inst->conf, CONF_tcp_keepalives));
if (error) {
char *msg = dupprintf("Unable to open connection to %s:\n%s",
- inst->cfg.host, error);
+ conf_get_str(inst->conf, CONF_host), error);
inst->exited = TRUE;
fatal_message_box(inst->window, msg);
sfree(msg);
exit(0);
}
- if (inst->cfg.wintitle[0]) {
- set_title(inst, inst->cfg.wintitle);
- set_icon(inst, inst->cfg.wintitle);
+ s = conf_get_str(inst->conf, CONF_wintitle);
+ if (s[0]) {
+ set_title_and_icon(inst, s, s);
} else {
char *title = make_default_wintitle(realhost);
- set_title(inst, title);
- set_icon(inst, title);
+ set_title_and_icon(inst, title, title);
sfree(title);
}
sfree(realhost);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
inst->ldisc =
- ldisc_create(&inst->cfg, inst->term, inst->back, inst->backhandle,
+ ldisc_create(inst->conf, inst->term, inst->back, inst->backhandle,
inst);
gtk_widget_set_sensitive(inst->restartitem, FALSE);
int pt_main(int argc, char **argv)
{
- extern int cfgbox(Config *cfg);
+ extern int cfgbox(Conf *conf);
struct gui_data *inst;
/*
memset(inst, 0, sizeof(*inst));
inst->alt_keycode = -1; /* this one needs _not_ to be zero */
inst->busy_status = BUSY_NOT;
+ inst->conf = conf_new();
+ inst->wintitle = inst->icontitle = NULL;
/* defer any child exit handling until we're ready to deal with
* it */
}
if (argc > 1 && !strncmp(argv[1], "---", 3)) {
- read_dupsession_data(inst, &inst->cfg, argv[1]);
+ read_dupsession_data(inst, inst->conf, argv[1]);
/* Splatter this argument so it doesn't clutter a ps listing */
memset(argv[1], 0, strlen(argv[1]));
} else {
* a session. This gets set to TRUE if something happens to change
* that (e.g., a hostname is specified on the command-line). */
int allow_launch = FALSE;
- if (do_cmdline(argc, argv, 0, &allow_launch, inst, &inst->cfg))
+ if (do_cmdline(argc, argv, 0, &allow_launch, inst, inst->conf))
exit(1); /* pre-defaults pass to get -class */
- do_defaults(NULL, &inst->cfg);
- if (do_cmdline(argc, argv, 1, &allow_launch, inst, &inst->cfg))
+ do_defaults(NULL, inst->conf);
+ if (do_cmdline(argc, argv, 1, &allow_launch, inst, inst->conf))
exit(1); /* post-defaults, do everything */
- cmdline_run_saved(&inst->cfg);
+ cmdline_run_saved(inst->conf);
if (loaded_session)
allow_launch = TRUE;
- if ((!allow_launch || !cfg_launchable(&inst->cfg)) &&
- !cfgbox(&inst->cfg))
+ if ((!allow_launch || !conf_launchable(inst->conf)) &&
+ !cfgbox(inst->conf))
exit(0); /* config box hit Cancel */
}
init_cutbuffers();
inst->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- if (inst->cfg.winclass[0])
- gtk_window_set_wmclass(GTK_WINDOW(inst->window),
- inst->cfg.winclass, inst->cfg.winclass);
+ {
+ const char *winclass = conf_get_str(inst->conf, CONF_winclass);
+ if (*winclass)
+ gtk_window_set_wmclass(GTK_WINDOW(inst->window),
+ winclass, winclass);
+ }
/*
* Set up the colour map.
*/
palette_reset(inst);
- inst->width = inst->cfg.width;
- inst->height = inst->cfg.height;
+ inst->width = conf_get_int(inst->conf, CONF_width);
+ inst->height = conf_get_int(inst->conf, CONF_height);
+ cache_conf_values(inst);
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area),
- inst->font_width * inst->cfg.width + 2*inst->cfg.window_border,
- inst->font_height * inst->cfg.height + 2*inst->cfg.window_border);
+ inst->font_width * inst->width + 2*inst->window_border,
+ inst->font_height * inst->height + 2*inst->window_border);
inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0));
inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust);
inst->hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
* unwanted, so we can pop it up quickly if it suddenly becomes
* desirable.
*/
- if (inst->cfg.scrollbar_on_left)
+ if (conf_get_int(inst->conf, CONF_scrollbar_on_left))
gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0);
gtk_box_pack_start(inst->hbox, inst->area, TRUE, TRUE, 0);
- if (!inst->cfg.scrollbar_on_left)
+ if (!conf_get_int(inst->conf, CONF_scrollbar_on_left))
gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(inst->window), GTK_WIDGET(inst->hbox));
set_geom_hints(inst);
gtk_widget_show(inst->area);
- if (inst->cfg.scrollbar)
+ if (conf_get_int(inst->conf, CONF_scrollbar))
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
GTK_SIGNAL_FUNC(selection_get), inst);
gtk_signal_connect(GTK_OBJECT(inst->area), "selection_clear_event",
GTK_SIGNAL_FUNC(selection_clear), inst);
- if (inst->cfg.scrollbar)
+ if (conf_get_int(inst->conf, CONF_scrollbar))
gtk_signal_connect(GTK_OBJECT(inst->sbar_adjust), "value_changed",
GTK_SIGNAL_FUNC(scrollbar_moved), inst);
gtk_widget_add_events(GTK_WIDGET(inst->area),
inst->eventlogstuff = eventlogstuff_new();
- inst->term = term_init(&inst->cfg, &inst->ucsdata, inst);
- inst->logctx = log_init(inst, &inst->cfg);
+ inst->term = term_init(inst->conf, &inst->ucsdata, inst);
+ inst->logctx = log_init(inst, inst->conf);
term_provide_logctx(inst->term, inst->logctx);
uxsel_init();
- term_size(inst->term, inst->cfg.height, inst->cfg.width, inst->cfg.savelines);
+ term_size(inst->term, inst->height, inst->width,
+ conf_get_int(inst->conf, CONF_savelines));
start_backend(inst);
void *get_window(void *frontend); /* void * to avoid depending on gtk.h */
/* Things pterm.c needs from gtkdlg.c */
-int do_config_box(const char *title, Config *cfg,
+int do_config_box(const char *title, Conf *conf,
int midsession, int protcfginfo);
void fatal_message_box(void *window, char *msg);
void about_box(void *window);
/* Things pterm.c needs from {ptermm,uxputty}.c */
char *make_default_wintitle(char *hostname);
-int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch);
+int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch);
/* pterm.c needs this special function in xkeysym.c */
int keysym_to_unicode(int keysym);
#include "ssh.h"
#include "network.h"
-void platform_get_x11_auth(struct X11Display *disp, const Config *cfg)
+void platform_get_x11_auth(struct X11Display *disp, Conf *conf)
{
char *xauthfile;
int needs_free;
union control *c;
/*
- * The Config structure contains two Unix-specific elements
- * which are not configured in here: stamp_utmp and
- * login_shell. This is because pterm does not put up a
- * configuration box right at the start, which is the only time
- * when these elements would be useful to configure.
+ * The Conf structure contains two Unix-specific elements which
+ * are not configured in here: stamp_utmp and login_shell. This
+ * is because pterm does not put up a configuration box right at
+ * the start, which is the only time when these elements would
+ * be useful to configure.
*/
/*
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_RADIO &&
- c->generic.context.i == offsetof(Config, proxy_type)) {
- assert(c->generic.handler == dlg_stdradiobutton_handler);
+ c->generic.context.i == CONF_proxy_type) {
+ assert(c->generic.handler == conf_radiobutton_handler);
c->radio.nbuttons++;
c->radio.buttons =
sresize(c->radio.buttons, c->radio.nbuttons, char *);
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_EDITBOX &&
- c->generic.context.i ==
- offsetof(Config, proxy_telnet_command)) {
- assert(c->generic.handler == dlg_stdeditbox_handler);
+ c->generic.context.i == CONF_proxy_telnet_command) {
+ assert(c->generic.handler == conf_editbox_handler);
sfree(c->generic.label);
c->generic.label = dupstr("Telnet command, or local"
" proxy command");
}
/* Dynamically load gssapi libs. */
-struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
{
void *gsslib;
+ char *gsspath;
struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist);
list->libraries = snewn(4, struct ssh_gss_library);
2, "Using GSSAPI from libgss.so.1");
/* User-specified GSSAPI library */
- if (cfg->ssh_gss_custom.path[0] &&
- (gsslib = dlopen(cfg->ssh_gss_custom.path, RTLD_LAZY)) != NULL)
+ gsspath = conf_get_filename(conf, CONF_ssh_gss_custom)->path;
+ if (*gsspath && (gsslib = dlopen(gsspath, RTLD_LAZY)) != NULL)
gss_init(&list->libraries[list->nlibraries++], gsslib,
3, dupprintf("Using GSSAPI from user-specified"
- " library '%s'", cfg->ssh_gss_custom.path));
+ " library '%s'", gsspath));
return list;
}
#include <gssapi/gssapi.h>
/* Dynamically load gssapi libs. */
-struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
{
struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist);
static Backend *back;
static void *backhandle;
-static Config cfg;
+static Conf *conf;
/*
* Default settings that are specific to pterm.
/*
* Process the command line.
*/
- do_defaults(NULL, &cfg);
+ conf = conf_new();
+ do_defaults(NULL, conf);
loaded_session = FALSE;
- default_protocol = cfg.protocol;
- default_port = cfg.port;
+ default_protocol = conf_get_int(conf, CONF_protocol);
+ default_port = conf_get_int(conf, CONF_port);
errors = 0;
{
/*
if (p) {
const Backend *b = backend_from_name(p);
if (b) {
- default_protocol = cfg.protocol = b->protocol;
- default_port = cfg.port = b->default_port;
+ default_protocol = b->protocol;
+ default_port = b->default_port;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
}
}
}
char *p = *++argv;
if (*p == '-') {
int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
- 1, &cfg);
+ 1, conf);
if (ret == -2) {
fprintf(stderr,
"plink: option \"%s\" requires an argument\n", p);
} else if (!strcmp(p, "-batch")) {
console_batch_mode = 1;
} else if (!strcmp(p, "-s")) {
- /* Save status to write to cfg later. */
+ /* Save status to write to conf later. */
use_subsystem = 1;
} else if (!strcmp(p, "-V")) {
version();
errors = 1;
}
} else if (*p) {
- if (!cfg_launchable(&cfg) || !(got_host || loaded_session)) {
+ if (!conf_launchable(conf) || !(got_host || loaded_session)) {
char *q = p;
/*
q += 7;
if (q[0] == '/' && q[1] == '/')
q += 2;
- cfg.protocol = PROT_TELNET;
+ conf_set_int(conf, CONF_protocol, PROT_TELNET);
p = q;
while (*p && *p != ':' && *p != '/')
p++;
if (*p)
*p++ = '\0';
if (c == ':')
- cfg.port = atoi(p);
+ conf_set_int(conf, CONF_port, atoi(p));
else
- cfg.port = -1;
- strncpy(cfg.host, q, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_int(conf, CONF_port, -1);
+ conf_set_str(conf, CONF_host, q);
got_host = TRUE;
} else {
char *r, *user, *host;
*r = '\0';
b = backend_from_name(p);
if (b) {
- default_protocol = cfg.protocol = b->protocol;
+ default_protocol = b->protocol;
+ conf_set_int(conf, CONF_protocol,
+ default_protocol);
portnumber = b->default_port;
}
p = r + 1;
* same name as the hostname.
*/
{
- Config cfg2;
- do_defaults(host, &cfg2);
- if (loaded_session || !cfg_launchable(&cfg2)) {
+ Conf *conf2 = conf_new();
+ do_defaults(host, conf2);
+ if (loaded_session || !conf_launchable(conf2)) {
/* No settings for this host; use defaults */
/* (or session was already loaded with -load) */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
- cfg.port = default_port;
+ conf_set_str(conf, CONF_host, host);
+ conf_set_int(conf, CONF_port, default_port);
got_host = TRUE;
} else {
- cfg = cfg2;
+ conf_copy_into(conf, conf2);
loaded_session = TRUE;
}
+ conf_free(conf2);
}
if (user) {
/* Patch in specified username. */
- strncpy(cfg.username, user,
- sizeof(cfg.username) - 1);
- cfg.username[sizeof(cfg.username) - 1] = '\0';
+ conf_set_str(conf, CONF_username, user);
}
}
}
if (cmdlen) command[--cmdlen]='\0';
/* change trailing blank to NUL */
- cfg.remote_cmd_ptr = command;
- cfg.remote_cmd_ptr2 = NULL;
- cfg.nopty = TRUE; /* command => no terminal */
+ conf_set_str(conf, CONF_remote_cmd, command);
+ conf_set_str(conf, CONF_remote_cmd2, "");
+ conf_set_int(conf, CONF_nopty, TRUE); /* command => no tty */
break; /* done with cmdline */
}
if (errors)
return 1;
- if (!cfg_launchable(&cfg) || !(got_host || loaded_session)) {
+ if (!conf_launchable(conf) || !(got_host || loaded_session)) {
usage();
}
/*
- * Trim leading whitespace off the hostname if it's there.
+ * Muck about with the hostname in various ways.
*/
{
- int space = strspn(cfg.host, " \t");
- memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
- }
+ char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
+ char *host = hostbuf;
+ char *p, *q;
+
+ /*
+ * Trim leading whitespace.
+ */
+ host += strspn(host, " \t");
- /* See if host is of the form user@host */
- if (cfg.host[0] != '\0') {
- char *atsign = strrchr(cfg.host, '@');
- /* Make sure we're not overflowing the user field */
- if (atsign) {
- if (atsign - cfg.host < sizeof cfg.username) {
- strncpy(cfg.username, cfg.host, atsign - cfg.host);
- cfg.username[atsign - cfg.host] = '\0';
+ /*
+ * See if host is of the form user@host, and separate out
+ * the username if so.
+ */
+ if (host[0] != '\0') {
+ char *atsign = strrchr(host, '@');
+ if (atsign) {
+ *atsign = '\0';
+ conf_set_str(conf, CONF_username, host);
+ host = atsign + 1;
}
- memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
+
+ /*
+ * Trim off a colon suffix if it's there.
+ */
+ host[strcspn(host, ":")] = '\0';
+
+ /*
+ * Remove any remaining whitespace.
+ */
+ p = hostbuf;
+ q = host;
+ while (*q) {
+ if (*q != ' ' && *q != '\t')
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+
+ conf_set_str(conf, CONF_host, hostbuf);
+ sfree(hostbuf);
}
/*
* Perform command-line overrides on session configuration.
*/
- cmdline_run_saved(&cfg);
+ cmdline_run_saved(conf);
/*
* Apply subsystem status.
*/
if (use_subsystem)
- cfg.ssh_subsys = TRUE;
-
- /*
- * Trim a colon suffix off the hostname if it's there.
- */
- cfg.host[strcspn(cfg.host, ":")] = '\0';
-
- /*
- * Remove any remaining whitespace from the hostname.
- */
- {
- int p1 = 0, p2 = 0;
- while (cfg.host[p2] != '\0') {
- if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
- cfg.host[p1] = cfg.host[p2];
- p1++;
- }
- p2++;
- }
- cfg.host[p1] = '\0';
- }
+ conf_set_int(conf, CONF_ssh_subsys, TRUE);
- if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd && !*cfg.ssh_nc_host)
+ if (!*conf_get_str(conf, CONF_remote_cmd) &&
+ !*conf_get_str(conf, CONF_remote_cmd2) &&
+ !*conf_get_str(conf, CONF_ssh_nc_host))
flags |= FLAG_INTERACTIVE;
/*
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
- back = backend_from_proto(cfg.protocol);
+ back = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) {
fprintf(stderr,
"Internal fault: Unsupported protocol found\n");
* Select port.
*/
if (portnumber != -1)
- cfg.port = portnumber;
+ conf_set_int(conf, CONF_port, portnumber);
/*
* Set up the pipe we'll use to tell us about SIGWINCH.
* connection is set up, so if there are none now, we can safely set
* the "simple" flag.
*/
- if (cfg.protocol == PROT_SSH && !cfg.x11_forward && !cfg.agentfwd &&
- cfg.portfwd[0] == '\0' && cfg.portfwd[1] == '\0')
- cfg.ssh_simple = TRUE;
+ if (conf_get_int(conf, CONF_protocol) == PROT_SSH &&
+ !conf_get_int(conf, CONF_x11_forward) &&
+ !conf_get_int(conf, CONF_agentfwd) &&
+ !conf_get_str_nthstrkey(conf, CONF_portfwd, 0))
+ conf_set_int(conf, CONF_ssh_simple, TRUE);
+
/*
* Start up the connection.
*/
- logctx = log_init(NULL, &cfg);
+ logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
{
const char *error;
char *realhost;
/* nodelay is only useful if stdin is a terminal device */
- int nodelay = cfg.tcp_nodelay && isatty(0);
+ int nodelay = conf_get_int(conf, CONF_tcp_nodelay) && isatty(0);
- error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
- &realhost, nodelay, cfg.tcp_keepalives);
+ error = back->init(NULL, &backhandle, conf,
+ conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port),
+ &realhost, nodelay,
+ conf_get_int(conf, CONF_tcp_keepalives));
if (error) {
fprintf(stderr, "Unable to open connection:\n%s\n", error);
return 1;
}
back->provide_logctx(backhandle, logctx);
- ldisc_create(&cfg, NULL, back, backhandle, NULL);
+ ldisc_create(conf, NULL, back, backhandle, NULL);
sfree(realhost);
}
connopen = 1;
Socket platform_new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg)
+ Plug plug, Conf *conf)
{
char *cmd;
Local_Proxy_Socket ret;
int to_cmd_pipe[2], from_cmd_pipe[2], pid;
- if (cfg->proxy_type != PROXY_CMD)
+ if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
return NULL;
- cmd = format_telnet_command(addr, port, cfg);
+ cmd = format_telnet_command(addr, port, conf);
ret = snew(struct Socket_localproxy_tag);
ret->fn = &socket_fn_table;
const int new_session = 0, saved_sessions = 0; /* or these */
const int use_pty_argv = TRUE;
-Backend *select_backend(Config *cfg)
+Backend *select_backend(Conf *conf)
{
return &pty_backend;
}
-int cfgbox(Config *cfg)
+int cfgbox(Conf *conf)
{
/*
* This is a no-op in pterm, except that we'll ensure the
* protocol is set to -1 to inhibit the useless Connection
* panel in the config box.
*/
- cfg->protocol = -1;
+ conf_set_int(conf, CONF_protocol, -1);
return 1;
}
exit(code);
}
-int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
+int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch)
{
return 0; /* pterm doesn't have any. */
}
static int pty_signal_pipe[2] = { -1, -1 }; /* obviously bogus initial val */
struct pty_tag {
- Config cfg;
+ Conf *conf;
int master_fd, slave_fd;
void *frontend;
char name[FILENAME_MAX];
}
if (finished && !pty->finished) {
+ int close_on_exit;
+
uxsel_del(pty->master_fd);
pty_close(pty);
pty->master_fd = -1;
* Only On Clean and it wasn't a clean exit) do we output a
* `terminated' message.
*/
- if (pty->cfg.close_on_exit == FORCE_OFF ||
- (pty->cfg.close_on_exit == AUTO && pty->exit_code != 0)) {
+ close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit);
+ if (close_on_exit == FORCE_OFF ||
+ (close_on_exit == AUTO && pty->exit_code != 0)) {
char message[512];
if (WIFEXITED(pty->exit_code))
sprintf(message, "\r\n[pterm: process terminated with exit"
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
-static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
+static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
char *host, int port, char **realhost, int nodelay,
int keepalive)
{
pty->frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */
- pty->cfg = *cfg; /* structure copy */
- pty->term_width = cfg->width;
- pty->term_height = cfg->height;
+ pty->conf = conf_copy(conf);
+ pty->term_width = conf_get_int(conf, CONF_width);
+ pty->term_height = conf_get_int(conf, CONF_height);
if (pty->master_fd < 0)
pty_open_master(pty);
{
struct termios attrs;
tcgetattr(pty->master_fd, &attrs);
- attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010';
+ attrs.c_cc[VERASE] = conf_get_int(conf, CONF_bksp_is_delete)
+ ? '\177' : '\010';
tcsetattr(pty->master_fd, TCSANOW, &attrs);
}
* Stamp utmp (that is, tell the utmp helper process to do so),
* or not.
*/
- if (!cfg->stamp_utmp) {
+ if (!conf_get_int(conf, CONF_stamp_utmp)) {
close(pty_utmp_helper_pipe); /* just let the child process die */
pty_utmp_helper_pipe = -1;
} else {
close(open(pty->name, O_WRONLY, 0));
setpgid(pgrp, pgrp);
{
- char *term_env_var = dupprintf("TERM=%s", cfg->termtype);
+ char *term_env_var = dupprintf("TERM=%s",
+ conf_get_str(conf, CONF_termtype));
putenv(term_env_var);
/* We mustn't free term_env_var, as putenv links it into the
* environment in place.
}
#endif
{
- char *e = cfg->environmt;
- char *var, *varend, *val, *varval;
- while (*e) {
- var = e;
- while (*e && *e != '\t') e++;
- varend = e;
- if (*e == '\t') e++;
- val = e;
- while (*e) e++;
- e++;
-
- varval = dupprintf("%.*s=%s", varend-var, var, val);
+ char *key, *val;
+
+ for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key);
+ val != NULL;
+ val = conf_get_str_strs(conf, CONF_environmt, key, &key)) {
+ char *varval = dupcat(key, "=", val, NULL);
putenv(varval);
/*
* We must not free varval, since putenv links it
else {
char *shell = getenv("SHELL");
char *shellname;
- if (cfg->login_shell) {
+ if (conf_get_int(conf, CONF_login_shell)) {
char *p = strrchr(shell, '/');
shellname = snewn(2+strlen(shell), char);
p = p ? p+1 : shell;
return NULL;
}
-static void pty_reconfig(void *handle, Config *cfg)
+static void pty_reconfig(void *handle, Conf *conf)
{
Pty pty = (Pty)handle;
/*
* unfortunately we do need to pick up the setting of Close On
* Exit so we know whether to give a `terminated' message.
*/
- pty->cfg = *cfg; /* structure copy */
+ conf_copy_into(pty->conf, conf);
}
/*
exit(code);
}
-Backend *select_backend(Config *cfg)
+Backend *select_backend(Conf *conf)
{
- Backend *back = backend_from_proto(cfg->protocol);
+ Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol));
assert(back != NULL);
return back;
}
-int cfgbox(Config *cfg)
+int cfgbox(Conf *conf)
{
char *title = dupcat(appname, " Configuration", NULL);
- int ret = do_config_box(title, cfg, 0, 0);
+ int ret = do_config_box(title, conf, 0, 0);
sfree(title);
return ret;
}
const int use_event_log = 1, new_session = 1, saved_sessions = 1;
-int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
+int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch)
{
char *p, *q = arg;
* argument, so that it will be deferred until it's a good
* moment to run it.
*/
- int ret = cmdline_process_param("-P", arg, 1, cfg);
+ int ret = cmdline_process_param("-P", arg, 1, conf);
assert(ret == 2);
} else if (!strncmp(q, "telnet:", 7)) {
/*
q += 7;
if (q[0] == '/' && q[1] == '/')
q += 2;
- cfg->protocol = PROT_TELNET;
+ conf_set_int(conf, CONF_protocol, PROT_TELNET);
p = q;
while (*p && *p != ':' && *p != '/')
p++;
if (*p)
*p++ = '\0';
if (c == ':')
- cfg->port = atoi(p);
+ conf_set_int(conf, CONF_port, atoi(p));
else
- cfg->port = -1;
- strncpy(cfg->host, q, sizeof(cfg->host) - 1);
- cfg->host[sizeof(cfg->host) - 1] = '\0';
+ conf_set_int(conf, CONF_port, -1);
+ conf_set_str(conf, CONF_host, q);
got_host = 1;
} else {
/*
p++;
if (*p)
*p++ = '\0';
- strncpy(cfg->host, q, sizeof(cfg->host) - 1);
- cfg->host[sizeof(cfg->host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, q);
got_host = 1;
}
if (got_host)
static void serial_uxsel_setup(Serial serial);
static void serial_try_write(Serial serial);
-static const char *serial_configure(Serial serial, Config *cfg)
+static const char *serial_configure(Serial serial, Conf *conf)
{
struct termios options;
- int bflag, bval;
+ int bflag, bval, speed, flow, parity;
const char *str;
char *msg;
/*
* Find the appropriate baud rate flag.
*/
+ speed = conf_get_int(conf, CONF_serspeed);
#define SETBAUD(x) (bflag = B ## x, bval = x)
-#define CHECKBAUD(x) do { if (cfg->serspeed >= x) SETBAUD(x); } while (0)
+#define CHECKBAUD(x) do { if (speed >= x) SETBAUD(x); } while (0)
SETBAUD(50);
#ifdef B75
CHECKBAUD(75);
sfree(msg);
options.c_cflag &= ~CSIZE;
- switch (cfg->serdatabits) {
+ switch (conf_get_int(conf, CONF_serdatabits)) {
case 5: options.c_cflag |= CS5; break;
case 6: options.c_cflag |= CS6; break;
case 7: options.c_cflag |= CS7; break;
case 8: options.c_cflag |= CS8; break;
default: return "Invalid number of data bits (need 5, 6, 7 or 8)";
}
- msg = dupprintf("Configuring %d data bits", cfg->serdatabits);
+ msg = dupprintf("Configuring %d data bits",
+ conf_get_int(conf, CONF_serdatabits));
logevent(serial->frontend, msg);
sfree(msg);
- if (cfg->serstopbits >= 4) {
+ if (conf_get_int(conf, CONF_serstopbits) >= 4) {
options.c_cflag |= CSTOPB;
} else {
options.c_cflag &= ~CSTOPB;
#ifdef CNEW_RTSCTS
options.c_cflag &= ~CNEW_RTSCTS;
#endif
- if (cfg->serflow == SER_FLOW_XONXOFF) {
+ flow = conf_get_int(conf, CONF_serflow);
+ if (flow == SER_FLOW_XONXOFF) {
options.c_iflag |= IXON | IXOFF;
str = "XON/XOFF";
- } else if (cfg->serflow == SER_FLOW_RTSCTS) {
+ } else if (flow == SER_FLOW_RTSCTS) {
#ifdef CRTSCTS
options.c_cflag |= CRTSCTS;
#endif
sfree(msg);
/* Parity */
- if (cfg->serparity == SER_PAR_ODD) {
+ parity = conf_get_int(conf, CONF_serparity);
+ if (parity == SER_PAR_ODD) {
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
str = "odd";
- } else if (cfg->serparity == SER_PAR_EVEN) {
+ } else if (parity == SER_PAR_EVEN) {
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
str = "even";
* freed by the caller.
*/
static const char *serial_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
+ Conf *conf,
char *host, int port, char **realhost, int nodelay,
int keepalive)
{
Serial serial;
const char *err;
+ char *line;
serial = snew(struct serial_backend_data);
*backend_handle = serial;
serial->inbufsize = 0;
bufchain_init(&serial->output_data);
+ line = conf_get_str(conf, CONF_serline);
{
- char *msg = dupprintf("Opening serial device %s", cfg->serline);
+ char *msg = dupprintf("Opening serial device %s", line);
logevent(serial->frontend, msg);
}
- serial->fd = open(cfg->serline, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
+ serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (serial->fd < 0)
return "Unable to open serial port";
cloexec(serial->fd);
- err = serial_configure(serial, cfg);
+ err = serial_configure(serial, conf);
if (err)
return err;
- *realhost = dupstr(cfg->serline);
+ *realhost = dupstr(line);
if (!serial_by_fd)
serial_by_fd = newtree234(serial_compare_by_fd);
sfree(serial);
}
-static void serial_reconfig(void *handle, Config *cfg)
+static void serial_reconfig(void *handle, Conf *conf)
{
Serial serial = (Serial) handle;
/*
* FIXME: what should we do if this returns an error?
*/
- serial_configure(serial, cfg);
+ serial_configure(serial, conf);
}
static int serial_select_result(int fd, int event)
return NULL; /* this is a stub */
}
-void platform_get_x11_auth(struct X11Display *display, const Config *cfg)
+void platform_get_x11_auth(struct X11Display *display, Conf *conf)
{
/* Do nothing, therefore no auth. */
}
return ret;
}
-char *read_setting_s(void *handle, const char *key, char *buffer, int buflen)
+char *read_setting_s(void *handle, const char *key)
{
tree234 *tree = (tree234 *)handle;
const char *val;
if (!val)
return NULL;
- else {
- strncpy(buffer, val, buflen);
- buffer[buflen-1] = '\0';
- return buffer;
- }
+ else
+ return dupstr(val);
}
int read_setting_i(void *handle, const char *key, int defvalue)
* ("FontName").
*/
char *suffname = dupcat(name, "Name", NULL);
- if (read_setting_s(handle, suffname, result->name, sizeof(result->name))) {
+ char *tmp;
+
+ if ((tmp = read_setting_s(handle, suffname)) != NULL) {
+ strncpy(result->name, tmp, sizeof(result->name)-1);
+ result->name[sizeof(result->name)-1] = '\0';
sfree(suffname);
+ sfree(tmp);
return TRUE; /* got new-style name */
}
sfree(suffname);
/* Fall back to old-style name. */
- memcpy(result->name, "server:", 7);
- if (!read_setting_s(handle, name,
- result->name + 7, sizeof(result->name) - 7) ||
- !result->name[7]) {
- result->name[0] = '\0';
- return FALSE;
- } else {
+ tmp = read_setting_s(handle, name);
+ if (tmp && *tmp) {
+ strcpy(result->name, "server:");
+ strncpy(result->name + 7, tmp, sizeof(result->name) - 8);
+ result->name[sizeof(result->name)-1] = '\0';
+ sfree(tmp);
return TRUE;
+ } else {
+ sfree(tmp);
+ return FALSE;
}
}
int read_setting_filename(void *handle, const char *name, Filename *result)
{
- return !!read_setting_s(handle, name, result->path, sizeof(result->path));
+ char *tmp = read_setting_s(handle, name);
+ if (tmp) {
+ strncpy(result->path, tmp, sizeof(result->path)-1);
+ result->path[sizeof(result->path)-1] = '\0';
+ sfree(tmp);
+ return TRUE;
+ } else
+ return FALSE;
}
void write_setting_fontspec(void *handle, const char *name, FontSpec result)
/*
* Failing that, line_codepage should be decoded from the
- * specification in cfg.
+ * specification in conf.
*/
if (ucsdata->line_codepage == CS_NONE)
ucsdata->line_codepage = decode_codepage(linecharset);
"Control the scrollback in the window");
ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
HELPCTX(window_scrollback),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,scrollbar_in_fullscreen)));
+ conf_checkbox_handler,
+ I(CONF_scrollbar_in_fullscreen));
/*
* Really this wants to go just after `Display scrollbar'. See
* if we can find that control, and do some shuffling.
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_CHECKBOX &&
- c->generic.context.i == offsetof(Config,scrollbar)) {
+ c->generic.context.i == CONF_scrollbar) {
/*
* Control i is the scrollbar checkbox.
* Control s->ncontrols-1 is the scrollbar-in-FS one.
"Enable extra keyboard features:");
ctrl_checkbox(s, "AltGr acts as Compose key", 't',
HELPCTX(keyboard_compose),
- dlg_stdcheckbox_handler, I(offsetof(Config,compose_key)));
+ conf_checkbox_handler, I(CONF_compose_key));
ctrl_checkbox(s, "Control-Alt is different from AltGr", 'd',
HELPCTX(keyboard_ctrlalt),
- dlg_stdcheckbox_handler, I(offsetof(Config,ctrlaltkeys)));
+ conf_checkbox_handler, I(CONF_ctrlaltkeys));
/*
* Windows allows an arbitrary .WAV to be played as a bell, and
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_RADIO &&
- c->generic.context.i == offsetof(Config, beep)) {
- assert(c->generic.handler == dlg_stdradiobutton_handler);
+ c->generic.context.i == CONF_beep) {
+ assert(c->generic.handler == conf_radiobutton_handler);
c->radio.nbuttons += 2;
c->radio.buttons =
sresize(c->radio.buttons, c->radio.nbuttons, char *);
ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,
FILTER_WAVE_FILES, FALSE, "Select bell sound file",
HELPCTX(bell_style),
- dlg_stdfilesel_handler, I(offsetof(Config, bell_wavefile)));
+ conf_filesel_handler, I(CONF_bell_wavefile));
/*
* While we've got this box open, taskbar flashing on a bell is
*/
ctrl_radiobuttons(s, "Taskbar/caption indication on bell:", 'i', 3,
HELPCTX(bell_taskbar),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, beep_ind)),
+ conf_radiobutton_handler,
+ I(CONF_beep_ind),
"Disabled", I(B_IND_DISABLED),
"Flashing", I(B_IND_FLASH),
"Steady", I(B_IND_STEADY), NULL);
"Adjust the window border");
ctrl_checkbox(s, "Sunken-edge border (slightly thicker)", 's',
HELPCTX(appearance_border),
- dlg_stdcheckbox_handler, I(offsetof(Config,sunken_edge)));
+ conf_checkbox_handler, I(CONF_sunken_edge));
/*
* Configurable font quality settings for Windows.
HELPCTX(appearance_font), variable_pitch_handler, I(0));
ctrl_radiobuttons(s, "Font quality:", 'q', 2,
HELPCTX(appearance_font),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, font_quality)),
+ conf_radiobutton_handler,
+ I(CONF_font_quality),
"Antialiased", I(FQ_ANTIALIASED),
"Non-Antialiased", I(FQ_NONANTIALIASED),
"ClearType", I(FQ_CLEARTYPE),
s = ctrl_getset(b, "Window/Translation", "tweaks", NULL);
ctrl_checkbox(s, "Caps Lock acts as Cyrillic switch", 's',
HELPCTX(translation_cyrillic),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,xlat_capslockcyr)));
+ conf_checkbox_handler,
+ I(CONF_xlat_capslockcyr));
/*
* On Windows we can use but not enumerate translation tables
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_RADIO &&
- c->generic.context.i == offsetof(Config, vtmode)) {
- assert(c->generic.handler == dlg_stdradiobutton_handler);
+ c->generic.context.i == CONF_vtmode) {
+ assert(c->generic.handler == conf_radiobutton_handler);
c->radio.nbuttons += 3;
c->radio.buttons =
sresize(c->radio.buttons, c->radio.nbuttons, char *);
"Formatting of pasted characters");
ctrl_checkbox(s, "Paste to clipboard in RTF as well as plain text", 'f',
HELPCTX(selection_rtf),
- dlg_stdcheckbox_handler, I(offsetof(Config,rtf_paste)));
+ conf_checkbox_handler, I(CONF_rtf_paste));
/*
* Windows often has no middle button, so we supply a selection
"Control use of mouse");
ctrl_radiobuttons(s, "Action of mouse buttons:", 'm', 1,
HELPCTX(selection_buttons),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, mouse_is_xterm)),
+ conf_radiobutton_handler,
+ I(CONF_mouse_is_xterm),
"Windows (Middle extends, Right brings up menu)", I(2),
"Compromise (Middle extends, Right pastes)", I(0),
"xterm (Right extends, Middle pastes)", I(1), NULL);
"General options for colour usage");
ctrl_checkbox(s, "Attempt to use logical palettes", 'l',
HELPCTX(colours_logpal),
- dlg_stdcheckbox_handler, I(offsetof(Config,try_palette)));
+ conf_checkbox_handler, I(CONF_try_palette));
ctrl_checkbox(s, "Use system colours", 's',
HELPCTX(colours_system),
- dlg_stdcheckbox_handler, I(offsetof(Config,system_colour)));
+ conf_checkbox_handler, I(CONF_system_colour));
/*
s = ctrl_getset(b, "Window", "size", "Set the size of the window");
ctrl_radiobuttons(s, "When window is resized:", 'z', 1,
HELPCTX(window_resize),
- dlg_stdradiobutton_handler,
- I(offsetof(Config, resize_action)),
+ conf_radiobutton_handler,
+ I(CONF_resize_action),
"Change the number of rows and columns", I(RESIZE_TERM),
"Change the size of the font", I(RESIZE_FONT),
"Change font size only when maximised", I(RESIZE_EITHER),
s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
ctrl_checkbox(s, "Window closes on ALT-F4", '4',
HELPCTX(behaviour_altf4),
- dlg_stdcheckbox_handler, I(offsetof(Config,alt_f4)));
+ conf_checkbox_handler, I(CONF_alt_f4));
ctrl_checkbox(s, "System menu appears on ALT-Space", 'y',
HELPCTX(behaviour_altspace),
- dlg_stdcheckbox_handler, I(offsetof(Config,alt_space)));
+ conf_checkbox_handler, I(CONF_alt_space));
ctrl_checkbox(s, "System menu appears on ALT alone", 'l',
HELPCTX(behaviour_altonly),
- dlg_stdcheckbox_handler, I(offsetof(Config,alt_only)));
+ conf_checkbox_handler, I(CONF_alt_only));
ctrl_checkbox(s, "Ensure window is always on top", 'e',
HELPCTX(behaviour_alwaysontop),
- dlg_stdcheckbox_handler, I(offsetof(Config,alwaysontop)));
+ conf_checkbox_handler, I(CONF_alwaysontop));
ctrl_checkbox(s, "Full screen on Alt-Enter", 'f',
HELPCTX(behaviour_altenter),
- dlg_stdcheckbox_handler,
- I(offsetof(Config,fullscreenonaltenter)));
+ conf_checkbox_handler,
+ I(CONF_fullscreenonaltenter));
/*
* Windows supports a local-command proxy. This also means we
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_RADIO &&
- c->generic.context.i == offsetof(Config, proxy_type)) {
- assert(c->generic.handler == dlg_stdradiobutton_handler);
+ c->generic.context.i == CONF_proxy_type) {
+ assert(c->generic.handler == conf_radiobutton_handler);
c->radio.nbuttons++;
c->radio.buttons =
sresize(c->radio.buttons, c->radio.nbuttons, char *);
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_EDITBOX &&
- c->generic.context.i ==
- offsetof(Config, proxy_telnet_command)) {
- assert(c->generic.handler == dlg_stdeditbox_handler);
+ c->generic.context.i == CONF_proxy_telnet_command) {
+ assert(c->generic.handler == conf_editbox_handler);
sfree(c->generic.label);
c->generic.label = dupstr("Telnet command, or local"
" proxy command");
ctrl_filesel(s, "X authority file for local display", 't',
NULL, FALSE, "Select X authority file",
HELPCTX(ssh_tunnels_xauthority),
- dlg_stdfilesel_handler, I(offsetof(Config, xauthfile)));
+ conf_filesel_handler, I(CONF_xauthfile));
}
}
SetDlgItemText(dp->hwnd, c->base_id+1, text);
}
-void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
+char *dlg_editbox_get(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
+ char *ret;
+ int size;
assert(c && c->ctrl->generic.type == CTRL_EDITBOX);
- GetDlgItemText(dp->hwnd, c->base_id+1, buffer, length);
- buffer[length-1] = '\0';
+
+ size = 0;
+ ret = NULL;
+ do {
+ size = size * 4 / 3 + 512;
+ ret = sresize(ret, size, char);
+ GetDlgItemText(dp->hwnd, c->base_id+1, ret, size);
+ } while (!memchr(ret, '\0', size-1));
+
+ return ret;
}
/* The `listbox' functions can also apply to combo boxes. */
void dlg_auto_set_fixed_pitch_flag(void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
- Config *cfg = (Config *)dp->data;
- HFONT font;
+ Conf *conf = (Conf *)dp->data;
+ FontSpec *font;
+ int quality;
+ HFONT hfont;
HDC hdc;
TEXTMETRIC tm;
int is_var;
* dialog box as false.
*
* We assume here that any client of the dlg_* mechanism which is
- * using font selectors at all is also using a normal 'Config *'
+ * using font selectors at all is also using a normal 'Conf *'
* as dp->data.
*/
- font = CreateFont(0, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
- DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg->font_quality),
- FIXED_PITCH | FF_DONTCARE, cfg->font.name);
+ quality = conf_get_int(conf, CONF_font_quality);
+ font = conf_get_fontspec(conf, CONF_font);
+
+ hfont = CreateFont(0, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
+ DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality),
+ FIXED_PITCH | FF_DONTCARE, font->name);
hdc = GetDC(NULL);
- if (font && hdc && SelectObject(hdc, font) && GetTextMetrics(hdc, &tm)) {
+ if (font && hdc && SelectObject(hdc, hfont) && GetTextMetrics(hdc, &tm)) {
/* Note that the TMPF_FIXED_PITCH bit is defined upside down :-( */
is_var = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
} else {
}
if (hdc)
ReleaseDC(NULL, hdc);
- if (font)
- DeleteObject(font);
+ if (hfont)
+ DeleteObject(hfont);
if (is_var)
dp->fixed_pitch_fonts = FALSE;
static char **events = NULL;
static int nevents = 0, negsize = 0;
-extern Config cfg; /* defined in window.c */
+extern Conf *conf; /* defined in window.c */
#define PRINTER_DISABLED_STRING "None (printing disabled)"
dp_add_tree(&dp, &ctrls_panel);
dp.wintitle = dupprintf("%s Configuration", appname);
dp.errtitle = dupprintf("%s Error", appname);
- dp.data = &cfg;
+ dp.data = conf;
dlg_auto_set_fixed_pitch_flag(&dp);
dp.shortcuts['g'] = TRUE; /* the treeview: `Cate&gory' */
int do_reconfig(HWND hwnd, int protcfginfo)
{
- Config backup_cfg;
- int ret;
+ Conf *backup_conf;
+ int ret, protocol;
- backup_cfg = cfg; /* structure copy */
+ backup_conf = conf_copy(conf);
ctrlbox = ctrl_new_box();
- setup_config_box(ctrlbox, TRUE, cfg.protocol, protcfginfo);
- win_setup_config_box(ctrlbox, &dp.hwnd, has_help(), TRUE,
- cfg.protocol);
+ protocol = conf_get_int(conf, CONF_protocol);
+ setup_config_box(ctrlbox, TRUE, protocol, protcfginfo);
+ win_setup_config_box(ctrlbox, &dp.hwnd, has_help(), TRUE, protocol);
dp_init(&dp);
winctrl_init(&ctrls_base);
winctrl_init(&ctrls_panel);
dp_add_tree(&dp, &ctrls_panel);
dp.wintitle = dupprintf("%s Reconfiguration", appname);
dp.errtitle = dupprintf("%s Error", appname);
- dp.data = &cfg;
+ dp.data = conf;
dlg_auto_set_fixed_pitch_flag(&dp);
dp.shortcuts['g'] = TRUE; /* the treeview: `Cate&gory' */
dp_cleanup(&dp);
if (!ret)
- cfg = backup_cfg; /* structure copy */
+ conf_copy_into(conf, backup_conf);
+
+ conf_free(backup_conf);
return ret;
}
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
unsigned char *output);
-static void cfgtopalette(void);
+static void conftopalette(void);
static void systopalette(void);
static void init_palette(void);
static void init_fonts(int, int);
enum { SYSMENU, CTXMENU };
static HMENU savedsess_menu;
-Config cfg; /* exported to windlg.c */
+Conf *conf; /* exported to windlg.c */
+
+static void conf_cache_data(void);
+int cursor_type;
+int vtmode;
static struct sesslist sesslist; /* for saved-session menu */
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
- back = backend_from_proto(cfg.protocol);
+ back = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) {
char *str = dupprintf("%s Internal Error", appname);
MessageBox(NULL, "Unsupported protocol number found",
cleanup_exit(1);
}
- error = back->init(NULL, &backhandle, &cfg,
- cfg.host, cfg.port, &realhost, cfg.tcp_nodelay,
- cfg.tcp_keepalives);
+ error = back->init(NULL, &backhandle, conf,
+ conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port),
+ &realhost,
+ conf_get_int(conf, CONF_tcp_nodelay),
+ conf_get_int(conf, CONF_tcp_keepalives));
back->provide_logctx(backhandle, logctx);
if (error) {
char *str = dupprintf("%s Error", appname);
sprintf(msg, "Unable to open connection to\n"
- "%.800s\n" "%s", cfg_dest(&cfg), error);
+ "%.800s\n" "%s", conf_dest(conf), error);
MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
sfree(str);
exit(0);
}
window_name = icon_name = NULL;
- if (*cfg.wintitle) {
- title = cfg.wintitle;
- } else {
+ title = conf_get_str(conf, CONF_wintitle);
+ if (!*title) {
sprintf(msg, "%s - %s", realhost, appname);
title = msg;
}
/*
* Set up a line discipline.
*/
- ldisc = ldisc_create(&cfg, term, back, backhandle, NULL);
+ ldisc = ldisc_create(conf, term, back, backhandle, NULL);
/*
* Destroy the Restart Session menu item. (This will return
init_flashwindow();
+ conf = conf_new();
+
/*
* Initialize COM.
*/
if (b)
default_port = b->default_port;
}
- cfg.logtype = LGTYP_NONE;
+ conf_set_int(conf, CONF_logtype, LGTYP_NONE);
- do_defaults(NULL, &cfg);
+ do_defaults(NULL, conf);
p = cmdline;
while (i > 1 && isspace(p[i - 1]))
i--;
p[i] = '\0';
- do_defaults(p + 1, &cfg);
- if (!cfg_launchable(&cfg) && !do_config()) {
+ do_defaults(p + 1, conf);
+ if (!conf_launchable(conf) && !do_config()) {
cleanup_exit(0);
}
allow_launch = TRUE; /* allow it to be launched directly */
/*
* An initial & means we've been given a command line
* containing the hex value of a HANDLE for a file
- * mapping object, which we must then extract as a
- * config.
+ * mapping object, which we must then interpret as a
+ * serialised Conf.
*/
HANDLE filemap;
- Config *cp;
- if (sscanf(p + 1, "%p", &filemap) == 1 &&
+ void *cp;
+ unsigned cpsize;
+ if (sscanf(p + 1, "%p:%u", &filemap, &cpsize) == 1 &&
(cp = MapViewOfFile(filemap, FILE_MAP_READ,
- 0, 0, sizeof(Config))) != NULL) {
- cfg = *cp;
+ 0, 0, cpsize)) != NULL) {
+ conf_deserialise(conf, cp, cpsize);
UnmapViewOfFile(cp);
CloseHandle(filemap);
} else if (!do_config()) {
int ret;
ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL,
- 1, &cfg);
+ 1, conf);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", p);
} else if (ret == 2) {
* argument, so that it will be deferred
* until it's a good moment to run it.
*/
- int ret = cmdline_process_param("-P", p, 1, &cfg);
+ int ret = cmdline_process_param("-P", p, 1, conf);
assert(ret == 2);
} else if (!strncmp(q, "telnet:", 7)) {
/*
q += 7;
if (q[0] == '/' && q[1] == '/')
q += 2;
- cfg.protocol = PROT_TELNET;
+ conf_set_int(conf, CONF_protocol, PROT_TELNET);
p = q;
while (*p && *p != ':' && *p != '/')
p++;
if (*p)
*p++ = '\0';
if (c == ':')
- cfg.port = atoi(p);
+ conf_set_int(conf, CONF_port, atoi(p));
else
- cfg.port = -1;
- strncpy(cfg.host, q, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_int(conf, CONF_port, -1);
+ conf_set_str(conf, CONF_host, q);
got_host = 1;
} else {
/*
p++;
if (*p)
*p++ = '\0';
- strncpy(cfg.host, q, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_str(conf, CONF_host, q);
got_host = 1;
}
} else {
}
}
- cmdline_run_saved(&cfg);
+ cmdline_run_saved(conf);
if (loaded_session || got_host)
allow_launch = TRUE;
- if ((!allow_launch || !cfg_launchable(&cfg)) && !do_config()) {
+ if ((!allow_launch || !conf_launchable(conf)) && !do_config()) {
cleanup_exit(0);
}
/*
- * Trim leading whitespace off the hostname if it's there.
+ * Muck about with the hostname in various ways.
*/
{
- int space = strspn(cfg.host, " \t");
- memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
- }
+ char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
+ char *host = hostbuf;
+ char *p, *q;
- /* See if host is of the form user@host */
- if (cfg.host[0] != '\0') {
- char *atsign = strrchr(cfg.host, '@');
- /* Make sure we're not overflowing the user field */
- if (atsign) {
- if (atsign - cfg.host < sizeof cfg.username) {
- strncpy(cfg.username, cfg.host, atsign - cfg.host);
- cfg.username[atsign - cfg.host] = '\0';
+ /*
+ * Trim leading whitespace.
+ */
+ host += strspn(host, " \t");
+
+ /*
+ * See if host is of the form user@host, and separate
+ * out the username if so.
+ */
+ if (host[0] != '\0') {
+ char *atsign = strrchr(host, '@');
+ if (atsign) {
+ *atsign = '\0';
+ conf_set_str(conf, CONF_username, host);
+ host = atsign + 1;
}
- memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
- }
- /*
- * Trim a colon suffix off the hostname if it's there. In
- * order to protect IPv6 address literals against this
- * treatment, we do not do this if there's _more_ than one
- * colon.
- */
- {
- char *c = strchr(cfg.host, ':');
+ /*
+ * Trim off a colon suffix if it's there.
+ */
+ host[strcspn(host, ":")] = '\0';
- if (c) {
- char *d = strchr(c+1, ':');
- if (!d)
- *c = '\0';
+ /*
+ * Remove any remaining whitespace.
+ */
+ p = hostbuf;
+ q = host;
+ while (*q) {
+ if (*q != ' ' && *q != '\t')
+ *p++ = *q;
+ q++;
}
- }
+ *p = '\0';
- /*
- * Remove any remaining whitespace from the hostname.
- */
- {
- int p1 = 0, p2 = 0;
- while (cfg.host[p2] != '\0') {
- if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
- cfg.host[p1] = cfg.host[p2];
- p1++;
- }
- p2++;
- }
- cfg.host[p1] = '\0';
+ conf_set_str(conf, CONF_host, hostbuf);
+ sfree(hostbuf);
}
}
memset(&ucsdata, 0, sizeof(ucsdata));
- cfgtopalette();
+ conf_cache_data();
+
+ conftopalette();
/*
* Guess some defaults for the window size. This all gets
font_height = 20;
extra_width = 25;
extra_height = 28;
- guess_width = extra_width + font_width * cfg.width;
- guess_height = extra_height + font_height * cfg.height;
+ guess_width = extra_width + font_width * conf_get_int(conf, CONF_width);
+ guess_height = extra_height + font_height*conf_get_int(conf, CONF_height);
{
RECT r;
get_fullscreen_rect(&r);
{
int winmode = WS_OVERLAPPEDWINDOW | WS_VSCROLL;
int exwinmode = 0;
- if (!cfg.scrollbar)
+ if (!conf_get_int(conf, CONF_scrollbar))
winmode &= ~(WS_VSCROLL);
- if (cfg.resize_action == RESIZE_DISABLED)
+ if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED)
winmode &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
- if (cfg.alwaysontop)
+ if (conf_get_int(conf, CONF_alwaysontop))
exwinmode |= WS_EX_TOPMOST;
- if (cfg.sunken_edge)
+ if (conf_get_int(conf, CONF_sunken_edge))
exwinmode |= WS_EX_CLIENTEDGE;
hwnd = CreateWindowEx(exwinmode, appname, appname,
winmode, CW_USEDEFAULT, CW_USEDEFAULT,
* which will call schedule_timer(), which will in turn call
* timer_change_notify() which will expect hwnd to exist.)
*/
- term = term_init(&cfg, &ucsdata, NULL);
- logctx = log_init(NULL, &cfg);
+ term = term_init(conf, &ucsdata, NULL);
+ logctx = log_init(NULL, conf);
term_provide_logctx(term, logctx);
- term_size(term, cfg.height, cfg.width, cfg.savelines);
+ term_size(term, conf_get_int(conf, CONF_height),
+ conf_get_int(conf, CONF_width),
+ conf_get_int(conf, CONF_savelines));
/*
* Initialise the fonts, simultaneously correcting the guesses
RECT cr, wr;
GetWindowRect(hwnd, &wr);
GetClientRect(hwnd, &cr);
- offset_width = offset_height = cfg.window_border;
+ offset_width = offset_height = conf_get_int(conf, CONF_window_border);
extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
}
AppendMenu(m, MF_ENABLED, IDM_CLRSB, "C&lear Scrollback");
AppendMenu(m, MF_ENABLED, IDM_RESET, "Rese&t Terminal");
AppendMenu(m, MF_SEPARATOR, 0, 0);
- AppendMenu(m, (cfg.resize_action == RESIZE_DISABLED) ?
- MF_GRAYED : MF_ENABLED, IDM_FULLSCREEN, "&Full Screen");
+ AppendMenu(m, (conf_get_int(conf, CONF_resize_action)
+ == RESIZE_DISABLED) ? MF_GRAYED : MF_ENABLED,
+ IDM_FULLSCREEN, "&Full Screen");
AppendMenu(m, MF_SEPARATOR, 0, 0);
if (has_help())
AppendMenu(m, MF_ENABLED, IDM_HELP, "&Help");
DeleteObject(pal);
sk_cleanup();
- if (cfg.protocol == PROT_SSH) {
+ if (conf_get_int(conf, CONF_protocol) == PROT_SSH) {
random_save_seed();
#ifdef MSCRYPTOAPI
crypto_wrapup();
*/
void set_raw_mouse_mode(void *frontend, int activate)
{
- activate = activate && !cfg.no_mouse_rep;
+ activate = activate && !conf_get_int(conf, CONF_no_mouse_rep);
send_raw_mouse = activate;
update_mouse_pointer();
}
MessageBox(hwnd, stuff, morestuff, MB_ICONERROR | MB_OK);
sfree(stuff);
- if (cfg.close_on_exit == FORCE_ON)
+ if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON)
PostQuitMessage(1);
else {
must_close_session = TRUE;
* Copy the colour palette from the configuration data into defpal.
* This is non-trivial because the colour indices are different.
*/
-static void cfgtopalette(void)
+static void conftopalette(void)
{
int i;
static const int ww[] = {
for (i = 0; i < 22; i++) {
int w = ww[i];
- defpal[w].rgbtRed = cfg.colours[i][0];
- defpal[w].rgbtGreen = cfg.colours[i][1];
- defpal[w].rgbtBlue = cfg.colours[i][2];
+ defpal[w].rgbtRed = conf_get_int_int(conf, CONF_colours, i*3+0);
+ defpal[w].rgbtGreen = conf_get_int_int(conf, CONF_colours, i*3+1);
+ defpal[w].rgbtBlue = conf_get_int_int(conf, CONF_colours, i*3+2);
}
for (i = 0; i < NEXTCOLOURS; i++) {
if (i < 216) {
}
/* Override with system colours if appropriate */
- if (cfg.system_colour)
+ if (conf_get_int(conf, CONF_system_colour))
systopalette();
}
int i;
HDC hdc = GetDC(hwnd);
if (hdc) {
- if (cfg.try_palette && GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
+ if (conf_get_int(conf, CONF_try_palette) &&
+ GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
/*
* This is a genuine case where we must use smalloc
* because the snew macros can't cope.
{
TEXTMETRIC tm;
CPINFO cpinfo;
+ FontSpec *font;
int fontsize[3];
int i;
+ int quality;
HDC hdc;
int fw_dontcare, fw_bold;
for (i = 0; i < FONT_MAXNO; i++)
fonts[i] = NULL;
- bold_mode = cfg.bold_colour ? BOLD_COLOURS : BOLD_FONT;
+ bold_mode = conf_get_int(conf, CONF_bold_colour) ?
+ BOLD_COLOURS : BOLD_FONT;
und_mode = UND_FONT;
- if (cfg.font.isbold) {
+ font = conf_get_fontspec(conf, CONF_font);
+ if (font->isbold) {
fw_dontcare = FW_BOLD;
fw_bold = FW_HEAVY;
} else {
if (pick_height)
font_height = pick_height;
else {
- font_height = cfg.font.height;
+ font_height = font->height;
if (font_height > 0) {
font_height =
-MulDiv(font_height, GetDeviceCaps(hdc, LOGPIXELSY), 72);
}
font_width = pick_width;
+ quality = conf_get_int(conf, CONF_font_quality);
#define f(i,c,w,u) \
fonts[i] = CreateFont (font_height, font_width, 0, 0, w, FALSE, u, FALSE, \
c, OUT_DEFAULT_PRECIS, \
- CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg.font_quality), \
- FIXED_PITCH | FF_DONTCARE, cfg.font.name)
+ CLIP_DEFAULT_PRECIS, quality, \
+ FIXED_PITCH | FF_DONTCARE, font->name)
- f(FONT_NORMAL, cfg.font.charset, fw_dontcare, FALSE);
+ f(FONT_NORMAL, font->charset, fw_dontcare, FALSE);
SelectObject(hdc, fonts[FONT_NORMAL]);
GetTextMetrics(hdc, &tm);
ucsdata.dbcs_screenfont = (cpinfo.MaxCharSize > 1);
}
- f(FONT_UNDERLINE, cfg.font.charset, fw_dontcare, TRUE);
+ f(FONT_UNDERLINE, font->charset, fw_dontcare, TRUE);
/*
* Some fonts, e.g. 9-pt Courier, draw their underlines
}
if (bold_mode == BOLD_FONT) {
- f(FONT_BOLD, cfg.font.charset, fw_bold, FALSE);
+ f(FONT_BOLD, font->charset, fw_bold, FALSE);
}
#undef f
}
fontflag[0] = fontflag[1] = fontflag[2] = 1;
- init_ucs(&cfg, &ucsdata);
+ init_ucs(conf, &ucsdata);
}
static void another_font(int fontno)
{
int basefont;
- int fw_dontcare, fw_bold;
+ int fw_dontcare, fw_bold, quality;
int c, u, w, x;
char *s;
+ FontSpec *font;
if (fontno < 0 || fontno >= FONT_MAXNO || fontflag[fontno])
return;
if (basefont != fontno && !fontflag[basefont])
another_font(basefont);
- if (cfg.font.isbold) {
+ font = conf_get_fontspec(conf, CONF_font);
+
+ if (font->isbold) {
fw_dontcare = FW_BOLD;
fw_bold = FW_HEAVY;
} else {
fw_bold = FW_BOLD;
}
- c = cfg.font.charset;
+ c = font->charset;
w = fw_dontcare;
u = FALSE;
- s = cfg.font.name;
+ s = font->name;
x = font_width;
if (fontno & FONT_WIDE)
if (fontno & FONT_UNDERLINE)
u = TRUE;
+ quality = conf_get_int(conf, CONF_font_quality);
+
fonts[fontno] =
CreateFont(font_height * (1 + !!(fontno & FONT_HIGH)), x, 0, 0, w,
FALSE, u, FALSE, c, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg.font_quality),
+ CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality),
DEFAULT_PITCH | FF_DONTCARE, s);
fontflag[fontno] = 1;
/* If the window is maximized supress resizing attempts */
if (IsZoomed(hwnd)) {
- if (cfg.resize_action == RESIZE_TERM)
+ if (conf_get_int(conf, CONF_resize_action) == RESIZE_TERM)
return;
}
- if (cfg.resize_action == RESIZE_DISABLED) return;
+ if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED) return;
if (h == term->rows && w == term->cols) return;
/* Sanity checks ... */
}
}
- term_size(term, h, w, cfg.savelines);
+ term_size(term, h, w, conf_get_int(conf, CONF_savelines));
- if (cfg.resize_action != RESIZE_FONT && !IsZoomed(hwnd)) {
+ if (conf_get_int(conf, CONF_resize_action) != RESIZE_FONT &&
+ !IsZoomed(hwnd)) {
width = extra_width + font_width * w;
height = extra_height + font_height * h;
* This function doesn't like to change the terminal size but if the
* font size is locked that may be it's only soluion.
*/
- int win_width, win_height;
+ int win_width, win_height, resize_action, window_border;
RECT cr, wr;
#ifdef RDB_DEBUG_PATCH
win_width = cr.right - cr.left;
win_height = cr.bottom - cr.top;
- if (cfg.resize_action == RESIZE_DISABLED) reinit = 2;
+ resize_action = conf_get_int(conf, CONF_resize_action);
+ window_border = conf_get_int(conf, CONF_window_border);
+
+ if (resize_action == RESIZE_DISABLED)
+ reinit = 2;
/* Are we being forced to reload the fonts ? */
if (reinit>1) {
extra_width = wr.right - wr.left - cr.right + cr.left;
extra_height = wr.bottom - wr.top - cr.bottom + cr.top;
- if (cfg.resize_action != RESIZE_TERM) {
- if ( font_width != win_width/term->cols ||
- font_height != win_height/term->rows) {
+ if (resize_action != RESIZE_TERM) {
+ if (font_width != win_width/term->cols ||
+ font_height != win_height/term->rows) {
deinit_fonts();
init_fonts(win_width/term->cols, win_height/term->rows);
offset_width = (win_width-font_width*term->cols)/2;
#endif
}
} else {
- if ( font_width * term->cols != win_width ||
- font_height * term->rows != win_height) {
+ if (font_width * term->cols != win_width ||
+ font_height * term->rows != win_height) {
/* Our only choice at this point is to change the
* size of the terminal; Oh well.
*/
term_size(term, win_height/font_height, win_width/font_width,
- cfg.savelines);
+ conf_get_int(conf, CONF_savelines));
offset_width = (win_width-font_width*term->cols)/2;
offset_height = (win_height-font_height*term->rows)/2;
InvalidateRect(hwnd, NULL, TRUE);
debug((27, "reset_window() -> Forced re-init"));
#endif
- offset_width = offset_height = cfg.window_border;
+ offset_width = offset_height = window_border;
extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
* window. But that may be too big for the screen which forces us
* to change the terminal.
*/
- if ((cfg.resize_action == RESIZE_TERM && reinit<=0) ||
- (cfg.resize_action == RESIZE_EITHER && reinit<0) ||
+ if ((resize_action == RESIZE_TERM && reinit<=0) ||
+ (resize_action == RESIZE_EITHER && reinit<0) ||
reinit>0) {
- offset_width = offset_height = cfg.window_border;
+ offset_width = offset_height = window_border;
extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
/* Grrr too big */
if ( term->rows > height || term->cols > width ) {
- if (cfg.resize_action == RESIZE_EITHER) {
+ if (resize_action == RESIZE_EITHER) {
/* Make the font the biggest we can */
if (term->cols > width)
font_width = (ss.right - ss.left - extra_width)
} else {
if ( height > term->rows ) height = term->rows;
if ( width > term->cols ) width = term->cols;
- term_size(term, height, width, cfg.savelines);
+ term_size(term, height, width,
+ conf_get_int(conf, CONF_savelines));
#ifdef RDB_DEBUG_PATCH
debug((27, "reset_window() -> term resize to (%d,%d)",
height, width));
/* We're allowed to or must change the font but do we want to ? */
- if (font_width != (win_width-cfg.window_border*2)/term->cols ||
- font_height != (win_height-cfg.window_border*2)/term->rows) {
+ if (font_width != (win_width-window_border*2)/term->cols ||
+ font_height != (win_height-window_border*2)/term->rows) {
deinit_fonts();
- init_fonts((win_width-cfg.window_border*2)/term->cols,
- (win_height-cfg.window_border*2)/term->rows);
+ init_fonts((win_width-window_border*2)/term->cols,
+ (win_height-window_border*2)/term->rows);
offset_width = (win_width-font_width*term->cols)/2;
offset_height = (win_height-font_height*term->rows)/2;
{
int thistime = GetMessageTime();
- if (send_raw_mouse && !(cfg.mouse_override && shift)) {
+ if (send_raw_mouse &&
+ !(shift && conf_get_int(conf, CONF_mouse_override))) {
lastbtn = MBT_NOTHING;
term_mouse(term, b, translate_button(b), MA_CLICK,
x, y, shift, ctrl, alt);
if (button == MBT_LEFT)
return MBT_SELECT;
if (button == MBT_MIDDLE)
- return cfg.mouse_is_xterm == 1 ? MBT_PASTE : MBT_EXTEND;
+ return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ?
+ MBT_PASTE : MBT_EXTEND;
if (button == MBT_RIGHT)
- return cfg.mouse_is_xterm == 1 ? MBT_EXTEND : MBT_PASTE;
+ return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ?
+ MBT_EXTEND : MBT_PASTE;
return 0; /* shouldn't happen */
}
/* NB that the counter in ShowCursor() is also frobbed by
* update_mouse_pointer() */
static int cursor_visible = 1;
- if (!cfg.hide_mouseptr) /* override if this feature disabled */
- show = 1;
+ if (!conf_get_int(conf, CONF_hide_mouseptr))
+ show = 1; /* override if this feature disabled */
if (cursor_visible && !show)
ShowCursor(FALSE);
else if (!cursor_visible && show)
void notify_remote_exit(void *fe)
{
- int exitcode;
+ int exitcode, close_on_exit;
if (!session_closed &&
(exitcode = back->exitcode(backhandle)) >= 0) {
+ close_on_exit = conf_get_int(conf, CONF_close_on_exit);
/* Abnormal exits will already have set session_closed and taken
* appropriate action. */
- if (cfg.close_on_exit == FORCE_ON ||
- (cfg.close_on_exit == AUTO && exitcode != INT_MAX)) {
+ if (close_on_exit == FORCE_ON ||
+ (close_on_exit == AUTO && exitcode != INT_MAX)) {
PostQuitMessage(0);
} else {
must_close_session = TRUE;
timing_next_time = next;
}
+static void conf_cache_data(void)
+{
+ /* Cache some items from conf to speed lookups in very hot code */
+ cursor_type = conf_get_int(conf, CONF_cursor_type);
+ vtmode = conf_get_int(conf, CONF_vtmode);
+}
+
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static int fullscr_on_max = FALSE;
static int processed_resize = FALSE;
static UINT last_mousemove = 0;
+ int resize_action;
switch (message) {
case WM_TIMER:
char *str;
show_mouseptr(1);
str = dupprintf("%s Exit Confirmation", appname);
- if (!cfg.warn_on_close || session_closed ||
+ if (session_closed || !conf_get_int(conf, CONF_warn_on_close) ||
MessageBox(hwnd,
"Are you sure you want to close this session?",
str, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1)
* config structure.
*/
SECURITY_ATTRIBUTES sa;
- Config *p;
+ void *p;
+ int size;
+
+ size = conf_serialised_size(conf);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
filemap = CreateFileMapping(INVALID_HANDLE_VALUE,
&sa,
PAGE_READWRITE,
- 0, sizeof(Config), NULL);
+ 0, size, NULL);
if (filemap && filemap != INVALID_HANDLE_VALUE) {
- p = (Config *) MapViewOfFile(filemap,
- FILE_MAP_WRITE,
- 0, 0, sizeof(Config));
+ p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, size);
if (p) {
- *p = cfg; /* structure copy */
+ conf_serialise(conf, p);
UnmapViewOfFile(p);
}
}
inherit_handles = TRUE;
- sprintf(c, "putty &%p", filemap);
+ sprintf(c, "putty &%p:%u", filemap, (unsigned)size);
cl = c;
} else if (wParam == IDM_SAVEDSESS) {
unsigned int sessno = ((lParam - IDM_SAVED_MIN)
break;
case IDM_RECONF:
{
- Config prev_cfg;
+ Conf *prev_conf;
int init_lvl = 1;
int reconfig_result;
else
reconfiguring = TRUE;
- GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle));
- prev_cfg = cfg;
+ /*
+ * Copy the current window title into the stored
+ * previous configuration, so that doing nothing to
+ * the window title field in the config box doesn't
+ * reset the title to its startup state.
+ */
+ conf_set_str(conf, CONF_wintitle, window_name);
+
+ prev_conf = conf_copy(conf);
reconfig_result =
do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0);
if (!reconfig_result)
break;
+ conf_cache_data();
+
+ resize_action = conf_get_int(conf, CONF_resize_action);
{
/* Disable full-screen if resizing forbidden */
int i;
for (i = 0; i < lenof(popup_menus); i++)
EnableMenuItem(popup_menus[i].menu, IDM_FULLSCREEN,
MF_BYCOMMAND |
- (cfg.resize_action == RESIZE_DISABLED)
+ (resize_action == RESIZE_DISABLED)
? MF_GRAYED : MF_ENABLED);
/* Gracefully unzoom if necessary */
- if (IsZoomed(hwnd) &&
- (cfg.resize_action == RESIZE_DISABLED)) {
+ if (IsZoomed(hwnd) && (resize_action == RESIZE_DISABLED))
ShowWindow(hwnd, SW_RESTORE);
- }
}
/* Pass new config data to the logging module */
- log_reconfig(logctx, &cfg);
+ log_reconfig(logctx, conf);
sfree(logpal);
/*
* Flush the line discipline's edit buffer in the
* case where local editing has just been disabled.
*/
+ ldisc_configure(ldisc, conf);
if (ldisc)
ldisc_send(ldisc, NULL, 0, 0);
if (pal)
DeleteObject(pal);
logpal = NULL;
pal = NULL;
- cfgtopalette();
+ conftopalette();
init_palette();
/* Pass new config data to the terminal */
- term_reconfig(term, &cfg);
+ term_reconfig(term, conf);
/* Pass new config data to the back end */
if (back)
- back->reconfig(backhandle, &cfg);
+ back->reconfig(backhandle, conf);
/* Screen size changed ? */
- if (cfg.height != prev_cfg.height ||
- cfg.width != prev_cfg.width ||
- cfg.savelines != prev_cfg.savelines ||
- cfg.resize_action == RESIZE_FONT ||
- (cfg.resize_action == RESIZE_EITHER && IsZoomed(hwnd)) ||
- cfg.resize_action == RESIZE_DISABLED)
- term_size(term, cfg.height, cfg.width, cfg.savelines);
+ if (conf_get_int(conf, CONF_height) !=
+ conf_get_int(prev_conf, CONF_height) ||
+ conf_get_int(conf, CONF_width) !=
+ conf_get_int(prev_conf, CONF_width) ||
+ conf_get_int(conf, CONF_savelines) !=
+ conf_get_int(prev_conf, CONF_savelines) ||
+ resize_action == RESIZE_FONT ||
+ (resize_action == RESIZE_EITHER && IsZoomed(hwnd)) ||
+ resize_action == RESIZE_DISABLED)
+ term_size(term, conf_get_int(conf, CONF_height),
+ conf_get_int(conf, CONF_width),
+ conf_get_int(conf, CONF_savelines));
/* Enable or disable the scroll bar, etc */
{
GetWindowLongPtr(hwnd, GWL_EXSTYLE);
nexflag = exflag;
- if (cfg.alwaysontop != prev_cfg.alwaysontop) {
- if (cfg.alwaysontop) {
+ if (conf_get_int(conf, CONF_alwaysontop) !=
+ conf_get_int(prev_conf, CONF_alwaysontop)) {
+ if (conf_get_int(conf, CONF_alwaysontop)) {
nexflag |= WS_EX_TOPMOST;
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE);
SWP_NOMOVE | SWP_NOSIZE);
}
}
- if (cfg.sunken_edge)
+ if (conf_get_int(conf, CONF_sunken_edge))
nexflag |= WS_EX_CLIENTEDGE;
else
nexflag &= ~(WS_EX_CLIENTEDGE);
nflg = flag;
- if (is_full_screen() ?
- cfg.scrollbar_in_fullscreen : cfg.scrollbar)
+ if (conf_get_int(conf, is_full_screen() ?
+ CONF_scrollbar_in_fullscreen :
+ CONF_scrollbar))
nflg |= WS_VSCROLL;
else
nflg &= ~WS_VSCROLL;
- if (cfg.resize_action == RESIZE_DISABLED ||
+ if (resize_action == RESIZE_DISABLED ||
is_full_screen())
nflg &= ~WS_THICKFRAME;
else
nflg |= WS_THICKFRAME;
- if (cfg.resize_action == RESIZE_DISABLED)
+ if (resize_action == RESIZE_DISABLED)
nflg &= ~WS_MAXIMIZEBOX;
else
nflg |= WS_MAXIMIZEBOX;
}
/* Oops */
- if (cfg.resize_action == RESIZE_DISABLED && IsZoomed(hwnd)) {
+ if (resize_action == RESIZE_DISABLED && IsZoomed(hwnd)) {
force_normal(hwnd);
init_lvl = 2;
}
- set_title(NULL, cfg.wintitle);
+ set_title(NULL, conf_get_str(conf, CONF_wintitle));
if (IsIconic(hwnd)) {
SetWindowText(hwnd,
- cfg.win_name_always ? window_name :
- icon_name);
+ conf_get_int(conf, CONF_win_name_always) ?
+ window_name : icon_name);
}
- if (strcmp(cfg.font.name, prev_cfg.font.name) != 0 ||
- strcmp(cfg.line_codepage, prev_cfg.line_codepage) != 0 ||
- cfg.font.isbold != prev_cfg.font.isbold ||
- cfg.font.height != prev_cfg.font.height ||
- cfg.font.charset != prev_cfg.font.charset ||
- cfg.font_quality != prev_cfg.font_quality ||
- cfg.vtmode != prev_cfg.vtmode ||
- cfg.bold_colour != prev_cfg.bold_colour ||
- cfg.resize_action == RESIZE_DISABLED ||
- cfg.resize_action == RESIZE_EITHER ||
- (cfg.resize_action != prev_cfg.resize_action))
- init_lvl = 2;
+ {
+ FontSpec *font = conf_get_fontspec(conf, CONF_font);
+ FontSpec *prev_font = conf_get_fontspec(prev_conf,
+ CONF_font);
+
+ if (!strcmp(font->name, prev_font->name) ||
+ !strcmp(conf_get_str(conf, CONF_line_codepage),
+ conf_get_str(prev_conf, CONF_line_codepage)) ||
+ font->isbold != prev_font->isbold ||
+ font->height != prev_font->height ||
+ font->charset != prev_font->charset ||
+ conf_get_int(conf, CONF_font_quality) !=
+ conf_get_int(prev_conf, CONF_font_quality) ||
+ conf_get_int(conf, CONF_vtmode) !=
+ conf_get_int(prev_conf, CONF_vtmode) ||
+ conf_get_int(conf, CONF_bold_colour) !=
+ conf_get_int(prev_conf, CONF_bold_colour) ||
+ resize_action == RESIZE_DISABLED ||
+ resize_action == RESIZE_EITHER ||
+ resize_action != conf_get_int(prev_conf,
+ CONF_resize_action))
+ init_lvl = 2;
+ }
InvalidateRect(hwnd, NULL, TRUE);
reset_window(init_lvl);
net_pending_errors();
+
+ conf_free(prev_conf);
}
break;
case IDM_COPYALL:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
if (message == WM_RBUTTONDOWN &&
- ((wParam & MK_CONTROL) || (cfg.mouse_is_xterm == 2))) {
+ ((wParam & MK_CONTROL) ||
+ (conf_get_int(conf, CONF_mouse_is_xterm) == 2))) {
POINT cursorpos;
show_mouseptr(1); /* make sure pointer is visible */
debug((27, "WM_EXITSIZEMOVE"));
#endif
if (need_backend_resize) {
- term_size(term, cfg.height, cfg.width, cfg.savelines);
+ term_size(term, conf_get_int(conf, CONF_height),
+ conf_get_int(conf, CONF_width),
+ conf_get_int(conf, CONF_savelines));
InvalidateRect(hwnd, NULL, TRUE);
}
break;
* 1) Keep the sizetip uptodate
* 2) Make sure the window size is _stepped_ in units of the font size.
*/
- if (cfg.resize_action == RESIZE_TERM ||
- (cfg.resize_action == RESIZE_EITHER && !is_alt_pressed())) {
+ resize_action = conf_get_int(conf, CONF_resize_action);
+ if (resize_action == RESIZE_TERM ||
+ (resize_action == RESIZE_EITHER && !is_alt_pressed())) {
int width, height, w, h, ew, eh;
LPRECT r = (LPRECT) lParam;
- if ( !need_backend_resize && cfg.resize_action == RESIZE_EITHER &&
- (cfg.height != term->rows || cfg.width != term->cols )) {
+ if (!need_backend_resize && resize_action == RESIZE_EITHER &&
+ (conf_get_int(conf, CONF_height) != term->rows ||
+ conf_get_int(conf, CONF_width) != term->cols)) {
/*
* Great! It seems that both the terminal size and the
* font size have been changed and the user is now dragging.
* font size!
*
* This would be easier but it seems to be too confusing.
-
- term_size(term, cfg.height, cfg.width, cfg.savelines);
- reset_window(2);
*/
- cfg.height=term->rows; cfg.width=term->cols;
+ conf_set_int(conf, CONF_height, term->rows);
+ conf_set_int(conf, CONF_width, term->cols);
InvalidateRect(hwnd, NULL, TRUE);
need_backend_resize = TRUE;
return 0;
} else {
int width, height, w, h, rv = 0;
- int ex_width = extra_width + (cfg.window_border - offset_width) * 2;
- int ex_height = extra_height + (cfg.window_border - offset_height) * 2;
+ int window_border = conf_get_int(conf, CONF_window_border);
+ int ex_width = extra_width + (window_border - offset_width) * 2;
+ int ex_height = extra_height + (window_border - offset_height) * 2;
LPRECT r = (LPRECT) lParam;
width = r->right - r->left - ex_width;
sys_cursor_update();
break;
case WM_SIZE:
+ resize_action = conf_get_int(conf, CONF_resize_action);
#ifdef RDB_DEBUG_PATCH
debug((27, "WM_SIZE %s (%d,%d)",
(wParam == SIZE_MINIMIZED) ? "SIZE_MINIMIZED":
#endif
if (wParam == SIZE_MINIMIZED)
SetWindowText(hwnd,
- cfg.win_name_always ? window_name : icon_name);
+ conf_get_int(conf, CONF_win_name_always) ?
+ window_name : icon_name);
if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
SetWindowText(hwnd, window_name);
if (wParam == SIZE_RESTORED) {
processed_resize = TRUE;
- if (cfg.resize_action == RESIZE_DISABLED) {
+ if (resize_action == RESIZE_DISABLED) {
/* A resize, well it better be a minimize. */
reset_window(-1);
} else {
int width, height, w, h;
+ int window_border = conf_get_int(conf, CONF_window_border);
width = LOWORD(lParam);
height = HIWORD(lParam);
was_zoomed = 1;
prev_rows = term->rows;
prev_cols = term->cols;
- if (cfg.resize_action == RESIZE_TERM) {
+ if (resize_action == RESIZE_TERM) {
w = width / font_width;
if (w < 1) w = 1;
h = height / font_height;
if (h < 1) h = 1;
- term_size(term, h, w, cfg.savelines);
+ term_size(term, h, w, conf_get_int(conf, CONF_savelines));
}
reset_window(0);
} else if (wParam == SIZE_RESTORED && was_zoomed) {
was_zoomed = 0;
- if (cfg.resize_action == RESIZE_TERM) {
- w = (width-cfg.window_border*2) / font_width;
+ if (resize_action == RESIZE_TERM) {
+ w = (width-window_border*2) / font_width;
if (w < 1) w = 1;
- h = (height-cfg.window_border*2) / font_height;
+ h = (height-window_border*2) / font_height;
if (h < 1) h = 1;
- term_size(term, h, w, cfg.savelines);
+ term_size(term, h, w, conf_get_int(conf, CONF_savelines));
reset_window(2);
- } else if (cfg.resize_action != RESIZE_FONT)
+ } else if (resize_action != RESIZE_FONT)
reset_window(2);
else
reset_window(0);
} else if (wParam == SIZE_MINIMIZED) {
/* do nothing */
- } else if (cfg.resize_action == RESIZE_TERM ||
- (cfg.resize_action == RESIZE_EITHER &&
+ } else if (resize_action == RESIZE_TERM ||
+ (resize_action == RESIZE_EITHER &&
!is_alt_pressed())) {
- w = (width-cfg.window_border*2) / font_width;
+ w = (width-window_border*2) / font_width;
if (w < 1) w = 1;
- h = (height-cfg.window_border*2) / font_height;
+ h = (height-window_border*2) / font_height;
if (h < 1) h = 1;
if (resizing) {
* opaque drag.)
*/
need_backend_resize = TRUE;
- cfg.height = h;
- cfg.width = w;
+ conf_set_int(conf, CONF_height, h);
+ conf_set_int(conf, CONF_height, w);
} else {
- term_size(term, h, w, cfg.savelines);
+ term_size(term, h, w, conf_get_int(conf, CONF_savelines));
}
} else {
reset_window(0);
}
return 0;
case WM_SYSCOLORCHANGE:
- if (cfg.system_colour) {
+ if (conf_get_int(conf, CONF_system_colour)) {
/* Refresh palette from system colours. */
/* XXX actually this zaps the entire palette. */
systopalette();
} else
break;
- if (send_raw_mouse &&
- !(cfg.mouse_override && shift_pressed)) {
+ if (send_raw_mouse && shift_pressed &&
+ !(conf_get_int(conf, CONF_mouse_override))) {
/* Mouse wheel position is in screen coordinates for
* some reason */
POINT p;
x += offset_width;
y += offset_height;
- if ((attr & TATTR_ACTCURS) && (cfg.cursor_type == 0 || term->big_cursor)) {
+ if ((attr & TATTR_ACTCURS) && (cursor_type == 0 || term->big_cursor)) {
attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS);
if (bold_mode == BOLD_COLOURS)
attr &= ~ATTR_BOLD;
}
nfont = 0;
- if (cfg.vtmode == VT_POORMAN && lattr != LATTR_NORM) {
+ if (vtmode == VT_POORMAN && lattr != LATTR_NORM) {
/* Assume a poorman font is borken in other ways too. */
lattr = LATTR_WIDE;
} else
int fnt_width;
int char_width;
HDC hdc = ctx;
- int ctype = cfg.cursor_type;
+ int ctype = cursor_type;
lattr &= LATTR_MODE;
int r, i, code;
unsigned char *p = output;
static int alt_sum = 0;
+ int funky_type = conf_get_int(conf, CONF_funky_type);
+ int no_applic_k = conf_get_int(conf, CONF_no_applic_k);
+ int ctrlaltkeys = conf_get_int(conf, CONF_ctrlaltkeys);
+ int nethack_keypad = conf_get_int(conf, CONF_nethack_keypad);
HKL kbd_layout = GetKeyboardLayout(0);
/* keys is for ToAsciiEx. There's some ick here, see below. */
static WORD keys[3];
static int compose_char = 0;
- static WPARAM compose_key = 0;
+ static WPARAM compose_keycode = 0;
r = GetKeyboardState(keystate);
if (!r)
/* Nastyness with NUMLock - Shift-NUMLock is left alone though */
- if ((cfg.funky_type == FUNKY_VT400 ||
- (cfg.funky_type <= FUNKY_LINUX && term->app_keypad_keys &&
- !cfg.no_applic_k))
+ if ((funky_type == FUNKY_VT400 ||
+ (funky_type <= FUNKY_LINUX && term->app_keypad_keys &&
+ !no_applic_k))
&& wParam == VK_NUMLOCK && !(keystate[VK_SHIFT] & 0x80)) {
wParam = VK_EXECUTE;
/* Make sure Ctrl-ALT is not the same as AltGr for ToAscii unless told. */
if (left_alt && (keystate[VK_CONTROL] & 0x80)) {
- if (cfg.ctrlaltkeys)
+ if (ctrlaltkeys)
keystate[VK_MENU] = 0;
else {
keystate[VK_RMENU] = 0x80;
/* Note if AltGr was pressed and if it was used as a compose key */
if (!compose_state) {
- compose_key = 0x100;
- if (cfg.compose_key) {
+ compose_keycode = 0x100;
+ if (conf_get_int(conf, CONF_compose_key)) {
if (wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED))
- compose_key = wParam;
+ compose_keycode = wParam;
}
if (wParam == VK_APPS)
- compose_key = wParam;
+ compose_keycode = wParam;
}
- if (wParam == compose_key) {
+ if (wParam == compose_keycode) {
if (compose_state == 0
&& (HIWORD(lParam) & (KF_UP | KF_REPEAT)) == 0) compose_state =
1;
compose_state = 0;
/* Sanitize the number pad if not using a PC NumPad */
- if (left_alt || (term->app_keypad_keys && !cfg.no_applic_k
- && cfg.funky_type != FUNKY_XTERM)
- || cfg.funky_type == FUNKY_VT400 || cfg.nethack_keypad || compose_state) {
+ if (left_alt || (term->app_keypad_keys && !no_applic_k
+ && funky_type != FUNKY_XTERM)
+ || funky_type == FUNKY_VT400 || nethack_keypad || compose_state) {
if ((HIWORD(lParam) & KF_EXTENDED) == 0) {
int nParam = 0;
switch (wParam) {
request_paste(NULL);
return 0;
}
- if (left_alt && wParam == VK_F4 && cfg.alt_f4) {
+ if (left_alt && wParam == VK_F4 && conf_get_int(conf, CONF_alt_f4)) {
return -1;
}
- if (left_alt && wParam == VK_SPACE && cfg.alt_space) {
+ if (left_alt && wParam == VK_SPACE && conf_get_int(conf,
+ CONF_alt_space)) {
SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
return -1;
}
- if (left_alt && wParam == VK_RETURN && cfg.fullscreenonaltenter &&
- (cfg.resize_action != RESIZE_DISABLED)) {
+ if (left_alt && wParam == VK_RETURN &&
+ conf_get_int(conf, CONF_fullscreenonaltenter) &&
+ (conf_get_int(conf, CONF_resize_action) != RESIZE_DISABLED)) {
if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
flip_full_screen();
return -1;
}
/* Nethack keypad */
- if (cfg.nethack_keypad && !left_alt) {
+ if (nethack_keypad && !left_alt) {
switch (wParam) {
case VK_NUMPAD1:
*p++ = "bB\002\002"[shift_state & 3];
if (!left_alt) {
int xkey = 0;
- if (cfg.funky_type == FUNKY_VT400 ||
- (cfg.funky_type <= FUNKY_LINUX &&
- term->app_keypad_keys && !cfg.no_applic_k)) switch (wParam) {
+ if (funky_type == FUNKY_VT400 ||
+ (funky_type <= FUNKY_LINUX &&
+ term->app_keypad_keys && !no_applic_k)) switch (wParam) {
case VK_EXECUTE:
xkey = 'P';
break;
xkey = 'S';
break;
}
- if (term->app_keypad_keys && !cfg.no_applic_k)
+ if (term->app_keypad_keys && !no_applic_k)
switch (wParam) {
case VK_NUMPAD0:
xkey = 'p';
xkey = 'n';
break;
case VK_ADD:
- if (cfg.funky_type == FUNKY_XTERM) {
+ if (funky_type == FUNKY_XTERM) {
if (shift_state)
xkey = 'l';
else
break;
case VK_DIVIDE:
- if (cfg.funky_type == FUNKY_XTERM)
+ if (funky_type == FUNKY_XTERM)
xkey = 'o';
break;
case VK_MULTIPLY:
- if (cfg.funky_type == FUNKY_XTERM)
+ if (funky_type == FUNKY_XTERM)
xkey = 'j';
break;
case VK_SUBTRACT:
- if (cfg.funky_type == FUNKY_XTERM)
+ if (funky_type == FUNKY_XTERM)
xkey = 'm';
break;
}
if (wParam == VK_BACK && shift_state == 0) { /* Backspace */
- *p++ = (cfg.bksp_is_delete ? 0x7F : 0x08);
+ *p++ = (conf_get_int(conf, CONF_bksp_is_delete) ? 0x7F : 0x08);
*p++ = 0;
return -2;
}
if (wParam == VK_BACK && shift_state == 1) { /* Shift Backspace */
/* We do the opposite of what is configured */
- *p++ = (cfg.bksp_is_delete ? 0x08 : 0x7F);
+ *p++ = (conf_get_int(conf, CONF_bksp_is_delete) ? 0x08 : 0x7F);
*p++ = 0;
return -2;
}
break;
}
/* Reorder edit keys to physical order */
- if (cfg.funky_type == FUNKY_VT400 && code <= 6)
+ if (funky_type == FUNKY_VT400 && code <= 6)
code = "\0\2\1\4\5\3\6"[code];
if (term->vt52_mode && code > 0 && code <= 6) {
return p - output;
}
- if (cfg.funky_type == FUNKY_SCO && /* SCO function keys */
- code >= 11 && code <= 34) {
+ if (funky_type == FUNKY_SCO && code >= 11 && code <= 34) {
+ /* SCO function keys */
char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
int index = 0;
switch (wParam) {
p += sprintf((char *) p, "\x1B[%c", codes[index]);
return p - output;
}
- if (cfg.funky_type == FUNKY_SCO && /* SCO small keypad */
+ if (funky_type == FUNKY_SCO && /* SCO small keypad */
code >= 1 && code <= 6) {
char codes[] = "HL.FIG";
if (code == 3) {
}
return p - output;
}
- if ((term->vt52_mode || cfg.funky_type == FUNKY_VT100P) && code >= 11 && code <= 24) {
+ if ((term->vt52_mode || funky_type == FUNKY_VT100P) && code >= 11 && code <= 24) {
int offt = 0;
if (code > 15)
offt++;
sprintf((char *) p, "\x1BO%c", code + 'P' - 11 - offt);
return p - output;
}
- if (cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
+ if (funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
p += sprintf((char *) p, "\x1B[[%c", code + 'A' - 11);
return p - output;
}
- if (cfg.funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
+ if (funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
if (term->vt52_mode)
p += sprintf((char *) p, "\x1B%c", code + 'P' - 11);
else
p += sprintf((char *) p, "\x1BO%c", code + 'P' - 11);
return p - output;
}
- if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
+ if ((code == 1 || code == 4) &&
+ conf_get_int(conf, CONF_rxvt_homeend)) {
p += sprintf((char *) p, code == 1 ? "\x1B[H" : "\x1BOw");
return p - output;
}
BOOL capsOn=0;
/* helg: clear CAPS LOCK state if caps lock switches to cyrillic */
- if(cfg.xlat_capslockcyr && keystate[VK_CAPITAL] != 0) {
+ if(keystate[VK_CAPITAL] != 0 &&
+ conf_get_int(conf, CONF_xlat_capslockcyr)) {
capsOn= !left_alt;
keystate[VK_CAPITAL] = 0;
}
* we return -1, which means Windows will give the keystroke
* its default handling (i.e. bring up the System menu).
*/
- if (wParam == VK_MENU && !cfg.alt_only)
+ if (wParam == VK_MENU && !conf_get_int(conf, CONF_alt_only))
return 0;
return -1;
sfree(window_name);
window_name = snewn(1 + strlen(title), char);
strcpy(window_name, title);
- if (cfg.win_name_always || !IsIconic(hwnd))
+ if (conf_get_int(conf, CONF_win_name_always) || !IsIconic(hwnd))
SetWindowText(hwnd, title);
}
sfree(icon_name);
icon_name = snewn(1 + strlen(title), char);
strcpy(icon_name, title);
- if (!cfg.win_name_always && IsIconic(hwnd))
+ if (!conf_get_int(conf, CONF_win_name_always) && IsIconic(hwnd))
SetWindowText(hwnd, title);
}
{
SCROLLINFO si;
- if (is_full_screen() ? !cfg.scrollbar_in_fullscreen : !cfg.scrollbar)
+ if (!conf_get_int(conf, is_full_screen() ?
+ CONF_scrollbar_in_fullscreen : CONF_scrollbar))
return;
si.cbSize = sizeof(si);
memcpy(lock, data, len * sizeof(wchar_t));
WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL);
- if (cfg.rtf_paste) {
+ if (conf_get_int(conf, CONF_rtf_paste)) {
wchar_t unitab[256];
char *rtf = NULL;
unsigned char *tdata = (unsigned char *)lock2;
int attrUnder, lastAttrUnder = 0;
int palette[NALLCOLOURS];
int numcolours;
+ FontSpec *font = conf_get_fontspec(conf, CONF_font);
get_unitab(CP_ACP, unitab, 0);
- rtfsize = 100 + strlen(cfg.font.name);
+ rtfsize = 100 + strlen(font->name);
rtf = snewn(rtfsize, char);
rtflen = sprintf(rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d",
- cfg.font.name, cfg.font.height*2);
+ font->name, font->height*2);
/*
* Add colour palette
*/
static void flash_window(int mode)
{
- if ((mode == 0) || (cfg.beep_ind == B_IND_DISABLED)) {
+ int beep_ind = conf_get_int(conf, CONF_beep_ind);
+ if ((mode == 0) || (beep_ind == B_IND_DISABLED)) {
/* stop */
if (flashing) {
flashing = 0;
* "flashing" mode, although I haven't seen this
* documented. */
flash_window_ex(FLASHW_ALL | FLASHW_TIMER,
- (cfg.beep_ind == B_IND_FLASH ? 0 : 2),
+ (beep_ind == B_IND_FLASH ? 0 : 2),
0 /* system cursor blink rate */);
/* No need to schedule timer */
} else {
}
}
- } else if ((mode == 1) && (cfg.beep_ind == B_IND_FLASH)) {
+ } else if ((mode == 1) && (beep_ind == B_IND_FLASH)) {
/* maintain */
if (flashing && !p_FlashWindowEx) {
FlashWindow(hwnd, TRUE); /* toggle */
*/
lastbeep = GetTickCount();
} else if (mode == BELL_WAVEFILE) {
- if (!PlaySound(cfg.bell_wavefile.path, NULL,
+ Filename *bell_wavefile = conf_get_filename(conf, CONF_bell_wavefile);
+ if (!PlaySound(bell_wavefile->path, NULL,
SND_ASYNC | SND_FILENAME)) {
- char buf[sizeof(cfg.bell_wavefile.path) + 80];
+ char buf[sizeof(bell_wavefile->path) + 80];
char otherbuf[100];
sprintf(buf, "Unable to play sound file\n%s\n"
- "Using default sound instead", cfg.bell_wavefile.path);
+ "Using default sound instead", bell_wavefile->path);
sprintf(otherbuf, "%.70s Sound Error", appname);
MessageBox(hwnd, buf, otherbuf,
MB_OK | MB_ICONEXCLAMATION);
- cfg.beep = BELL_DEFAULT;
+ conf_set_int(conf, CONF_beep, BELL_DEFAULT);
}
} else if (mode == BELL_PCSPEAKER) {
static long lastbeep = 0;
*/
void move_window(void *frontend, int x, int y)
{
- if (cfg.resize_action == RESIZE_DISABLED ||
- cfg.resize_action == RESIZE_FONT ||
+ int resize_action = conf_get_int(conf, CONF_resize_action);
+ if (resize_action == RESIZE_DISABLED ||
+ resize_action == RESIZE_FONT ||
IsZoomed(hwnd))
return;
*/
void set_zorder(void *frontend, int top)
{
- if (cfg.alwaysontop)
+ if (conf_get_int(conf, CONF_alwaysontop))
return; /* ignore */
SetWindowPos(hwnd, top ? HWND_TOP : HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE);
/* Remove the window furniture. */
style = GetWindowLongPtr(hwnd, GWL_STYLE);
style &= ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME);
- if (cfg.scrollbar_in_fullscreen)
+ if (conf_get_int(conf, CONF_scrollbar_in_fullscreen))
style |= WS_VSCROLL;
else
style &= ~WS_VSCROLL;
/* Reinstate the window furniture. */
style = oldstyle = GetWindowLongPtr(hwnd, GWL_STYLE);
style |= WS_CAPTION | WS_BORDER;
- if (cfg.resize_action == RESIZE_DISABLED)
+ if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED)
style &= ~WS_THICKFRAME;
else
style |= WS_THICKFRAME;
- if (cfg.scrollbar)
+ if (conf_get_int(conf, CONF_scrollbar))
style |= WS_VSCROLL;
else
style &= ~WS_VSCROLL;
static void ssh_sspi_bind_fns(struct ssh_gss_library *lib);
-struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
{
HMODULE module;
HKEY regkey;
struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist);
+ char *path;
list->libraries = snewn(3, struct ssh_gss_library);
list->nlibraries = 0;
* Custom GSSAPI DLL.
*/
module = NULL;
- if (cfg->ssh_gss_custom.path[0]) {
- module = LoadLibrary(cfg->ssh_gss_custom.path);
+ path = conf_get_filename(conf, CONF_ssh_gss_custom)->path;
+ if (*path) {
+ module = LoadLibrary(path);
}
if (module) {
struct ssh_gss_library *lib =
lib->id = 2;
lib->gsslogmsg = dupprintf("Using GSSAPI from user-specified"
- " library '%s'", cfg->ssh_gss_custom.path);
+ " library '%s'", path);
lib->handle = (void *)module;
#define BIND_GSS_FN(name) \
static Backend *back;
static void *backhandle;
-static Config cfg;
+static Conf *conf;
int term_ldisc(Terminal *term, int mode)
{
/*
* Process the command line.
*/
- do_defaults(NULL, &cfg);
+ conf = conf_new();
+ do_defaults(NULL, conf);
loaded_session = FALSE;
- default_protocol = cfg.protocol;
- default_port = cfg.port;
+ default_protocol = conf_get_int(conf, CONF_protocol);
+ default_port = conf_get_int(conf, CONF_port);
errors = 0;
{
/*
if (p) {
const Backend *b = backend_from_name(p);
if (b) {
- default_protocol = cfg.protocol = b->protocol;
- default_port = cfg.port = b->default_port;
+ default_protocol = b->protocol;
+ default_port = b->default_port;
+ conf_set_int(conf, CONF_protocol, default_protocol);
+ conf_set_int(conf, CONF_port, default_port);
}
}
}
char *p = *++argv;
if (*p == '-') {
int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
- 1, &cfg);
+ 1, conf);
if (ret == -2) {
fprintf(stderr,
"plink: option \"%s\" requires an argument\n", p);
} else if (!strcmp(p, "-batch")) {
console_batch_mode = 1;
} else if (!strcmp(p, "-s")) {
- /* Save status to write to cfg later. */
+ /* Save status to write to conf later. */
use_subsystem = 1;
} else if (!strcmp(p, "-V")) {
version();
errors = 1;
}
} else if (*p) {
- if (!cfg_launchable(&cfg) || !(got_host || loaded_session)) {
+ if (!conf_launchable(conf) || !(got_host || loaded_session)) {
char *q = p;
/*
* If the hostname starts with "telnet:", set the
q += 7;
if (q[0] == '/' && q[1] == '/')
q += 2;
- cfg.protocol = PROT_TELNET;
+ conf_set_int(conf, CONF_protocol, PROT_TELNET);
p = q;
while (*p && *p != ':' && *p != '/')
p++;
if (*p)
*p++ = '\0';
if (c == ':')
- cfg.port = atoi(p);
+ conf_set_int(conf, CONF_port, atoi(p));
else
- cfg.port = -1;
- strncpy(cfg.host, q, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
+ conf_set_int(conf, CONF_port, -1);
+ conf_set_str(conf, CONF_host, q);
got_host = TRUE;
} else {
char *r, *user, *host;
*r = '\0';
b = backend_from_name(p);
if (b) {
- default_protocol = cfg.protocol = b->protocol;
+ default_protocol = b->protocol;
+ conf_set_int(conf, CONF_protocol,
+ default_protocol);
portnumber = b->default_port;
}
p = r + 1;
* same name as the hostname.
*/
{
- Config cfg2;
- do_defaults(host, &cfg2);
- if (loaded_session || !cfg_launchable(&cfg2)) {
+ Conf *conf2 = conf_new();
+ do_defaults(host, conf2);
+ if (loaded_session || !conf_launchable(conf2)) {
/* No settings for this host; use defaults */
/* (or session was already loaded with -load) */
- strncpy(cfg.host, host, sizeof(cfg.host) - 1);
- cfg.host[sizeof(cfg.host) - 1] = '\0';
- cfg.port = default_port;
+ conf_set_str(conf, CONF_host, host);
+ conf_set_int(conf, CONF_port, default_port);
got_host = TRUE;
} else {
- cfg = cfg2;
+ conf_copy_into(conf, conf2);
loaded_session = TRUE;
}
+ conf_free(conf2);
}
if (user) {
/* Patch in specified username. */
- strncpy(cfg.username, user,
- sizeof(cfg.username) - 1);
- cfg.username[sizeof(cfg.username) - 1] = '\0';
+ conf_set_str(conf, CONF_username, user);
}
}
}
if (cmdlen) command[--cmdlen]='\0';
/* change trailing blank to NUL */
- cfg.remote_cmd_ptr = command;
- cfg.remote_cmd_ptr2 = NULL;
- cfg.nopty = TRUE; /* command => no terminal */
+ conf_set_str(conf, CONF_remote_cmd, command);
+ conf_set_str(conf, CONF_remote_cmd2, "");
+ conf_set_int(conf, CONF_nopty, TRUE); /* command => no tty */
break; /* done with cmdline */
}
if (errors)
return 1;
- if (!cfg_launchable(&cfg) || !(got_host || loaded_session)) {
+ if (!conf_launchable(conf) || !(got_host || loaded_session)) {
usage();
}
/*
- * Trim leading whitespace off the hostname if it's there.
+ * Muck about with the hostname in various ways.
*/
{
- int space = strspn(cfg.host, " \t");
- memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
- }
+ char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
+ char *host = hostbuf;
+ char *p, *q;
+
+ /*
+ * Trim leading whitespace.
+ */
+ host += strspn(host, " \t");
- /* See if host is of the form user@host */
- if (cfg_launchable(&cfg)) {
- char *atsign = strrchr(cfg.host, '@');
- /* Make sure we're not overflowing the user field */
- if (atsign) {
- if (atsign - cfg.host < sizeof cfg.username) {
- strncpy(cfg.username, cfg.host, atsign - cfg.host);
- cfg.username[atsign - cfg.host] = '\0';
+ /*
+ * See if host is of the form user@host, and separate out
+ * the username if so.
+ */
+ if (host[0] != '\0') {
+ char *atsign = strrchr(host, '@');
+ if (atsign) {
+ *atsign = '\0';
+ conf_set_str(conf, CONF_username, host);
+ host = atsign + 1;
}
- memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
+
+ /*
+ * Trim off a colon suffix if it's there.
+ */
+ host[strcspn(host, ":")] = '\0';
+
+ /*
+ * Remove any remaining whitespace.
+ */
+ p = hostbuf;
+ q = host;
+ while (*q) {
+ if (*q != ' ' && *q != '\t')
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+
+ conf_set_str(conf, CONF_host, hostbuf);
+ sfree(hostbuf);
}
/*
* Perform command-line overrides on session configuration.
*/
- cmdline_run_saved(&cfg);
+ cmdline_run_saved(conf);
/*
* Apply subsystem status.
*/
if (use_subsystem)
- cfg.ssh_subsys = TRUE;
-
- /*
- * Trim a colon suffix off the hostname if it's there.
- */
- cfg.host[strcspn(cfg.host, ":")] = '\0';
-
- /*
- * Remove any remaining whitespace from the hostname.
- */
- {
- int p1 = 0, p2 = 0;
- while (cfg.host[p2] != '\0') {
- if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
- cfg.host[p1] = cfg.host[p2];
- p1++;
- }
- p2++;
- }
- cfg.host[p1] = '\0';
- }
+ conf_set_int(conf, CONF_ssh_subsys, TRUE);
- if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd && !*cfg.ssh_nc_host)
+ if (!*conf_get_str(conf, CONF_remote_cmd) &&
+ !*conf_get_str(conf, CONF_remote_cmd2) &&
+ !*conf_get_str(conf, CONF_ssh_nc_host))
flags |= FLAG_INTERACTIVE;
/*
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
- back = backend_from_proto(cfg.protocol);
+ back = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) {
fprintf(stderr,
"Internal fault: Unsupported protocol found\n");
* Select port.
*/
if (portnumber != -1)
- cfg.port = portnumber;
+ conf_set_int(conf, CONF_port, portnumber);
sk_init();
if (p_WSAEventSelect == NULL) {
return 1;
}
- logctx = log_init(NULL, &cfg);
+ logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
/*
const char *error;
char *realhost;
/* nodelay is only useful if stdin is a character device (console) */
- int nodelay = cfg.tcp_nodelay &&
+ int nodelay = conf_get_int(conf, CONF_tcp_nodelay) &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
- error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
- &realhost, nodelay, cfg.tcp_keepalives);
+ error = back->init(NULL, &backhandle, conf,
+ conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port),
+ &realhost, nodelay,
+ conf_get_int(conf, CONF_tcp_keepalives));
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
return 1;
Socket platform_new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
- Plug plug, const Config *cfg)
+ Plug plug, Conf *conf)
{
char *cmd;
STARTUPINFO si;
PROCESS_INFORMATION pi;
- if (cfg->proxy_type != PROXY_CMD)
+ if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
return NULL;
- cmd = format_telnet_command(addr, port, cfg);
+ cmd = format_telnet_command(addr, port, conf);
{
char *msg = dupprintf("Starting local proxy command: %s", cmd);
}
}
-static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg)
+static const char *serial_configure(Serial serial, HANDLE serport, Conf *conf)
{
DCB dcb;
COMMTIMEOUTS timeouts;
/*
* Configurable parameters.
*/
- dcb.BaudRate = cfg->serspeed;
- msg = dupprintf("Configuring baud rate %d", cfg->serspeed);
+ dcb.BaudRate = conf_get_int(conf, CONF_serspeed);
+ msg = dupprintf("Configuring baud rate %d", dcb.BaudRate);
logevent(serial->frontend, msg);
sfree(msg);
- dcb.ByteSize = cfg->serdatabits;
- msg = dupprintf("Configuring %d data bits", cfg->serdatabits);
+ dcb.ByteSize = conf_get_int(conf, CONF_serdatabits);
+ msg = dupprintf("Configuring %d data bits", dcb.ByteSize);
logevent(serial->frontend, msg);
sfree(msg);
- switch (cfg->serstopbits) {
+ switch (conf_get_int(conf, CONF_serstopbits)) {
case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break;
case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break;
case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break;
logevent(serial->frontend, msg);
sfree(msg);
- switch (cfg->serparity) {
+ switch (conf_get_int(conf, CONF_serparity)) {
case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break;
case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break;
case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break;
logevent(serial->frontend, msg);
sfree(msg);
- switch (cfg->serflow) {
+ switch (conf_get_int(conf, CONF_serflow)) {
case SER_FLOW_NONE:
str = "no";
break;
* freed by the caller.
*/
static const char *serial_init(void *frontend_handle, void **backend_handle,
- Config *cfg,
- char *host, int port, char **realhost, int nodelay,
- int keepalive)
+ Conf *conf, char *host, int port,
+ char **realhost, int nodelay, int keepalive)
{
Serial serial;
HANDLE serport;
const char *err;
+ char *serline;
serial = snew(struct serial_backend_data);
serial->port = INVALID_HANDLE_VALUE;
serial->frontend = frontend_handle;
+ serline = conf_get_str(conf, CONF_serline);
{
- char *msg = dupprintf("Opening serial device %s", cfg->serline);
+ char *msg = dupprintf("Opening serial device %s", serline);
logevent(serial->frontend, msg);
}
* existing configurations using \\.\ continue working.)
*/
char *serfilename =
- dupprintf("%s%s",
- strchr(cfg->serline, '\\') ? "" : "\\\\.\\",
- cfg->serline);
+ dupprintf("%s%s", strchr(serline, '\\') ? "" : "\\\\.\\", serline);
serport = CreateFile(serfilename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
sfree(serfilename);
if (serport == INVALID_HANDLE_VALUE)
return "Unable to open serial port";
- err = serial_configure(serial, serport, cfg);
+ err = serial_configure(serial, serport, conf);
if (err)
return err;
HANDLE_FLAG_IGNOREEOF |
HANDLE_FLAG_UNITBUFFER);
- *realhost = dupstr(cfg->serline);
+ *realhost = dupstr(serline);
/*
* Specials are always available.
sfree(serial);
}
-static void serial_reconfig(void *handle, Config *cfg)
+static void serial_reconfig(void *handle, Conf *conf)
{
Serial serial = (Serial) handle;
const char *err;
- err = serial_configure(serial, serial->port, cfg);
+ err = serial_configure(serial, serial->port, conf);
/*
* FIXME: what should we do if err returns something?
return ret;
}
-void platform_get_x11_auth(struct X11Display *display, const Config *cfg)
+void platform_get_x11_auth(struct X11Display *display, Conf *conf)
{
/* Do nothing, therefore no auth. */
}
return (void *) sesskey;
}
-char *read_setting_s(void *handle, const char *key, char *buffer, int buflen)
+char *read_setting_s(void *handle, const char *key)
{
DWORD type, size;
- size = buflen;
+ char *ret;
- if (!handle ||
- RegQueryValueEx((HKEY) handle, key, 0,
- &type, buffer, &size) != ERROR_SUCCESS ||
+ if (!handle)
+ return NULL;
+
+ /* Find out the type and size of the data. */
+ if (RegQueryValueEx((HKEY) handle, key, 0,
+ &type, NULL, &size) != ERROR_SUCCESS ||
+ type != REG_SZ)
+ return NULL;
+
+ ret = snewn(size+1, char);
+ if (RegQueryValueEx((HKEY) handle, key, 0,
+ &type, ret, &size) != ERROR_SUCCESS ||
type != REG_SZ) return NULL;
- else
- return buffer;
+
+ return ret;
}
int read_setting_i(void *handle, const char *key, int defvalue)
{
char *settingname;
FontSpec ret;
+ char *fontname;
- if (!read_setting_s(handle, name, ret.name, sizeof(ret.name)))
+ fontname = read_setting_s(handle, name);
+ if (!fontname)
return 0;
+ strncpy(ret.name, fontname, sizeof(ret.name)-1);
+ ret.name[sizeof(ret.name)-1] = '\0';
+ sfree(fontname);
+
settingname = dupcat(name, "IsBold", NULL);
ret.isbold = read_setting_i(handle, settingname, -1);
sfree(settingname);
if (ret.isbold == -1) return 0;
+
settingname = dupcat(name, "CharSet", NULL);
ret.charset = read_setting_i(handle, settingname, -1);
sfree(settingname);
if (ret.charset == -1) return 0;
+
settingname = dupcat(name, "Height", NULL);
ret.height = read_setting_i(handle, settingname, INT_MIN);
sfree(settingname);
int read_setting_filename(void *handle, const char *name, Filename *result)
{
- return !!read_setting_s(handle, name, result->path, sizeof(result->path));
+ char *tmp = read_setting_s(handle, name);
+ if (tmp) {
+ strncpy(result->path, tmp, sizeof(result->path)-1);
+ result->path[sizeof(result->path)-1] = '\0';
+ sfree(tmp);
+ return TRUE;
+ } else
+ return FALSE;
}
void write_setting_filename(void *handle, const char *name, Filename result)
#ifndef DONE_TYPEDEFS
#define DONE_TYPEDEFS
-typedef struct config_tag Config;
+typedef struct conf_tag Conf;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal;
#endif
* Exports from unicode.c.
*/
struct unicode_data;
-void init_ucs(Config *, struct unicode_data *);
+void init_ucs(Conf *, struct unicode_data *);
/*
* Exports from winhandl.c.
static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
-void init_ucs(Config *cfg, struct unicode_data *ucsdata)
+void init_ucs(Conf *conf, struct unicode_data *ucsdata)
{
int i, j;
int used_dtf = 0;
char tbuf[256];
+ int vtmode;
for (i = 0; i < 256; i++)
tbuf[i] = i;
/* Decide on the Line and Font codepages */
- ucsdata->line_codepage = decode_codepage(cfg->line_codepage);
+ ucsdata->line_codepage = decode_codepage(conf_get_str(conf,
+ CONF_line_codepage));
if (ucsdata->font_codepage <= 0) {
ucsdata->font_codepage=0;
ucsdata->dbcs_screenfont=0;
}
- if (cfg->vtmode == VT_OEMONLY) {
+ vtmode = conf_get_int(conf, CONF_vtmode);
+ if (vtmode == VT_OEMONLY) {
ucsdata->font_codepage = 437;
ucsdata->dbcs_screenfont = 0;
if (ucsdata->line_codepage <= 0)
if (ucsdata->font_codepage == 437)
ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
}
- if (cfg->vtmode == VT_XWINDOWS)
+ if (vtmode == VT_XWINDOWS)
memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
sizeof(unitab_xterm_std));
get_unitab(CP_OEMCP, ucsdata->unitab_oemcp, 1);
/* Collect CP437 ucs table for SCO acs */
- if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS)
+ if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
sizeof(ucsdata->unitab_scoacs));
else
/* Collect line set ucs table */
if (ucsdata->line_codepage == ucsdata->font_codepage &&
(ucsdata->dbcs_screenfont ||
- cfg->vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
+ vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
/* For DBCS and POOR fonts force direct to font */
used_dtf = 1;
ucsdata->unitab_ctrl[i] = 0xFF;
/* Generate line->screen direct conversion links. */
- if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS)
+ if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
link_font(ucsdata->unitab_line, ucsdata->unitab_font, CSET_ACP);
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, CSET_ACP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, CSET_ACP);
- if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS) {
+ if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS) {
link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
}
}
/* Last chance, if !unicode then try poorman links. */
- if (cfg->vtmode != VT_UNICODE) {
+ if (vtmode != VT_UNICODE) {
static const char poorman_scoacs[] =
"CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
static const char poorman_latin1[] =
#include "putty.h"
#include "ssh.h"
-void platform_get_x11_auth(struct X11Display *disp, const Config *cfg)
+void platform_get_x11_auth(struct X11Display *disp, Conf *conf)
{
- if (cfg->xauthfile.path[0])
- x11_get_auth_from_authfile(disp, cfg->xauthfile.path);
+ char *xauthpath = conf_get_filename(conf, CONF_xauthfile)->path;
+ if (xauthpath[0])
+ x11_get_auth_from_authfile(disp, xauthpath);
}
const int platform_uses_x11_unix_by_default = FALSE;
dummy_plug_sent, dummy_plug_accepting
};
-struct X11Display *x11_setup_display(char *display, int authtype,
- const Config *cfg)
+struct X11Display *x11_setup_display(char *display, int authtype, Conf *conf)
{
struct X11Display *disp = snew(struct X11Display);
char *localcopy;
disp->port = 6000 + disp->displaynum;
disp->addr = name_lookup(disp->hostname, disp->port,
- &disp->realhost, cfg, ADDRTYPE_UNSPEC);
+ &disp->realhost, conf, ADDRTYPE_UNSPEC);
if ((err = sk_addr_error(disp->addr)) != NULL) {
sk_addr_free(disp->addr);
disp->localauthproto = X11_NO_AUTH;
disp->localauthdata = NULL;
disp->localauthdatalen = 0;
- platform_get_x11_auth(disp, cfg);
+ platform_get_x11_auth(disp, conf);
return disp;
}
* also, fills the SocketsStructure
*/
extern const char *x11_init(Socket *s, struct X11Display *disp, void *c,
- const char *peeraddr, int peerport,
- const Config *cfg)
+ const char *peeraddr, int peerport, Conf *conf)
{
static const struct plug_function_table fn_table = {
x11_log,
pr->s = *s = new_connection(sk_addr_dup(disp->addr),
disp->realhost, disp->port,
- 0, 1, 0, 0, (Plug) pr, cfg);
+ 0, 1, 0, 0, (Plug) pr, conf);
if ((err = sk_socket_error(*s)) != NULL) {
sfree(pr);
return err;