1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-08 08:58:00 +00:00

Post-release destabilisation! Completely remove the struct type

'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.

User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).

One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.

[originally from svn r9214]
This commit is contained in:
Simon Tatham 2011-07-14 18:52:21 +00:00
parent 7aba365ca9
commit a1f3b7a358
64 changed files with 4443 additions and 3303 deletions

10
Recipe
View File

@ -245,7 +245,7 @@ CFLAGS += -DWINVER=0x0500 -D_WIN32_WINDOWS=0x0410 -D_WIN32_WINNT=0x0500
# 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
@ -272,7 +272,7 @@ SFTP = sftp int64 logging
# 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
@ -315,12 +315,12 @@ psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC
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
@ -338,7 +338,7 @@ plink : [U] uxplink uxcons NONSSH UXSSH U_BE_ALL logging UXMISC uxsignal
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

211
cmdline.c
View File

@ -162,7 +162,7 @@ static int cmdline_check_unavailable(int flag, char *p)
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;
@ -170,7 +170,7 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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;
@ -179,41 +179,49 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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);
@ -223,41 +231,23 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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
@ -265,19 +255,47 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
* 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;
@ -286,20 +304,15 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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;
@ -317,8 +330,7 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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 {
@ -332,16 +344,17 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
}
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);
@ -349,7 +362,7 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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 {
@ -366,105 +379,107 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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 */
@ -483,55 +498,41 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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:
@ -540,11 +541,11 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
}
} 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);
@ -556,11 +557,11 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
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);
}

610
conf.c Normal file
View File

@ -0,0 +1,610 @@
/*
* 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);
}

1098
config.c

File diff suppressed because it is too large Load Diff

View File

@ -130,7 +130,8 @@ int proxy_socks5_handlechap (Proxy_Socket p)
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:
@ -159,7 +160,9 @@ int proxy_socks5_handlechap (Proxy_Socket p)
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 */
@ -169,11 +172,11 @@ int proxy_socks5_selectchap(Proxy_Socket p)
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;

137
dialog.c
View File

@ -456,140 +456,3 @@ void ctrl_free(union control *ctrl)
}
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));
}
}

View File

@ -162,7 +162,7 @@ union control {
*
* 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-
@ -521,45 +521,6 @@ union control *ctrl_checkbox(struct controlset *, char *label, char shortcut,
handler_fn handler, intorptr context);
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
@ -584,7 +545,7 @@ int dlg_radiobutton_get(union control *ctrl, void *dlg);
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);

42
ldisc.c
View File

@ -12,12 +12,12 @@
#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))))
@ -76,7 +76,7 @@ static void bsb(Ldisc ldisc, int n)
#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)
{
@ -87,12 +87,13 @@ void *ldisc_create(Config *mycfg, Terminal *term,
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;
@ -102,6 +103,17 @@ void *ldisc_create(Config *mycfg, Terminal *term,
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;
@ -203,7 +215,7 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
* 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);
@ -255,7 +267,7 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
* 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]));
@ -264,9 +276,9 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
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);
@ -300,27 +312,27 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
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;
}

View File

@ -11,10 +11,14 @@
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;

View File

@ -18,7 +18,8 @@ struct LogContext {
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);
@ -75,7 +76,7 @@ static void logprintf(struct LogContext *ctx, const char *fmt, ...)
*/
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);
}
@ -110,10 +111,10 @@ static void logfopen_callback(void *handle, int mode)
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);
@ -148,19 +149,22 @@ void logfopen(void *handle)
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);
@ -189,8 +193,8 @@ void logfclose(void *handle)
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);
}
}
@ -214,8 +218,8 @@ void log_eventlog(void *handle, const char *event)
/* 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);
@ -236,8 +240,8 @@ void log_packet(void *handle, int direction, int type,
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. */
@ -326,13 +330,14 @@ void log_packet(void *handle, int direction, int type,
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;
}
@ -346,13 +351,15 @@ void log_free(void *handle)
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;
@ -360,7 +367,10 @@ void log_reconfig(void *handle, Config *cfg)
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);

View File

@ -20,6 +20,15 @@ say you weren't warned!
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
--------------------------------

20
misc.c
View File

@ -635,21 +635,21 @@ void debug_memdump(void *buf, int len, int L)
#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);
}

View File

