diff --git a/conf.h b/conf.h index b5d8bf4d..f6d8acc8 100644 --- a/conf.h +++ b/conf.h @@ -9,6 +9,22 @@ * - SUBKEY_TYPE: if the primary key goes with a subkey (that is, the * primary key identifies some mapping from subkeys to values), the * data type of the subkey + * - DEFAULT_INT, DEFAULT_STR, DEFAULT_BOOL: the default value for + * the key, if no save data is available. Must match VALUE_TYPE, if + * the key has no subkey. Otherwise, no default is permitted, and + * the default value of the mapping is assumed to be empty (and if + * not, then LOAD_CUSTOM code must override that). + * - SAVE_KEYWORD: the keyword used for the option in the Windows + * registry or ~/.putty/sessions save files. + * - STORAGE_ENUM: for int-typed settings with no subkeys, this + * identifies an enumeration in conf-enums.h which maps internal + * values of the setting in the Conf to values in the saved data. + * - LOAD_CUSTOM, SAVE_CUSTOM: suppress automated loading or saving + * (respectively) of this setting, in favour of manual code in + * settings.c load_open_settings() or save_open_settings() + * respectively. + * - NOT_SAVED: indicate that this setting is not part of saved + * session data at all. */ CONF_OPTION(host, @@ -150,6 +166,7 @@ CONF_OPTION(remote_cmd2, * by user configuration, or loaded or saved. */ VALUE_TYPE(STR), + DEFAULT_STR(""), NOT_SAVED, ) CONF_OPTION(nopty, @@ -255,6 +272,7 @@ CONF_OPTION(ssh_simple, * user configuration, or loaded or saved. */ VALUE_TYPE(BOOL), + DEFAULT_BOOL(false), NOT_SAVED, ) CONF_OPTION(ssh_connection_sharing, @@ -349,14 +367,16 @@ CONF_OPTION(ssh_subsys, /* run a subsystem rather than a command */ * configuration, or loaded or saved. */ VALUE_TYPE(BOOL), + DEFAULT_BOOL(false), NOT_SAVED, ) -CONF_OPTION(ssh_subsys2, /* fallback to go with remote_cmd_ptr2 */ +CONF_OPTION(ssh_subsys2, /* fallback to go with remote_cmd2 */ /* * Only set internally by PSCP and PSFTP; never set by user * configuration, or loaded or saved. */ VALUE_TYPE(BOOL), + DEFAULT_BOOL(false), NOT_SAVED, ) CONF_OPTION(ssh_no_shell, /* avoid running a shell */ @@ -371,6 +391,7 @@ CONF_OPTION(ssh_nc_host, /* host to connect to in `nc' mode */ * also never loaded or saved. */ VALUE_TYPE(STR), + DEFAULT_STR(""), NOT_SAVED, ) CONF_OPTION(ssh_nc_port, /* port to connect to in `nc' mode */ @@ -380,6 +401,7 @@ CONF_OPTION(ssh_nc_port, /* port to connect to in `nc' mode */ * also never loaded or saved. */ VALUE_TYPE(INT), + DEFAULT_INT(0), NOT_SAVED, ) diff --git a/settings.c b/settings.c index 8bd84dba..075656f7 100644 --- a/settings.c +++ b/settings.c @@ -670,15 +670,27 @@ void load_open_settings(settings_r *sesskey, Conf *conf) int i; char *prot; - conf_set_bool(conf, CONF_ssh_subsys, false); /* FIXME: load this properly */ - conf_set_str(conf, CONF_remote_cmd, ""); - conf_set_str(conf, CONF_remote_cmd2, ""); - conf_set_str(conf, CONF_ssh_nc_host, ""); - /* Load the settings simple enough to handle automatically */ for (size_t key = 0; key < N_CONFIG_OPTIONS; key++) { const ConfKeyInfo *info = &conf_key_info[key]; - if (!info->load_custom && !info->not_saved) { + if (info->not_saved) { + /* Mappings are assumed to default to empty */ + if (info->subkey_type == CONF_TYPE_NONE) { + switch (info->value_type) { + case CONF_TYPE_STR: + conf_set_str(conf, key, info->default_value.sval); + break; + case CONF_TYPE_INT: + conf_set_int(conf, key, info->default_value.ival); + break; + case CONF_TYPE_BOOL: + conf_set_bool(conf, key, info->default_value.bval); + break; + default: + unreachable("bad key type in load_open_settings"); + } + } + } else if (!info->load_custom) { /* Mappings are handled individually below */ assert(info->subkey_type == CONF_TYPE_NONE); switch (info->value_type) { @@ -994,7 +1006,6 @@ void load_open_settings(settings_r *sesskey, Conf *conf) conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON); } } - conf_set_bool(conf, CONF_ssh_simple, false); gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys); } diff --git a/test/test_conf.c b/test/test_conf.c index d807a6ca..d9f215b3 100644 --- a/test/test_conf.c +++ b/test/test_conf.c @@ -822,6 +822,7 @@ void test_conf_key_info(void) const char *name; bool got_value_type : 1; bool got_subkey_type : 1; + bool got_default : 1; bool got_default_int : 1; bool got_default_str : 1; bool got_default_bool : 1; @@ -835,9 +836,9 @@ void test_conf_key_info(void) #define CONF_OPTION(id, ...) { .name = "CONF_" #id, __VA_ARGS__ }, #define VALUE_TYPE(x) .got_value_type = true #define SUBKEY_TYPE(x) .got_subkey_type = true -#define DEFAULT_INT(x) .got_default_int = true -#define DEFAULT_STR(x) .got_default_str = true -#define DEFAULT_BOOL(x) .got_default_bool = true +#define DEFAULT_INT(x) .got_default_int = true, .got_default = true +#define DEFAULT_STR(x) .got_default_str = true, .got_default = true +#define DEFAULT_BOOL(x) .got_default_bool = true, .got_default = true #define SAVE_KEYWORD(x) .got_save_keyword = true #define STORAGE_ENUM(x) .got_storage_enum = true #define SAVE_CUSTOM .save_custom = true @@ -857,6 +858,11 @@ void test_conf_key_info(void) nfails++; } + if (td->got_default && info->subkey_type != CONF_TYPE_NONE) { + fprintf(stderr, "%s: is a mapping but has a default\n", td->name); + nfails++; + } + if ((td->got_default_int && info->value_type != CONF_TYPE_INT) || (td->got_default_str && info->value_type != CONF_TYPE_STR) || (td->got_default_bool && info->value_type != CONF_TYPE_BOOL)) { @@ -871,6 +877,12 @@ void test_conf_key_info(void) } if (td->not_saved) { + if (!td->got_default && info->subkey_type == CONF_TYPE_NONE) { + fprintf(stderr, "%s: simple unsaved setting but has no " + "default\n", td->name); + nfails++; + } + if (td->got_save_keyword) { fprintf(stderr, "%s: not saved but has SAVE_KEYWORD\n", td->name);