@ -15,7 +15,7 @@
#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
@ -94,18 +94,18 @@ struct plug_function_table {
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 */

View File

@ -43,11 +43,11 @@ static void pinger_schedule(Pinger pinger)
}
}
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;
@ -56,10 +56,11 @@ Pinger pinger_new(Config *cfg, Backend *back, void *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);
}
}

View File

@ -325,7 +325,7 @@ static void pfd_sent(Plug plug, int bufsize)
* 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,
@ -343,7 +343,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port,
/*
* 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;
@ -362,7 +362,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port,
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;
@ -435,7 +435,7 @@ static int pfd_accepting(Plug p, OSSocket sock)
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 = {
@ -468,7 +468,8 @@ const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
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;

View File

@ -11,7 +11,7 @@
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;
}

173
proxy.c
View File

@ -14,9 +14,10 @@
#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
@ -263,7 +264,7 @@ static int plug_proxy_accepting (Plug p, OSSocket sock)
* 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];
@ -274,7 +275,7 @@ static int proxy_for_destination (SockAddr addr, char *hostname, int port,
* 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 */
@ -288,7 +289,7 @@ static int proxy_for_destination (SockAddr addr, char *hostname, int port,
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.
@ -349,11 +350,11 @@ static int proxy_for_destination (SockAddr addr, char *hostname, int port,
}
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);
}
@ -364,7 +365,7 @@ SockAddr name_lookup(char *host, int port, char **canonicalname,
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,
@ -386,24 +387,25 @@ Socket new_connection(SockAddr addr, char *hostname,
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;
@ -419,14 +421,15 @@ Socket new_connection(SockAddr addr, char *hostname,
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";
@ -440,8 +443,9 @@ Socket new_connection(SockAddr addr, char *hostname,
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;
@ -451,7 +455,8 @@ Socket new_connection(SockAddr addr, char *hostname,
/* 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)
@ -469,7 +474,7 @@ Socket new_connection(SockAddr addr, char *hostname,
}
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.
@ -525,6 +530,7 @@ int proxy_http_negotiate (Proxy_Socket p, int change)
* request
*/
char *buf, dest[512];
char *username, *password;
sk_getaddr(p->remote_addr, dest, lenof(dest));
@ -533,18 +539,22 @@ int proxy_http_negotiate (Proxy_Socket p, int change)
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);
@ -711,6 +721,7 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
int length, type, namelen;
char *command, addr[4], hostname[512];
char *username;
type = sk_addrtype(p->remote_addr);
if (type == ADDRTYPE_IPV6) {
@ -728,9 +739,10 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
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 */
@ -743,10 +755,11 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
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;
@ -868,10 +881,13 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
*/
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);
@ -1148,18 +1164,20 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
}
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
@ -1192,8 +1210,9 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
* 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;
@ -1208,22 +1227,21 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
* %%, %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;
}
@ -1231,15 +1249,15 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
/* 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);
@ -1280,15 +1298,12 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
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)
@ -1315,7 +1330,7 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
default:
ENSURE(2);
memcpy(ret+retlen, cfg->proxy_telnet_command + so, 2);
memcpy(ret+retlen, fmt + so, 2);
retlen += 2;
eo++;
break;
@ -1327,13 +1342,12 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
* 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));
@ -1343,8 +1357,7 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
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);
@ -1352,35 +1365,35 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
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);
@ -1404,7 +1417,7 @@ char *format_telnet_command(SockAddr addr, int port, const Config *cfg)
/* 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;
}
@ -1421,7 +1434,7 @@ int proxy_telnet_negotiate (Proxy_Socket p, int change)
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);

View File

@ -80,7 +80,7 @@ struct Socket_proxy_tag {
OSSocket accepting_sock;
/* configuration, used to look up proxy settings */
Config cfg;
Conf *conf;
/* CHAP transient data */
int chap_num_attributes;
@ -110,7 +110,7 @@ extern int proxy_socks5_negotiate (Proxy_Socket, int);
* 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

148
pscp.c
View File

@ -44,7 +44,7 @@ static int using_sftp = 0;
static Backend *back;
static void *backhandle;
static Config cfg;
static Conf *conf;
static void source(char *src);
static void rsource(char *src);
@ -333,88 +333,90 @@ static void do_cmd(char *host, char *user, char *cmd)
*/
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;
/* 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));
}
}
/*
* 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';
} 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);
}
}
@ -424,10 +426,14 @@ static void do_cmd(char *host, char *user, char *cmd)
* 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
@ -435,44 +441,49 @@ static void do_cmd(char *host, char *user, char *cmd)
* 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();
@ -2221,14 +2232,15 @@ int psftp_main(int argc, char *argv[])
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) {

146
psftp.c
View File

@ -36,7 +36,7 @@ void do_sftp_cleanup();
char *pwd, *homedir;
static Backend *back;
static void *backhandle;
static Config cfg;
static Conf *conf;
/* ----------------------------------------------------------------------
* Higher-level helper functions used in commands.
@ -2664,32 +2664,30 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
*/
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);
}
/*
@ -2698,78 +2696,82 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
* 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);
}
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.
*/
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++;
/*
* 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';
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
@ -2788,21 +2790,26 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
* 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)) {
@ -2854,7 +2861,8 @@ int psftp_main(int argc, char *argv[])
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++) {
@ -2866,7 +2874,7 @@ int psftp_main(int argc, char *argv[])
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) {
@ -2908,8 +2916,8 @@ int psftp_main(int argc, char *argv[])
* 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));
}
/*

523
putty.h
View File

@ -18,7 +18,7 @@
#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
@ -304,7 +304,7 @@ enum {
};
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. */
@ -312,22 +312,22 @@ enum {
};
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,
@ -415,12 +415,11 @@ enum {
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 */
@ -461,214 +460,6 @@ extern const int be_default_protocol;
*/
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.
*
@ -838,6 +629,255 @@ void set_busy_status(void *frontend, int status);
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.
*/
@ -853,13 +893,13 @@ void random_destroy_seed(void);
*/
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);
/*
@ -882,7 +922,7 @@ FontSpec platform_default_fontspec(const char *name);
* 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);
@ -904,7 +944,7 @@ void term_paste(Terminal *);
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);
@ -922,9 +962,9 @@ int format_arrow_key(char *buf, Terminal *term, int xkey, int ctrl);
/*
* 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);
@ -975,7 +1015,8 @@ extern Backend ssh_backend;
/*
* 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);
@ -1003,8 +1044,8 @@ void random_unref(void);
* 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);
/*
@ -1012,8 +1053,8 @@ 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.
@ -1147,8 +1188,8 @@ void printer_finish_job(printer_job *);
* 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
@ -1161,6 +1202,18 @@ void cmdline_error(char *, ...);
* 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);

20
raw.c
View File

@ -89,7 +89,7 @@ static void raw_sent(Plug plug, int bufsize)
* 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)
{
@ -102,6 +102,8 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
SockAddr addr;
const char *err;
Raw raw;
int addressfamily;
char *loghost;
raw = snew(struct raw_backend_data);
raw->fn = &fn_table;
@ -110,19 +112,20 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
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;
@ -135,15 +138,16 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
* 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) {
/*
@ -170,7 +174,7 @@ static void raw_free(void *handle)
/*
* 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)
{
}

View File

@ -28,7 +28,7 @@ typedef struct rlogin_tag {
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;
@ -122,18 +122,18 @@ static void rlogin_startup(Rlogin rlogin, const char *ruser)
{
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;
@ -148,7 +148,7 @@ static void rlogin_startup(Rlogin rlogin, const char *ruser)
* 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)
{
@ -161,33 +161,36 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
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;
@ -200,15 +203,16 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
* 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) {
/*
@ -226,16 +230,17 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
* 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);
@ -253,13 +258,14 @@ static void rlogin_free(void *handle)
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)
{
}

View File

@ -31,10 +31,14 @@ static void serial_parity_handler(union control *ctrl, void *dlg,
};
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++) {
@ -56,14 +60,14 @@ static void serial_parity_handler(union control *ctrl, void *dlg,
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);
}
}
@ -81,10 +85,14 @@ static void serial_flow_handler(union control *ctrl, void *dlg,
};
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++) {
@ -105,14 +113,14 @@ static void serial_flow_handler(union control *ctrl, void *dlg,
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);
}
}
@ -173,23 +181,22 @@ void ser_setup_config_box(struct controlbox *b, int midsession,
"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));

1024
settings.c

File diff suppressed because it is too large Load Diff

646
ssh.c

File diff suppressed because it is too large Load Diff

15
ssh.h
View File

@ -334,13 +334,11 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org);
/* 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);
@ -393,18 +391,17 @@ struct X11Display {
* 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 */

View File

@ -47,7 +47,7 @@ struct ssh_gss_liblist {
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);
/*

View File

@ -3,7 +3,7 @@
/* 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;

View File

@ -9,9 +9,9 @@
/* ----------------------------------------------------------------------
* 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.
*/
/*
@ -41,8 +41,8 @@ void close_settings_w(void *handle);
* 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
@ -53,7 +53,7 @@ void close_settings_w(void *handle);
* 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);

161
telnet.c
View File

@ -201,7 +201,7 @@ typedef struct telnet_tag {
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} state;
Config cfg;
Conf *conf;
Pinger pinger;
} *Telnet;
@ -363,42 +363,46 @@ static void proc_rec_opt(Telnet telnet, int cmd, int option)
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);
@ -407,6 +411,7 @@ static void process_subneg(Telnet telnet)
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;
@ -421,7 +426,7 @@ static void process_subneg(Telnet telnet)
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 {
@ -449,50 +454,75 @@ static void process_subneg(Telnet telnet)
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;
}
@ -674,9 +704,8 @@ static void telnet_sent(Plug plug, int bufsize)
* 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,
@ -687,10 +716,12 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
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;
@ -698,8 +729,8 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
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;
@ -710,14 +741,15 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
*/
{
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;
@ -730,16 +762,16 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
* 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++)
@ -768,11 +800,12 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
/*
* 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) {
/*
@ -796,6 +829,7 @@ static void telnet_free(void *handle)
sk_close(telnet->s);
if (telnet->pinger)
pinger_free(telnet->pinger);
conf_free(telnet->conf);
sfree(telnet);
}
/*
@ -803,11 +837,12 @@ static void telnet_free(void *handle)
* 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);
}
/*

View File

@ -989,7 +989,7 @@ static void resizeline(Terminal *term, termline *line, int cols)
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;
}
@ -1015,7 +1015,7 @@ static termline *lineptr(Terminal *term, int y, int lineno, int screen)
assert(!screen);
if (term->cfg.erase_to_scrollback &&
if (term->erase_to_scrollback &&
term->alt_which && term->alt_screen) {
altlines = term->alt_sblines;
}
@ -1133,7 +1133,7 @@ static void term_schedule_tblink(Terminal *term)
*/
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;
@ -1197,11 +1197,11 @@ static void power_on(Terminal *term, int clear)
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;
@ -1216,10 +1216,10 @@ static void power_on(Terminal *term, int clear)
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);
@ -1228,7 +1228,7 @@ static void power_on(Terminal *term, int clear)
{
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);
@ -1261,7 +1261,7 @@ void term_update(Terminal *term)
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;
@ -1300,7 +1300,7 @@ void term_seen_key_event(Terminal *term)
/*
* 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);
}
@ -1327,13 +1327,83 @@ static void set_erase_char(Terminal *term)
(ATTR_FGMASK | ATTR_BGMASK));
}
/*
* 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
@ -1345,21 +1415,28 @@ void term_reconfig(Terminal *term, Config *cfg)
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);
@ -1370,39 +1447,41 @@ void term_reconfig(Terminal *term, Config *cfg)
}
}
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);
}
/*
@ -1423,7 +1502,7 @@ void term_clrsb(Terminal *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;
@ -1435,7 +1514,7 @@ Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata,
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");
@ -1497,6 +1576,8 @@ Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata,
term->basic_erase_char.cc_next = 0;
term->erase_char = term->basic_erase_char;
term_copy_stuff_from_conf(term);
return term;
}
@ -1543,6 +1624,8 @@ void term_free(Terminal *term)
expire_timer_context(term);
conf_free(term->conf);
sfree(term);
}
@ -2243,7 +2326,7 @@ static void erase_lots(Terminal *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. */
@ -2334,13 +2417,13 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
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;
@ -2387,7 +2470,7 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
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) */
@ -2401,22 +2484,22 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
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;
@ -2454,14 +2537,14 @@ static void do_osc(Terminal *term)
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;
}
@ -2471,10 +2554,10 @@ static void do_osc(Terminal *term)
/*
* 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)
{
@ -2549,7 +2632,7 @@ static void term_out(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;
@ -2741,7 +2824,7 @@ static void term_out(Terminal *term)
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),
@ -2761,19 +2844,8 @@ static void term_out(Terminal *term)
*/
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 */
@ -2800,7 +2872,7 @@ static void term_out(Terminal *term)
* 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);
@ -2809,16 +2881,16 @@ static void term_out(Terminal *term)
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
@ -2831,10 +2903,10 @@ static void term_out(Terminal *term)
/*
* 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);
}
}
@ -2876,12 +2948,12 @@ static void term_out(Terminal *term)
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;
@ -2901,7 +2973,7 @@ static void term_out(Terminal *term)
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);
@ -2943,7 +3015,7 @@ static void term_out(Terminal *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));
@ -3166,7 +3238,7 @@ static void term_out(Terminal *term)
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;
}
@ -3231,55 +3303,55 @@ static void term_out(Terminal *term)
/* 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;
}
@ -3463,12 +3535,15 @@ static void term_out(Terminal *term)
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);
@ -3591,15 +3666,15 @@ static void term_out(Terminal *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);
@ -3722,7 +3797,7 @@ static void term_out(Terminal *term)
&& (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);
@ -3742,7 +3817,7 @@ static void term_out(Terminal *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));
@ -3767,10 +3842,10 @@ static void term_out(Terminal *term)
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:
@ -3825,8 +3900,8 @@ static void term_out(Terminal *term)
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;
@ -3838,8 +3913,8 @@ static void term_out(Terminal *term)
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;
@ -3875,10 +3950,10 @@ static void term_out(Terminal *term)
*/
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;
@ -3890,10 +3965,11 @@ static void term_out(Terminal *term)
*/
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;
@ -4095,7 +4171,7 @@ static void term_out(Terminal *term)
* 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
@ -4330,7 +4406,7 @@ static void term_out(Terminal *term)
* 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
@ -4474,7 +4550,7 @@ static void term_out(Terminal *term)
}
term_print_flush(term);
if (term->cfg.logflush)
if (term->logflush)
logflush(term->logctx);
}
@ -4577,7 +4653,7 @@ static termchar *term_bidi_line(Terminal *term, struct termline *ldata,
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)) {
@ -4595,7 +4671,7 @@ static termchar *term_bidi_line(Terminal *term, struct termline *ldata,
switch (uc & CSET_MASK) {
case CSET_LINEDRW:
if (!term->cfg.rawcnp) {
if (!term->rawcnp) {
uc = term->ucsdata->unitab_xterm[uc & 0xFF];
break;
}
@ -4620,15 +4696,15 @@ static termchar *term_bidi_line(Terminal *term, struct termline *ldata,
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) {
@ -4690,14 +4766,14 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
/* 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;
@ -4805,11 +4881,11 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
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)
@ -5265,7 +5341,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
switch (uc & CSET_MASK) {
case CSET_LINEDRW:
if (!term->cfg.rawcnp) {
if (!term->rawcnp) {
uc = term->ucsdata->unitab_xterm[uc & 0xFF];
break;
}
@ -5647,8 +5723,8 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
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) {
@ -5755,7 +5831,7 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
* 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;
@ -5875,7 +5951,7 @@ int format_arrow_key(char *buf, Terminal *term, int xkey, int ctrl)
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
@ -5992,7 +6068,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
}
/* Nethack keypad */
if (term->cfg.nethack_keypad) {
if (term->nethack_keypad) {
char c = 0;
switch (keysym) {
case PK_KP1: c = 'b'; break;
@ -6026,10 +6102,10 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
* 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;
@ -6038,7 +6114,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
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;
@ -6054,7 +6130,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
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.
@ -6126,10 +6202,10 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
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:
@ -6157,7 +6233,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
}
/* 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@[\\]^_`{";
@ -6187,7 +6263,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
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;
@ -6201,7 +6277,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
}
/* 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;
@ -6244,7 +6320,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
/* 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;
@ -6254,11 +6330,11 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
'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
@ -6478,9 +6554,9 @@ char *term_get_ttymode(Terminal *term, const char *mode)
{
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);
}

View File

@ -233,13 +233,13 @@ struct terminal_tag {
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
@ -273,6 +273,52 @@ struct terminal_tag {
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)

View File

@ -33,13 +33,13 @@
#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 *);
@ -74,14 +74,14 @@ struct loop_state {
};
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);
@ -101,7 +101,7 @@ static void loop_free(void *handle)
sfree(handle);
}
static void null_reconfig(void *handle, Config *cfg) {
static void null_reconfig(void *handle, Conf *conf) {
}

View File

@ -42,8 +42,8 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win)
"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.
@ -51,7 +51,7 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win)
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.
@ -89,29 +89,29 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win)
"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
@ -125,8 +125,8 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win)
"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) {
/*
@ -137,8 +137,7 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win)
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));
}
}

View File

@ -330,11 +330,10 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
* 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.
@ -344,7 +343,7 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
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);
@ -353,25 +352,16 @@ void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
#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");
@ -2826,12 +2816,12 @@ void set_dialog_action_area(GtkDialog *dlg, GtkWidget *w)
#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)
@ -2859,8 +2849,9 @@ int do_config_box(const char *title, Config *cfg, int midsession,
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);
@ -3095,7 +3086,7 @@ int do_config_box(const char *title, Config *cfg, int midsession,
}
#endif
dp.data = cfg;
dp.data = conf;
dlg_refresh(NULL, &dp);
dp.shortcuts = &selparams[0].shortcuts;

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,7 @@ long get_windowid(void *frontend);
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);
@ -100,7 +100,7 @@ int reallyclose(void *frontend);
/* 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);

View File

@ -12,7 +12,7 @@
#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;

View File

@ -16,11 +16,11 @@ void unix_setup_config_box(struct controlbox *b, int midsession, int protocol)
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.
*/
/*
@ -41,8 +41,8 @@ void unix_setup_config_box(struct controlbox *b, int midsession, int protocol)
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 *);
@ -58,9 +58,8 @@ void unix_setup_config_box(struct controlbox *b, int midsession, int protocol)
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");

View File

@ -53,9 +53,10 @@ static void gss_init(struct ssh_gss_library *lib, void *dlhandle,
}
/* 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);
@ -77,11 +78,11 @@ struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
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;
}
@ -129,7 +130,7 @@ const struct keyvalwhere gsslibkeywords[] = {
#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);

View File

@ -98,7 +98,7 @@ static int local_tty = FALSE; /* do we have a local tty? */
static Backend *back;
static void *backhandle;
static Config cfg;
static Conf *conf;
/*
* Default settings that are specific to pterm.
@ -605,10 +605,11 @@ int main(int argc, char **argv)
/*
* 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;
{
/*
@ -618,8 +619,10 @@ int main(int argc, char **argv)
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);
}
}
}
@ -627,7 +630,7 @@ int main(int argc, char **argv)
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);
@ -639,7 +642,7 @@ int main(int argc, char **argv)
} 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();
@ -660,7 +663,7 @@ int main(int argc, char **argv)
errors = 1;
}
} else if (*p) {
if (!cfg_launchable(&cfg) || !(got_host || loaded_session)) {
if (!conf_launchable(conf) || !(got_host || loaded_session)) {
char *q = p;
/*
@ -674,7 +677,7 @@ int main(int argc, char **argv)
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++;
@ -682,11 +685,10 @@ int main(int argc, char **argv)
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;
@ -701,7 +703,9 @@ int main(int argc, char **argv)
*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;
@ -728,26 +732,24 @@ int main(int argc, char **argv)
* 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);
}
}
@ -774,9 +776,9 @@ int main(int argc, char **argv)
}
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 */
}
@ -786,70 +788,78 @@ int main(int argc, char **argv)
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;
/* 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 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;
conf_set_int(conf, CONF_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';
}
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");
@ -860,7 +870,7 @@ int main(int argc, char **argv)
* 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.
@ -879,28 +889,34 @@ int main(int argc, char **argv)
* 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;

View File

@ -224,7 +224,7 @@ static int localproxy_select_result(int fd, int event)
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;
@ -243,10 +243,10 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
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;

View File

@ -12,19 +12,19 @@ const int use_event_log = 0; /* pterm doesn't need it */
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;
}
@ -33,7 +33,7 @@ void cleanup_exit(int code)
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. */
}

View File

@ -76,7 +76,7 @@ typedef struct pty_tag *Pty;
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];
@ -588,6 +588,8 @@ int pty_real_select_result(Pty pty, int event, int status)
}
if (finished && !pty->finished) {
int close_on_exit;
uxsel_del(pty->master_fd);
pty_close(pty);
pty->master_fd = -1;
@ -600,8 +602,9 @@ int pty_real_select_result(Pty pty, int event, int status)
* 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"
@ -681,7 +684,7 @@ static void pty_uxsel_setup(Pty pty)
* 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)
{
@ -705,9 +708,9 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
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);
@ -719,7 +722,8 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
{
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);
}
@ -728,7 +732,7 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
* 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 {
@ -787,7 +791,8 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
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.
@ -803,18 +808,12 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
}
#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++;
char *key, *val;
varval = dupprintf("%.*s=%s", varend-var, var, 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
@ -841,7 +840,7 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
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;
@ -884,7 +883,7 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
return NULL;
}
static void pty_reconfig(void *handle, Config *cfg)
static void pty_reconfig(void *handle, Conf *conf)
{
Pty pty = (Pty)handle;
/*
@ -892,7 +891,7 @@ static void pty_reconfig(void *handle, Config *cfg)
* 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);
}
/*

View File

@ -31,17 +31,17 @@ void cleanup_exit(int code)
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;
}
@ -50,7 +50,7 @@ static int got_host = 0;
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;
@ -61,7 +61,7 @@ int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
* 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)) {
/*
@ -74,7 +74,7 @@ int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
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++;
@ -82,11 +82,10 @@ int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
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 {
/*
@ -97,8 +96,7 @@ int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch)
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)

View File

@ -60,10 +60,10 @@ static int serial_select_result(int fd, int event);
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;
@ -75,8 +75,9 @@ static const char *serial_configure(Serial serial, Config *cfg)
/*
* 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);
@ -183,18 +184,19 @@ static const char *serial_configure(Serial serial, Config *cfg)
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;
@ -211,10 +213,11 @@ static const char *serial_configure(Serial serial, Config *cfg)
#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
@ -229,11 +232,12 @@ static const char *serial_configure(Serial serial, Config *cfg)
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";
@ -284,12 +288,13 @@ static const char *serial_configure(Serial serial, Config *cfg)
* 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;
@ -299,22 +304,23 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
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);
@ -349,14 +355,14 @@ static void serial_free(void *handle)
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)

View File

@ -34,7 +34,7 @@ char *x_get_default(const char *key)
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. */
}

View File

@ -317,7 +317,7 @@ void *open_settings_r(const char *sessionname)
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;
@ -333,11 +333,8 @@ char *read_setting_s(void *handle, const char *key, char *buffer, int buflen)
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)
@ -375,26 +372,40 @@ int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
* ("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)

View File

@ -139,7 +139,7 @@ int init_ucs(struct unicode_data *ucsdata, char *linecharset,
/*
* 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);

View File

@ -70,8 +70,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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.
@ -81,7 +81,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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.
@ -105,10 +105,10 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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
@ -133,8 +133,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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 *);
@ -159,7 +159,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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
@ -167,8 +167,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
*/
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);
@ -180,7 +180,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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.
@ -191,8 +191,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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),
@ -206,8 +206,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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
@ -232,8 +232,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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 *);
@ -272,7 +272,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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
@ -283,8 +283,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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);
@ -304,10 +304,10 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
"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));
/*
@ -316,8 +316,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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),
@ -331,20 +331,20 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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
@ -356,8 +356,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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 *);
@ -373,9 +373,8 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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");
@ -399,6 +398,6 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
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));
}
}

View File

@ -2100,13 +2100,23 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
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. */
@ -2471,8 +2481,10 @@ int dlg_coloursel_results(union control *ctrl, void *dlg,
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;
@ -2483,16 +2495,19 @@ void dlg_auto_set_fixed_pitch_flag(void *dlg)
* 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 {
@ -2500,8 +2515,8 @@ void dlg_auto_set_fixed_pitch_flag(void *dlg)
}
if (hdc)
ReleaseDC(NULL, hdc);
if (font)
DeleteObject(font);
if (hfont)
DeleteObject(hfont);
if (is_var)
dp->fixed_pitch_fonts = FALSE;

View File

@ -44,7 +44,7 @@ static struct dlgparam dp;
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)"
@ -648,7 +648,7 @@ int do_config(void)
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' */
@ -666,15 +666,15 @@ int do_config(void)
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);
@ -682,7 +682,7 @@ int do_reconfig(HWND hwnd, int protcfginfo)
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' */
@ -695,7 +695,9 @@ int do_reconfig(HWND hwnd, int protcfginfo)
dp_cleanup(&dp);
if (!ret)
cfg = backup_cfg; /* structure copy */
conf_copy_into(conf, backup_conf);
conf_free(backup_conf);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -65,11 +65,12 @@ const char *gsslogmsg = NULL;
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;
@ -148,8 +149,9 @@ struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
* 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 =
@ -157,7 +159,7 @@ struct ssh_gss_liblist *ssh_gss_setup(const Config *cfg)
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) \

View File

@ -83,7 +83,7 @@ WSAEVENT netevent;
static Backend *back;
static void *backhandle;
static Config cfg;
static Conf *conf;
int term_ldisc(Terminal *term, int mode)
{
@ -298,10 +298,11 @@ int main(int argc, char **argv)
/*
* 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;
{
/*
@ -311,8 +312,10 @@ int main(int argc, char **argv)
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);
}
}
}
@ -320,7 +323,7 @@ int main(int argc, char **argv)
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);
@ -332,7 +335,7 @@ int main(int argc, char **argv)
} 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();
@ -344,7 +347,7 @@ int main(int argc, char **argv)
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
@ -357,7 +360,7 @@ int main(int argc, char **argv)
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++;
@ -365,11 +368,10 @@ int main(int argc, char **argv)
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;
@ -384,7 +386,9 @@ int main(int argc, char **argv)
*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;
@ -411,26 +415,24 @@ int main(int argc, char **argv)
* 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);
}
}
@ -457,9 +459,9 @@ int main(int argc, char **argv)
}
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 */
}
@ -469,70 +471,78 @@ int main(int argc, char **argv)
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;
/* 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';
/*
* 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 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;
conf_set_int(conf, CONF_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';
}
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");
@ -543,7 +553,7 @@ int main(int argc, char **argv)
* Select port.
*/
if (portnumber != -1)
cfg.port = portnumber;
conf_set_int(conf, CONF_port, portnumber);
sk_init();
if (p_WSAEventSelect == NULL) {
@ -551,7 +561,7 @@ int main(int argc, char **argv)
return 1;
}
logctx = log_init(NULL, &cfg);
logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
/*
@ -562,11 +572,14 @@ int main(int argc, char **argv)
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;

View File

@ -123,7 +123,7 @@ static const char *sk_localproxy_socket_error(Socket s)
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;
@ -145,10 +145,10 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
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);

View File

@ -87,7 +87,7 @@ static void serial_sentdata(struct handle *h, int new_backlog)
}
}
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;
@ -121,17 +121,17 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg)
/*
* 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;
@ -141,7 +141,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg)
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;
@ -152,7 +152,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg)
logevent(serial->frontend, msg);
sfree(msg);
switch (cfg->serflow) {
switch (conf_get_int(conf, CONF_serflow)) {
case SER_FLOW_NONE:
str = "no";
break;
@ -199,13 +199,13 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg)
* 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;
@ -216,8 +216,9 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
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);
}
@ -246,9 +247,7 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
* 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);
@ -257,7 +256,7 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
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;
@ -269,7 +268,7 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
HANDLE_FLAG_IGNOREEOF |
HANDLE_FLAG_UNITBUFFER);
*realhost = dupstr(cfg->serline);
*realhost = dupstr(serline);
/*
* Specials are always available.
@ -288,12 +287,12 @@ static void serial_free(void *handle)
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?

View File

@ -20,7 +20,7 @@ int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
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. */
}

View File

@ -150,17 +150,26 @@ void *open_settings_r(const char *sessionname)
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)
@ -181,17 +190,25 @@ int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
{
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);
@ -218,7 +235,14 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec font)
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)

View File

@ -115,7 +115,7 @@ struct FontSpec {
#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
@ -473,7 +473,7 @@ void EnableSizeTip(int bEnable);
* 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.

View File

@ -436,24 +436,27 @@ static const struct cp_list_item cp_list[] = {
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)
@ -473,7 +476,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
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));
@ -481,7 +484,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
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
@ -490,7 +493,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
/* 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;
@ -560,14 +563,14 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
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);
}
@ -581,7 +584,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
}
/* 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[] =

View File

@ -9,10 +9,11 @@
#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;

View File

@ -68,8 +68,7 @@ static const struct plug_function_table dummy_plug = {
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;
@ -166,7 +165,7 @@ struct X11Display *x11_setup_display(char *display, int authtype,
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);
@ -249,7 +248,7 @@ struct X11Display *x11_setup_display(char *display, int authtype,
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;
}
@ -558,8 +557,7 @@ int x11_get_screen_number(char *display)
* 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,
@ -586,7 +584,7 @@ extern const char *x11_init(Socket *s, struct X11Display *disp, void *c,
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;