2 * settings.c: read and write saved sessions. (platform-independent)
\r
11 /* The cipher order given here is the default order. */
\r
12 static const struct keyvalwhere ciphernames[] = {
\r
13 { "aes", CIPHER_AES, -1, -1 },
\r
14 { "chacha20", CIPHER_CHACHA20, CIPHER_AES, +1 },
\r
15 { "blowfish", CIPHER_BLOWFISH, -1, -1 },
\r
16 { "3des", CIPHER_3DES, -1, -1 },
\r
17 { "WARN", CIPHER_WARN, -1, -1 },
\r
18 { "arcfour", CIPHER_ARCFOUR, -1, -1 },
\r
19 { "des", CIPHER_DES, -1, -1 }
\r
22 /* The default order here is sometimes overridden by the backward-
\r
23 * compatibility warts in load_open_settings(), and should be kept
\r
24 * in sync with those. */
\r
25 static const struct keyvalwhere kexnames[] = {
\r
26 { "ecdh", KEX_ECDH, -1, +1 },
\r
27 /* This name is misleading: it covers both SHA-256 and SHA-1 variants */
\r
28 { "dh-gex-sha1", KEX_DHGEX, -1, -1 },
\r
29 { "dh-group14-sha1", KEX_DHGROUP14, -1, -1 },
\r
30 { "dh-group1-sha1", KEX_DHGROUP1, KEX_WARN, +1 },
\r
31 { "rsa", KEX_RSA, KEX_WARN, -1 },
\r
32 { "WARN", KEX_WARN, -1, -1 }
\r
35 static const struct keyvalwhere hknames[] = {
\r
36 { "ed25519", HK_ED25519, -1, +1 },
\r
37 { "ecdsa", HK_ECDSA, -1, -1 },
\r
38 { "dsa", HK_DSA, -1, -1 },
\r
39 { "rsa", HK_RSA, -1, -1 },
\r
40 { "WARN", HK_WARN, -1, -1 },
\r
44 * All the terminal modes that we know about for the "TerminalModes"
\r
45 * setting. (Also used by config.c for the drop-down list.)
\r
46 * This is currently precisely the same as the set in ssh.c, but could
\r
47 * in principle differ if other backends started to support tty modes
\r
48 * (e.g., the pty backend).
\r
49 * The set of modes in in this array is currently significant for
\r
50 * settings migration from old versions; if they change, review the
\r
51 * gppmap() invocation for "TerminalModes".
\r
53 const char *const ttymodes[] = {
\r
54 "INTR", "QUIT", "ERASE", "KILL", "EOF",
\r
55 "EOL", "EOL2", "START", "STOP", "SUSP",
\r
56 "DSUSP", "REPRINT", "WERASE", "LNEXT", "FLUSH",
\r
57 "SWTCH", "STATUS", "DISCARD", "IGNPAR", "PARMRK",
\r
58 "INPCK", "ISTRIP", "INLCR", "IGNCR", "ICRNL",
\r
59 "IUCLC", "IXON", "IXANY", "IXOFF", "IMAXBEL",
\r
60 "IUTF8", "ISIG", "ICANON", "XCASE", "ECHO",
\r
61 "ECHOE", "ECHOK", "ECHONL", "NOFLSH", "TOSTOP",
\r
62 "IEXTEN", "ECHOCTL", "ECHOKE", "PENDIN", "OPOST",
\r
63 "OLCUC", "ONLCR", "OCRNL", "ONOCR", "ONLRET",
\r
64 "CS7", "CS8", "PARENB", "PARODD", NULL
\r
68 * Convenience functions to access the backends[] array
\r
69 * (which is only present in tools that manage settings).
\r
72 Backend *backend_from_name(const char *name)
\r
75 for (p = backends; *p != NULL; p++)
\r
76 if (!strcmp((*p)->name, name))
\r
81 Backend *backend_from_proto(int proto)
\r
84 for (p = backends; *p != NULL; p++)
\r
85 if ((*p)->protocol == proto)
\r
90 char *get_remote_username(Conf *conf)
\r
92 char *username = conf_get_str(conf, CONF_username);
\r
94 return dupstr(username);
\r
95 } else if (conf_get_int(conf, CONF_username_from_env)) {
\r
96 /* Use local username. */
\r
97 return get_username(); /* might still be NULL */
\r
103 static char *gpps_raw(void *handle, const char *name, const char *def)
\r
105 char *ret = read_setting_s(handle, name);
\r
107 ret = platform_default_s(name);
\r
109 ret = def ? dupstr(def) : NULL; /* permit NULL as final fallback */
\r
113 static void gpps(void *handle, const char *name, const char *def,
\r
114 Conf *conf, int primary)
\r
116 char *val = gpps_raw(handle, name, def);
\r
117 conf_set_str(conf, primary, val);
\r
122 * gppfont and gppfile cannot have local defaults, since the very
\r
123 * format of a Filename or FontSpec is platform-dependent. So the
\r
124 * platform-dependent functions MUST return some sort of value.
\r
126 static void gppfont(void *handle, const char *name, Conf *conf, int primary)
\r
128 FontSpec *result = read_setting_fontspec(handle, name);
\r
130 result = platform_default_fontspec(name);
\r
131 conf_set_fontspec(conf, primary, result);
\r
132 fontspec_free(result);
\r
134 static void gppfile(void *handle, const char *name, Conf *conf, int primary)
\r
136 Filename *result = read_setting_filename(handle, name);
\r
138 result = platform_default_filename(name);
\r
139 conf_set_filename(conf, primary, result);
\r
140 filename_free(result);
\r
143 static int gppi_raw(void *handle, const char *name, int def)
\r
145 def = platform_default_i(name, def);
\r
146 return read_setting_i(handle, name, def);
\r
149 static void gppi(void *handle, const char *name, int def,
\r
150 Conf *conf, int primary)
\r
152 conf_set_int(conf, primary, gppi_raw(handle, name, def));
\r
156 * Read a set of name-value pairs in the format we occasionally use:
\r
157 * NAME\tVALUE\0NAME\tVALUE\0\0 in memory
\r
158 * NAME=VALUE,NAME=VALUE, in storage
\r
159 * If there's no "=VALUE" (e.g. just NAME,NAME,NAME) then those keys
\r
160 * are mapped to the empty string.
\r
162 static int gppmap(void *handle, const char *name, Conf *conf, int primary)
\r
164 char *buf, *p, *q, *key, *val;
\r
167 * Start by clearing any existing subkeys of this key from conf.
\r
169 while ((key = conf_get_str_nthstrkey(conf, primary, 0)) != NULL)
\r
170 conf_del_str_str(conf, primary, key);
\r
173 * Now read a serialised list from the settings and unmarshal it
\r
174 * into its components.
\r
176 buf = gpps_raw(handle, name, NULL);
\r
184 while (*p && *p != ',') {
\r
200 if (primary == CONF_portfwd && strchr(buf, 'D') != NULL) {
\r
202 * Backwards-compatibility hack: dynamic forwardings are
\r
203 * indexed in the data store as a third type letter in the
\r
204 * key, 'D' alongside 'L' and 'R' - but really, they
\r
205 * should be filed under 'L' with a special _value_,
\r
206 * because local and dynamic forwardings both involve
\r
207 * _listening_ on a local port, and are hence mutually
\r
208 * exclusive on the same port number. So here we translate
\r
209 * the legacy storage format into the sensible internal
\r
210 * form, by finding the D and turning it into a L.
\r
212 char *newkey = dupstr(buf);
\r
213 *strchr(newkey, 'D') = 'L';
\r
214 conf_set_str_str(conf, primary, newkey, "D");
\r
217 conf_set_str_str(conf, primary, buf, val);
\r
226 * Write a set of name/value pairs in the above format, or just the
\r
227 * names if include_values is FALSE.
\r
229 static void wmap(void *handle, char const *outkey, Conf *conf, int primary,
\r
230 int include_values)
\r
232 char *buf, *p, *key, *realkey;
\r
233 const char *val, *q;
\r
236 len = 1; /* allow for NUL */
\r
238 for (val = conf_get_str_strs(conf, primary, NULL, &key);
\r
240 val = conf_get_str_strs(conf, primary, key, &key))
\r
241 len += 2 + 2 * (strlen(key) + strlen(val)); /* allow for escaping */
\r
243 buf = snewn(len, char);
\r
246 for (val = conf_get_str_strs(conf, primary, NULL, &key);
\r
248 val = conf_get_str_strs(conf, primary, key, &key)) {
\r
250 if (primary == CONF_portfwd && !strcmp(val, "D")) {
\r
252 * Backwards-compatibility hack, as above: translate from
\r
253 * the sensible internal representation of dynamic
\r
254 * forwardings (key "L<port>", value "D") to the
\r
255 * conceptually incoherent legacy storage format (key
\r
256 * "D<port>", value empty).
\r
260 realkey = key; /* restore it at end of loop */
\r
263 L = strchr(key, 'L');
\r
271 for (q = key; *q; q++) {
\r
272 if (*q == '=' || *q == ',' || *q == '\\')
\r
276 if (include_values) {
\r
278 for (q = val; *q; q++) {
\r
279 if (*q == '=' || *q == ',' || *q == '\\')
\r
291 write_setting_s(handle, outkey, buf);
\r
295 static int key2val(const struct keyvalwhere *mapping,
\r
296 int nmaps, char *key)
\r
299 for (i = 0; i < nmaps; i++)
\r
300 if (!strcmp(mapping[i].s, key)) return mapping[i].v;
\r
304 static const char *val2key(const struct keyvalwhere *mapping,
\r
305 int nmaps, int val)
\r
308 for (i = 0; i < nmaps; i++)
\r
309 if (mapping[i].v == val) return mapping[i].s;
\r
314 * Helper function to parse a comma-separated list of strings into
\r
315 * a preference list array of values. Any missing values are added
\r
316 * to the end and duplicates are weeded.
\r
317 * XXX: assumes vals in 'mapping' are small +ve integers
\r
319 static void gprefs_from_str(const char *str,
\r
320 const struct keyvalwhere *mapping, int nvals,
\r
321 Conf *conf, int primary)
\r
323 char *commalist = dupstr(str);
\r
325 int i, j, n, v, pos;
\r
326 unsigned long seen = 0; /* bitmap for weeding dups etc */
\r
329 * Go through that list and convert it into values.
\r
334 while (*p && *p == ',') p++;
\r
336 break; /* no more words */
\r
339 while (*p && *p != ',') p++;
\r
340 if (*p) *p++ = '\0';
\r
342 v = key2val(mapping, nvals, q);
\r
343 if (v != -1 && !(seen & (1 << v))) {
\r
345 conf_set_int_int(conf, primary, n, v);
\r
353 * Now go through 'mapping' and add values that weren't mentioned
\r
354 * in the list we fetched. We may have to loop over it multiple
\r
355 * times so that we add values before other values whose default
\r
356 * positions depend on them.
\r
358 while (n < nvals) {
\r
359 for (i = 0; i < nvals; i++) {
\r
360 assert(mapping[i].v < 32);
\r
362 if (!(seen & (1 << mapping[i].v))) {
\r
364 * This element needs adding. But can we add it yet?
\r
366 if (mapping[i].vrel != -1 && !(seen & (1 << mapping[i].vrel)))
\r
367 continue; /* nope */
\r
370 * OK, we can work out where to add this element, so
\r
373 if (mapping[i].vrel == -1) {
\r
374 pos = (mapping[i].where < 0 ? n : 0);
\r
376 for (j = 0; j < n; j++)
\r
377 if (conf_get_int_int(conf, primary, j) ==
\r
380 assert(j < n); /* implied by (seen & (1<<vrel)) */
\r
381 pos = (mapping[i].where < 0 ? j : j+1);
\r
387 for (j = n-1; j >= pos; j--)
\r
388 conf_set_int_int(conf, primary, j+1,
\r
389 conf_get_int_int(conf, primary, j));
\r
390 conf_set_int_int(conf, primary, pos, mapping[i].v);
\r
391 seen |= (1 << mapping[i].v);
\r
399 * Read a preference list.
\r
401 static void gprefs(void *sesskey, const char *name, const char *def,
\r
402 const struct keyvalwhere *mapping, int nvals,
\r
403 Conf *conf, int primary)
\r
406 * Fetch the string which we'll parse as a comma-separated list.
\r
408 char *value = gpps_raw(sesskey, name, def);
\r
409 gprefs_from_str(value, mapping, nvals, conf, primary);
\r
414 * Write out a preference list.
\r
416 static void wprefs(void *sesskey, const char *name,
\r
417 const struct keyvalwhere *mapping, int nvals,
\r
418 Conf *conf, int primary)
\r
423 for (maxlen = i = 0; i < nvals; i++) {
\r
424 const char *s = val2key(mapping, nvals,
\r
425 conf_get_int_int(conf, primary, i));
\r
427 maxlen += (maxlen > 0 ? 1 : 0) + strlen(s);
\r
431 buf = snewn(maxlen + 1, char);
\r
434 for (i = 0; i < nvals; i++) {
\r
435 const char *s = val2key(mapping, nvals,
\r
436 conf_get_int_int(conf, primary, i));
\r
438 p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);
\r
442 assert(p - buf == maxlen);
\r
445 write_setting_s(sesskey, name, buf);
\r
450 char *save_settings(const char *section, Conf *conf)
\r
455 sesskey = open_settings_w(section, &errmsg);
\r
458 save_open_settings(sesskey, conf);
\r
459 close_settings_w(sesskey);
\r
463 void save_open_settings(void *sesskey, Conf *conf)
\r
468 write_setting_i(sesskey, "Present", 1);
\r
469 write_setting_s(sesskey, "HostName", conf_get_str(conf, CONF_host));
\r
470 write_setting_filename(sesskey, "LogFileName", conf_get_filename(conf, CONF_logfilename));
\r
471 write_setting_i(sesskey, "LogType", conf_get_int(conf, CONF_logtype));
\r
472 write_setting_i(sesskey, "LogFileClash", conf_get_int(conf, CONF_logxfovr));
\r
473 write_setting_i(sesskey, "LogFlush", conf_get_int(conf, CONF_logflush));
\r
474 write_setting_i(sesskey, "SSHLogOmitPasswords", conf_get_int(conf, CONF_logomitpass));
\r
475 write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata));
\r
478 const Backend *b = backend_from_proto(conf_get_int(conf, CONF_protocol));
\r
482 write_setting_s(sesskey, "Protocol", p);
\r
483 write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));
\r
484 /* The CloseOnExit numbers are arranged in a different order from
\r
485 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
486 write_setting_i(sesskey, "CloseOnExit", (conf_get_int(conf, CONF_close_on_exit)+2)%3);
\r
487 write_setting_i(sesskey, "WarnOnClose", !!conf_get_int(conf, CONF_warn_on_close));
\r
488 write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60); /* minutes */
\r
489 write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60); /* seconds */
\r
490 write_setting_i(sesskey, "TCPNoDelay", conf_get_int(conf, CONF_tcp_nodelay));
\r
491 write_setting_i(sesskey, "TCPKeepalives", conf_get_int(conf, CONF_tcp_keepalives));
\r
492 write_setting_s(sesskey, "TerminalType", conf_get_str(conf, CONF_termtype));
\r
493 write_setting_s(sesskey, "TerminalSpeed", conf_get_str(conf, CONF_termspeed));
\r
494 wmap(sesskey, "TerminalModes", conf, CONF_ttymodes, TRUE);
\r
496 /* Address family selection */
\r
497 write_setting_i(sesskey, "AddressFamily", conf_get_int(conf, CONF_addressfamily));
\r
499 /* proxy settings */
\r
500 write_setting_s(sesskey, "ProxyExcludeList", conf_get_str(conf, CONF_proxy_exclude_list));
\r
501 write_setting_i(sesskey, "ProxyDNS", (conf_get_int(conf, CONF_proxy_dns)+2)%3);
\r
502 write_setting_i(sesskey, "ProxyLocalhost", conf_get_int(conf, CONF_even_proxy_localhost));
\r
503 write_setting_i(sesskey, "ProxyMethod", conf_get_int(conf, CONF_proxy_type));
\r
504 write_setting_s(sesskey, "ProxyHost", conf_get_str(conf, CONF_proxy_host));
\r
505 write_setting_i(sesskey, "ProxyPort", conf_get_int(conf, CONF_proxy_port));
\r
506 write_setting_s(sesskey, "ProxyUsername", conf_get_str(conf, CONF_proxy_username));
\r
507 write_setting_s(sesskey, "ProxyPassword", conf_get_str(conf, CONF_proxy_password));
\r
508 write_setting_s(sesskey, "ProxyTelnetCommand", conf_get_str(conf, CONF_proxy_telnet_command));
\r
509 write_setting_i(sesskey, "ProxyLogToTerm", conf_get_int(conf, CONF_proxy_log_to_term));
\r
510 wmap(sesskey, "Environment", conf, CONF_environmt, TRUE);
\r
511 write_setting_s(sesskey, "UserName", conf_get_str(conf, CONF_username));
\r
512 write_setting_i(sesskey, "UserNameFromEnvironment", conf_get_int(conf, CONF_username_from_env));
\r
513 write_setting_s(sesskey, "LocalUserName", conf_get_str(conf, CONF_localusername));
\r
514 write_setting_i(sesskey, "NoPTY", conf_get_int(conf, CONF_nopty));
\r
515 write_setting_i(sesskey, "Compression", conf_get_int(conf, CONF_compression));
\r
516 write_setting_i(sesskey, "TryAgent", conf_get_int(conf, CONF_tryagent));
\r
517 write_setting_i(sesskey, "AgentFwd", conf_get_int(conf, CONF_agentfwd));
\r
518 write_setting_i(sesskey, "GssapiFwd", conf_get_int(conf, CONF_gssapifwd));
\r
519 write_setting_i(sesskey, "ChangeUsername", conf_get_int(conf, CONF_change_username));
\r
520 wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
\r
521 wprefs(sesskey, "KEX", kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
\r
522 wprefs(sesskey, "HostKey", hknames, HK_MAX, conf, CONF_ssh_hklist);
\r
523 write_setting_i(sesskey, "RekeyTime", conf_get_int(conf, CONF_ssh_rekey_time));
\r
524 write_setting_s(sesskey, "RekeyBytes", conf_get_str(conf, CONF_ssh_rekey_data));
\r
525 write_setting_i(sesskey, "SshNoAuth", conf_get_int(conf, CONF_ssh_no_userauth));
\r
526 write_setting_i(sesskey, "SshBanner", conf_get_int(conf, CONF_ssh_show_banner));
\r
527 write_setting_i(sesskey, "AuthTIS", conf_get_int(conf, CONF_try_tis_auth));
\r
528 write_setting_i(sesskey, "AuthKI", conf_get_int(conf, CONF_try_ki_auth));
\r
529 write_setting_i(sesskey, "AuthGSSAPI", conf_get_int(conf, CONF_try_gssapi_auth));
\r
531 wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
\r
532 write_setting_filename(sesskey, "GSSCustom", conf_get_filename(conf, CONF_ssh_gss_custom));
\r
534 write_setting_i(sesskey, "SshNoShell", conf_get_int(conf, CONF_ssh_no_shell));
\r
535 write_setting_i(sesskey, "SshProt", conf_get_int(conf, CONF_sshprot));
\r
536 write_setting_s(sesskey, "LogHost", conf_get_str(conf, CONF_loghost));
\r
537 write_setting_i(sesskey, "SSH2DES", conf_get_int(conf, CONF_ssh2_des_cbc));
\r
538 write_setting_filename(sesskey, "PublicKeyFile", conf_get_filename(conf, CONF_keyfile));
\r
539 write_setting_s(sesskey, "RemoteCommand", conf_get_str(conf, CONF_remote_cmd));
\r
540 write_setting_i(sesskey, "RFCEnviron", conf_get_int(conf, CONF_rfc_environ));
\r
541 write_setting_i(sesskey, "PassiveTelnet", conf_get_int(conf, CONF_passive_telnet));
\r
542 write_setting_i(sesskey, "BackspaceIsDelete", conf_get_int(conf, CONF_bksp_is_delete));
\r
543 write_setting_i(sesskey, "RXVTHomeEnd", conf_get_int(conf, CONF_rxvt_homeend));
\r
544 write_setting_i(sesskey, "LinuxFunctionKeys", conf_get_int(conf, CONF_funky_type));
\r
545 write_setting_i(sesskey, "NoApplicationKeys", conf_get_int(conf, CONF_no_applic_k));
\r
546 write_setting_i(sesskey, "NoApplicationCursors", conf_get_int(conf, CONF_no_applic_c));
\r
547 write_setting_i(sesskey, "NoMouseReporting", conf_get_int(conf, CONF_no_mouse_rep));
\r
548 write_setting_i(sesskey, "NoRemoteResize", conf_get_int(conf, CONF_no_remote_resize));
\r
549 write_setting_i(sesskey, "NoAltScreen", conf_get_int(conf, CONF_no_alt_screen));
\r
550 write_setting_i(sesskey, "NoRemoteWinTitle", conf_get_int(conf, CONF_no_remote_wintitle));
\r
551 write_setting_i(sesskey, "NoRemoteClearScroll", conf_get_int(conf, CONF_no_remote_clearscroll));
\r
552 write_setting_i(sesskey, "RemoteQTitleAction", conf_get_int(conf, CONF_remote_qtitle_action));
\r
553 write_setting_i(sesskey, "NoDBackspace", conf_get_int(conf, CONF_no_dbackspace));
\r
554 write_setting_i(sesskey, "NoRemoteCharset", conf_get_int(conf, CONF_no_remote_charset));
\r
555 write_setting_i(sesskey, "ApplicationCursorKeys", conf_get_int(conf, CONF_app_cursor));
\r
556 write_setting_i(sesskey, "ApplicationKeypad", conf_get_int(conf, CONF_app_keypad));
\r
557 write_setting_i(sesskey, "NetHackKeypad", conf_get_int(conf, CONF_nethack_keypad));
\r
558 write_setting_i(sesskey, "AltF4", conf_get_int(conf, CONF_alt_f4));
\r
559 write_setting_i(sesskey, "AltSpace", conf_get_int(conf, CONF_alt_space));
\r
560 write_setting_i(sesskey, "AltOnly", conf_get_int(conf, CONF_alt_only));
\r
561 write_setting_i(sesskey, "ComposeKey", conf_get_int(conf, CONF_compose_key));
\r
562 write_setting_i(sesskey, "CtrlAltKeys", conf_get_int(conf, CONF_ctrlaltkeys));
\r
563 #ifdef OSX_META_KEY_CONFIG
\r
564 write_setting_i(sesskey, "OSXOptionMeta", conf_get_int(conf, CONF_osx_option_meta));
\r
565 write_setting_i(sesskey, "OSXCommandMeta", conf_get_int(conf, CONF_osx_command_meta));
\r
567 write_setting_i(sesskey, "TelnetKey", conf_get_int(conf, CONF_telnet_keyboard));
\r
568 write_setting_i(sesskey, "TelnetRet", conf_get_int(conf, CONF_telnet_newline));
\r
569 write_setting_i(sesskey, "LocalEcho", conf_get_int(conf, CONF_localecho));
\r
570 write_setting_i(sesskey, "LocalEdit", conf_get_int(conf, CONF_localedit));
\r
571 write_setting_s(sesskey, "Answerback", conf_get_str(conf, CONF_answerback));
\r
572 write_setting_i(sesskey, "AlwaysOnTop", conf_get_int(conf, CONF_alwaysontop));
\r
573 write_setting_i(sesskey, "FullScreenOnAltEnter", conf_get_int(conf, CONF_fullscreenonaltenter));
\r
574 write_setting_i(sesskey, "HideMousePtr", conf_get_int(conf, CONF_hide_mouseptr));
\r
575 write_setting_i(sesskey, "SunkenEdge", conf_get_int(conf, CONF_sunken_edge));
\r
576 write_setting_i(sesskey, "WindowBorder", conf_get_int(conf, CONF_window_border));
\r
577 write_setting_i(sesskey, "CurType", conf_get_int(conf, CONF_cursor_type));
\r
578 write_setting_i(sesskey, "BlinkCur", conf_get_int(conf, CONF_blink_cur));
\r
579 write_setting_i(sesskey, "Beep", conf_get_int(conf, CONF_beep));
\r
580 write_setting_i(sesskey, "BeepInd", conf_get_int(conf, CONF_beep_ind));
\r
581 write_setting_filename(sesskey, "BellWaveFile", conf_get_filename(conf, CONF_bell_wavefile));
\r
582 write_setting_i(sesskey, "BellOverload", conf_get_int(conf, CONF_bellovl));
\r
583 write_setting_i(sesskey, "BellOverloadN", conf_get_int(conf, CONF_bellovl_n));
\r
584 write_setting_i(sesskey, "BellOverloadT", conf_get_int(conf, CONF_bellovl_t)
\r
585 #ifdef PUTTY_UNIX_H
\r
589 write_setting_i(sesskey, "BellOverloadS", conf_get_int(conf, CONF_bellovl_s)
\r
590 #ifdef PUTTY_UNIX_H
\r
594 write_setting_i(sesskey, "ScrollbackLines", conf_get_int(conf, CONF_savelines));
\r
595 write_setting_i(sesskey, "DECOriginMode", conf_get_int(conf, CONF_dec_om));
\r
596 write_setting_i(sesskey, "AutoWrapMode", conf_get_int(conf, CONF_wrap_mode));
\r
597 write_setting_i(sesskey, "LFImpliesCR", conf_get_int(conf, CONF_lfhascr));
\r
598 write_setting_i(sesskey, "CRImpliesLF", conf_get_int(conf, CONF_crhaslf));
\r
599 write_setting_i(sesskey, "DisableArabicShaping", conf_get_int(conf, CONF_arabicshaping));
\r
600 write_setting_i(sesskey, "DisableBidi", conf_get_int(conf, CONF_bidi));
\r
601 write_setting_i(sesskey, "WinNameAlways", conf_get_int(conf, CONF_win_name_always));
\r
602 write_setting_s(sesskey, "WinTitle", conf_get_str(conf, CONF_wintitle));
\r
603 write_setting_i(sesskey, "TermWidth", conf_get_int(conf, CONF_width));
\r
604 write_setting_i(sesskey, "TermHeight", conf_get_int(conf, CONF_height));
\r
605 write_setting_fontspec(sesskey, "Font", conf_get_fontspec(conf, CONF_font));
\r
606 write_setting_i(sesskey, "FontQuality", conf_get_int(conf, CONF_font_quality));
\r
607 write_setting_i(sesskey, "FontVTMode", conf_get_int(conf, CONF_vtmode));
\r
608 write_setting_i(sesskey, "UseSystemColours", conf_get_int(conf, CONF_system_colour));
\r
609 write_setting_i(sesskey, "TryPalette", conf_get_int(conf, CONF_try_palette));
\r
610 write_setting_i(sesskey, "ANSIColour", conf_get_int(conf, CONF_ansi_colour));
\r
611 write_setting_i(sesskey, "Xterm256Colour", conf_get_int(conf, CONF_xterm_256_colour));
\r
612 write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_style)-1);
\r
614 for (i = 0; i < 22; i++) {
\r
615 char buf[20], buf2[30];
\r
616 sprintf(buf, "Colour%d", i);
\r
617 sprintf(buf2, "%d,%d,%d",
\r
618 conf_get_int_int(conf, CONF_colours, i*3+0),
\r
619 conf_get_int_int(conf, CONF_colours, i*3+1),
\r
620 conf_get_int_int(conf, CONF_colours, i*3+2));
\r
621 write_setting_s(sesskey, buf, buf2);
\r
623 write_setting_i(sesskey, "RawCNP", conf_get_int(conf, CONF_rawcnp));
\r
624 write_setting_i(sesskey, "PasteRTF", conf_get_int(conf, CONF_rtf_paste));
\r
625 write_setting_i(sesskey, "MouseIsXterm", conf_get_int(conf, CONF_mouse_is_xterm));
\r
626 write_setting_i(sesskey, "RectSelect", conf_get_int(conf, CONF_rect_select));
\r
627 write_setting_i(sesskey, "MouseOverride", conf_get_int(conf, CONF_mouse_override));
\r
628 for (i = 0; i < 256; i += 32) {
\r
629 char buf[20], buf2[256];
\r
631 sprintf(buf, "Wordness%d", i);
\r
633 for (j = i; j < i + 32; j++) {
\r
634 sprintf(buf2 + strlen(buf2), "%s%d",
\r
635 (*buf2 ? "," : ""),
\r
636 conf_get_int_int(conf, CONF_wordness, j));
\r
638 write_setting_s(sesskey, buf, buf2);
\r
640 write_setting_s(sesskey, "LineCodePage", conf_get_str(conf, CONF_line_codepage));
\r
641 write_setting_i(sesskey, "CJKAmbigWide", conf_get_int(conf, CONF_cjk_ambig_wide));
\r
642 write_setting_i(sesskey, "UTF8Override", conf_get_int(conf, CONF_utf8_override));
\r
643 write_setting_s(sesskey, "Printer", conf_get_str(conf, CONF_printer));
\r
644 write_setting_i(sesskey, "CapsLockCyr", conf_get_int(conf, CONF_xlat_capslockcyr));
\r
645 write_setting_i(sesskey, "ScrollBar", conf_get_int(conf, CONF_scrollbar));
\r
646 write_setting_i(sesskey, "ScrollBarFullScreen", conf_get_int(conf, CONF_scrollbar_in_fullscreen));
\r
647 write_setting_i(sesskey, "ScrollOnKey", conf_get_int(conf, CONF_scroll_on_key));
\r
648 write_setting_i(sesskey, "ScrollOnDisp", conf_get_int(conf, CONF_scroll_on_disp));
\r
649 write_setting_i(sesskey, "EraseToScrollback", conf_get_int(conf, CONF_erase_to_scrollback));
\r
650 write_setting_i(sesskey, "LockSize", conf_get_int(conf, CONF_resize_action));
\r
651 write_setting_i(sesskey, "BCE", conf_get_int(conf, CONF_bce));
\r
652 write_setting_i(sesskey, "BlinkText", conf_get_int(conf, CONF_blinktext));
\r
653 write_setting_i(sesskey, "X11Forward", conf_get_int(conf, CONF_x11_forward));
\r
654 write_setting_s(sesskey, "X11Display", conf_get_str(conf, CONF_x11_display));
\r
655 write_setting_i(sesskey, "X11AuthType", conf_get_int(conf, CONF_x11_auth));
\r
656 write_setting_filename(sesskey, "X11AuthFile", conf_get_filename(conf, CONF_xauthfile));
\r
657 write_setting_i(sesskey, "LocalPortAcceptAll", conf_get_int(conf, CONF_lport_acceptall));
\r
658 write_setting_i(sesskey, "RemotePortAcceptAll", conf_get_int(conf, CONF_rport_acceptall));
\r
659 wmap(sesskey, "PortForwardings", conf, CONF_portfwd, TRUE);
\r
660 write_setting_i(sesskey, "BugIgnore1", 2-conf_get_int(conf, CONF_sshbug_ignore1));
\r
661 write_setting_i(sesskey, "BugPlainPW1", 2-conf_get_int(conf, CONF_sshbug_plainpw1));
\r
662 write_setting_i(sesskey, "BugRSA1", 2-conf_get_int(conf, CONF_sshbug_rsa1));
\r
663 write_setting_i(sesskey, "BugIgnore2", 2-conf_get_int(conf, CONF_sshbug_ignore2));
\r
664 write_setting_i(sesskey, "BugHMAC2", 2-conf_get_int(conf, CONF_sshbug_hmac2));
\r
665 write_setting_i(sesskey, "BugDeriveKey2", 2-conf_get_int(conf, CONF_sshbug_derivekey2));
\r
666 write_setting_i(sesskey, "BugRSAPad2", 2-conf_get_int(conf, CONF_sshbug_rsapad2));
\r
667 write_setting_i(sesskey, "BugPKSessID2", 2-conf_get_int(conf, CONF_sshbug_pksessid2));
\r
668 write_setting_i(sesskey, "BugRekey2", 2-conf_get_int(conf, CONF_sshbug_rekey2));
\r
669 write_setting_i(sesskey, "BugMaxPkt2", 2-conf_get_int(conf, CONF_sshbug_maxpkt2));
\r
670 write_setting_i(sesskey, "BugOldGex2", 2-conf_get_int(conf, CONF_sshbug_oldgex2));
\r
671 write_setting_i(sesskey, "BugWinadj", 2-conf_get_int(conf, CONF_sshbug_winadj));
\r
672 write_setting_i(sesskey, "BugChanReq", 2-conf_get_int(conf, CONF_sshbug_chanreq));
\r
673 write_setting_i(sesskey, "StampUtmp", conf_get_int(conf, CONF_stamp_utmp));
\r
674 write_setting_i(sesskey, "LoginShell", conf_get_int(conf, CONF_login_shell));
\r
675 write_setting_i(sesskey, "ScrollbarOnLeft", conf_get_int(conf, CONF_scrollbar_on_left));
\r
676 write_setting_fontspec(sesskey, "BoldFont", conf_get_fontspec(conf, CONF_boldfont));
\r
677 write_setting_fontspec(sesskey, "WideFont", conf_get_fontspec(conf, CONF_widefont));
\r
678 write_setting_fontspec(sesskey, "WideBoldFont", conf_get_fontspec(conf, CONF_wideboldfont));
\r
679 write_setting_i(sesskey, "ShadowBold", conf_get_int(conf, CONF_shadowbold));
\r
680 write_setting_i(sesskey, "ShadowBoldOffset", conf_get_int(conf, CONF_shadowboldoffset));
\r
681 write_setting_s(sesskey, "SerialLine", conf_get_str(conf, CONF_serline));
\r
682 write_setting_i(sesskey, "SerialSpeed", conf_get_int(conf, CONF_serspeed));
\r
683 write_setting_i(sesskey, "SerialDataBits", conf_get_int(conf, CONF_serdatabits));
\r
684 write_setting_i(sesskey, "SerialStopHalfbits", conf_get_int(conf, CONF_serstopbits));
\r
685 write_setting_i(sesskey, "SerialParity", conf_get_int(conf, CONF_serparity));
\r
686 write_setting_i(sesskey, "SerialFlowControl", conf_get_int(conf, CONF_serflow));
\r
687 write_setting_s(sesskey, "WindowClass", conf_get_str(conf, CONF_winclass));
\r
688 write_setting_i(sesskey, "ConnectionSharing", conf_get_int(conf, CONF_ssh_connection_sharing));
\r
689 write_setting_i(sesskey, "ConnectionSharingUpstream", conf_get_int(conf, CONF_ssh_connection_sharing_upstream));
\r
690 write_setting_i(sesskey, "ConnectionSharingDownstream", conf_get_int(conf, CONF_ssh_connection_sharing_downstream));
\r
691 wmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys, FALSE);
\r
694 void load_settings(const char *section, Conf *conf)
\r
698 sesskey = open_settings_r(section);
\r
699 load_open_settings(sesskey, conf);
\r
700 close_settings_r(sesskey);
\r
702 if (conf_launchable(conf))
\r
703 add_session_to_jumplist(section);
\r
706 void load_open_settings(void *sesskey, Conf *conf)
\r
711 conf_set_int(conf, CONF_ssh_subsys, 0); /* FIXME: load this properly */
\r
712 conf_set_str(conf, CONF_remote_cmd, "");
\r
713 conf_set_str(conf, CONF_remote_cmd2, "");
\r
714 conf_set_str(conf, CONF_ssh_nc_host, "");
\r
716 gpps(sesskey, "HostName", "", conf, CONF_host);
\r
717 gppfile(sesskey, "LogFileName", conf, CONF_logfilename);
\r
718 gppi(sesskey, "LogType", 0, conf, CONF_logtype);
\r
719 gppi(sesskey, "LogFileClash", LGXF_ASK, conf, CONF_logxfovr);
\r
720 gppi(sesskey, "LogFlush", 1, conf, CONF_logflush);
\r
721 gppi(sesskey, "SSHLogOmitPasswords", 1, conf, CONF_logomitpass);
\r
722 gppi(sesskey, "SSHLogOmitData", 0, conf, CONF_logomitdata);
\r
724 prot = gpps_raw(sesskey, "Protocol", "default");
\r
725 conf_set_int(conf, CONF_protocol, default_protocol);
\r
726 conf_set_int(conf, CONF_port, default_port);
\r
728 const Backend *b = backend_from_name(prot);
\r
730 conf_set_int(conf, CONF_protocol, b->protocol);
\r
731 gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
\r
736 /* Address family selection */
\r
737 gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, conf, CONF_addressfamily);
\r
739 /* The CloseOnExit numbers are arranged in a different order from
\r
740 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
741 i = gppi_raw(sesskey, "CloseOnExit", 1); conf_set_int(conf, CONF_close_on_exit, (i+1)%3);
\r
742 gppi(sesskey, "WarnOnClose", 1, conf, CONF_warn_on_close);
\r
744 /* This is two values for backward compatibility with 0.50/0.51 */
\r
745 int pingmin, pingsec;
\r
746 pingmin = gppi_raw(sesskey, "PingInterval", 0);
\r
747 pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);
\r
748 conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);
\r
750 gppi(sesskey, "TCPNoDelay", 1, conf, CONF_tcp_nodelay);
\r
751 gppi(sesskey, "TCPKeepalives", 0, conf, CONF_tcp_keepalives);
\r
752 gpps(sesskey, "TerminalType", "xterm", conf, CONF_termtype);
\r
753 gpps(sesskey, "TerminalSpeed", "38400,38400", conf, CONF_termspeed);
\r
754 if (gppmap(sesskey, "TerminalModes", conf, CONF_ttymodes)) {
\r
756 * Backwards compatibility with old saved settings.
\r
758 * From the invention of this setting through 0.67, the set of
\r
759 * terminal modes was fixed, and absence of a mode from this
\r
760 * setting meant the user had explicitly removed it from the
\r
761 * UI and we shouldn't send it.
\r
763 * In 0.68, the IUTF8 mode was added, and in handling old
\r
764 * settings we inadvertently removed the ability to not send
\r
765 * a mode. Any mode not mentioned was treated as if it was
\r
766 * set to 'auto' (A).
\r
768 * After 0.68, we added explicit notation to the setting format
\r
769 * when the user removes a known terminal mode from the list.
\r
771 * So: if any of the modes from the original set is missing, we
\r
772 * assume this was an intentional removal by the user and add
\r
773 * an explicit removal ('N'); but if IUTF8 (or any other mode
\r
774 * added after 0.67) is missing, we assume that its absence is
\r
775 * due to the setting being old rather than intentional, and
\r
776 * add it with its default setting.
\r
778 * (This does mean that if a 0.68 user explicitly removed IUTF8,
\r
779 * we add it back; but removing IUTF8 had no effect in 0.68, so
\r
780 * we're preserving behaviour, which is the best we can do.)
\r
782 for (i = 0; ttymodes[i]; i++) {
\r
783 if (!conf_get_str_str_opt(conf, CONF_ttymodes, ttymodes[i])) {
\r
784 /* Mode not mentioned in setting. */
\r
786 if (!strcmp(ttymodes[i], "IUTF8")) {
\r
787 /* Any new modes we add in future should be treated
\r
789 def = "A"; /* same as new-setting default below */
\r
791 /* One of the original modes. Absence is probably
\r
793 def = "N"; /* don't send */
\r
795 conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], def);
\r
799 /* This hardcodes a big set of defaults in any new saved
\r
800 * sessions. Let's hope we don't change our mind. */
\r
801 for (i = 0; ttymodes[i]; i++)
\r
802 conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");
\r
805 /* proxy settings */
\r
806 gpps(sesskey, "ProxyExcludeList", "", conf, CONF_proxy_exclude_list);
\r
807 i = gppi_raw(sesskey, "ProxyDNS", 1); conf_set_int(conf, CONF_proxy_dns, (i+1)%3);
\r
808 gppi(sesskey, "ProxyLocalhost", 0, conf, CONF_even_proxy_localhost);
\r
809 gppi(sesskey, "ProxyMethod", -1, conf, CONF_proxy_type);
\r
810 if (conf_get_int(conf, CONF_proxy_type) == -1) {
\r
812 i = gppi_raw(sesskey, "ProxyType", 0);
\r
814 conf_set_int(conf, CONF_proxy_type, PROXY_NONE);
\r
816 conf_set_int(conf, CONF_proxy_type, PROXY_HTTP);
\r
818 conf_set_int(conf, CONF_proxy_type, PROXY_TELNET);
\r
820 conf_set_int(conf, CONF_proxy_type, PROXY_CMD);
\r
822 i = gppi_raw(sesskey, "ProxySOCKSVersion", 5);
\r
824 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS5);
\r
826 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS4);
\r
829 gpps(sesskey, "ProxyHost", "proxy", conf, CONF_proxy_host);
\r
830 gppi(sesskey, "ProxyPort", 80, conf, CONF_proxy_port);
\r
831 gpps(sesskey, "ProxyUsername", "", conf, CONF_proxy_username);
\r
832 gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);
\r
833 gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
\r
834 conf, CONF_proxy_telnet_command);
\r
835 gppi(sesskey, "ProxyLogToTerm", FORCE_OFF, conf, CONF_proxy_log_to_term);
\r
836 gppmap(sesskey, "Environment", conf, CONF_environmt);
\r
837 gpps(sesskey, "UserName", "", conf, CONF_username);
\r
838 gppi(sesskey, "UserNameFromEnvironment", 0, conf, CONF_username_from_env);
\r
839 gpps(sesskey, "LocalUserName", "", conf, CONF_localusername);
\r
840 gppi(sesskey, "NoPTY", 0, conf, CONF_nopty);
\r
841 gppi(sesskey, "Compression", 0, conf, CONF_compression);
\r
842 gppi(sesskey, "TryAgent", 1, conf, CONF_tryagent);
\r
843 gppi(sesskey, "AgentFwd", 0, conf, CONF_agentfwd);
\r
844 gppi(sesskey, "ChangeUsername", 0, conf, CONF_change_username);
\r
845 gppi(sesskey, "GssapiFwd", 0, conf, CONF_gssapifwd);
\r
846 gprefs(sesskey, "Cipher", "\0",
\r
847 ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
\r
849 /* Backward-compatibility: before 0.58 (when the "KEX"
\r
850 * preference was first added), we had an option to
\r
851 * disable gex under the "bugs" panel after one report of
\r
852 * a server which offered it then choked, but we never got
\r
853 * a server version string or any other reports. */
\r
854 const char *default_kexes,
\r
855 *normal_default = "ecdh,dh-gex-sha1,dh-group14-sha1,rsa,"
\r
856 "WARN,dh-group1-sha1",
\r
857 *bugdhgex2_default = "ecdh,dh-group14-sha1,rsa,"
\r
858 "WARN,dh-group1-sha1,dh-gex-sha1";
\r
860 i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);
\r
862 default_kexes = bugdhgex2_default;
\r
864 default_kexes = normal_default;
\r
865 /* Migration: after 0.67 we decided we didn't like
\r
866 * dh-group1-sha1. If it looks like the user never changed
\r
867 * the defaults, quietly upgrade their settings to demote it.
\r
868 * (If they did, they're on their own.) */
\r
869 raw = gpps_raw(sesskey, "KEX", default_kexes);
\r
870 assert(raw != NULL);
\r
871 /* Lack of 'ecdh' tells us this was saved by 0.58-0.67
\r
872 * inclusive. If it was saved by a later version, we need
\r
873 * to leave it alone. */
\r
874 if (strcmp(raw, "dh-group14-sha1,dh-group1-sha1,rsa,"
\r
875 "WARN,dh-gex-sha1") == 0) {
\r
876 /* Previously migrated from BugDHGEx2. */
\r
878 raw = dupstr(bugdhgex2_default);
\r
879 } else if (strcmp(raw, "dh-gex-sha1,dh-group14-sha1,"
\r
880 "dh-group1-sha1,rsa,WARN") == 0) {
\r
881 /* Untouched old default setting. */
\r
883 raw = dupstr(normal_default);
\r
885 gprefs_from_str(raw, kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
\r
888 gprefs(sesskey, "HostKey", "ed25519,ecdsa,rsa,dsa,WARN",
\r
889 hknames, HK_MAX, conf, CONF_ssh_hklist);
\r
890 gppi(sesskey, "RekeyTime", 60, conf, CONF_ssh_rekey_time);
\r
891 gpps(sesskey, "RekeyBytes", "1G", conf, CONF_ssh_rekey_data);
\r
893 /* SSH-2 only by default */
\r
894 int sshprot = gppi_raw(sesskey, "SshProt", 3);
\r
895 /* Old sessions may contain the values corresponding to the fallbacks
\r
896 * we used to allow; migrate them */
\r
897 if (sshprot == 1) sshprot = 0; /* => "SSH-1 only" */
\r
898 else if (sshprot == 2) sshprot = 3; /* => "SSH-2 only" */
\r
899 conf_set_int(conf, CONF_sshprot, sshprot);
\r
901 gpps(sesskey, "LogHost", "", conf, CONF_loghost);
\r
902 gppi(sesskey, "SSH2DES", 0, conf, CONF_ssh2_des_cbc);
\r
903 gppi(sesskey, "SshNoAuth", 0, conf, CONF_ssh_no_userauth);
\r
904 gppi(sesskey, "SshBanner", 1, conf, CONF_ssh_show_banner);
\r
905 gppi(sesskey, "AuthTIS", 0, conf, CONF_try_tis_auth);
\r
906 gppi(sesskey, "AuthKI", 1, conf, CONF_try_ki_auth);
\r
907 gppi(sesskey, "AuthGSSAPI", 1, conf, CONF_try_gssapi_auth);
\r
909 gprefs(sesskey, "GSSLibs", "\0",
\r
910 gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
\r
911 gppfile(sesskey, "GSSCustom", conf, CONF_ssh_gss_custom);
\r
913 gppi(sesskey, "SshNoShell", 0, conf, CONF_ssh_no_shell);
\r
914 gppfile(sesskey, "PublicKeyFile", conf, CONF_keyfile);
\r
915 gpps(sesskey, "RemoteCommand", "", conf, CONF_remote_cmd);
\r
916 gppi(sesskey, "RFCEnviron", 0, conf, CONF_rfc_environ);
\r
917 gppi(sesskey, "PassiveTelnet", 0, conf, CONF_passive_telnet);
\r
918 gppi(sesskey, "BackspaceIsDelete", 1, conf, CONF_bksp_is_delete);
\r
919 gppi(sesskey, "RXVTHomeEnd", 0, conf, CONF_rxvt_homeend);
\r
920 gppi(sesskey, "LinuxFunctionKeys", 0, conf, CONF_funky_type);
\r
921 gppi(sesskey, "NoApplicationKeys", 0, conf, CONF_no_applic_k);
\r
922 gppi(sesskey, "NoApplicationCursors", 0, conf, CONF_no_applic_c);
\r
923 gppi(sesskey, "NoMouseReporting", 0, conf, CONF_no_mouse_rep);
\r
924 gppi(sesskey, "NoRemoteResize", 0, conf, CONF_no_remote_resize);
\r
925 gppi(sesskey, "NoAltScreen", 0, conf, CONF_no_alt_screen);
\r
926 gppi(sesskey, "NoRemoteWinTitle", 0, conf, CONF_no_remote_wintitle);
\r
927 gppi(sesskey, "NoRemoteClearScroll", 0, conf, CONF_no_remote_clearscroll);
\r
929 /* Backward compatibility */
\r
930 int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);
\r
931 /* We deliberately interpret the old setting of "no response" as
\r
932 * "empty string". This changes the behaviour, but hopefully for
\r
933 * the better; the user can always recover the old behaviour. */
\r
934 gppi(sesskey, "RemoteQTitleAction",
\r
935 no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
\r
936 conf, CONF_remote_qtitle_action);
\r
938 gppi(sesskey, "NoDBackspace", 0, conf, CONF_no_dbackspace);
\r
939 gppi(sesskey, "NoRemoteCharset", 0, conf, CONF_no_remote_charset);
\r
940 gppi(sesskey, "ApplicationCursorKeys", 0, conf, CONF_app_cursor);
\r
941 gppi(sesskey, "ApplicationKeypad", 0, conf, CONF_app_keypad);
\r
942 gppi(sesskey, "NetHackKeypad", 0, conf, CONF_nethack_keypad);
\r
943 gppi(sesskey, "AltF4", 1, conf, CONF_alt_f4);
\r
944 gppi(sesskey, "AltSpace", 0, conf, CONF_alt_space);
\r
945 gppi(sesskey, "AltOnly", 0, conf, CONF_alt_only);
\r
946 gppi(sesskey, "ComposeKey", 0, conf, CONF_compose_key);
\r
947 gppi(sesskey, "CtrlAltKeys", 1, conf, CONF_ctrlaltkeys);
\r
948 #ifdef OSX_META_KEY_CONFIG
\r
949 gppi(sesskey, "OSXOptionMeta", 1, conf, CONF_osx_option_meta);
\r
950 gppi(sesskey, "OSXCommandMeta", 0, conf, CONF_osx_command_meta);
\r
952 gppi(sesskey, "TelnetKey", 0, conf, CONF_telnet_keyboard);
\r
953 gppi(sesskey, "TelnetRet", 1, conf, CONF_telnet_newline);
\r
954 gppi(sesskey, "LocalEcho", AUTO, conf, CONF_localecho);
\r
955 gppi(sesskey, "LocalEdit", AUTO, conf, CONF_localedit);
\r
956 gpps(sesskey, "Answerback", "PuTTY", conf, CONF_answerback);
\r
957 gppi(sesskey, "AlwaysOnTop", 0, conf, CONF_alwaysontop);
\r
958 gppi(sesskey, "FullScreenOnAltEnter", 0, conf, CONF_fullscreenonaltenter);
\r
959 gppi(sesskey, "HideMousePtr", 0, conf, CONF_hide_mouseptr);
\r
960 gppi(sesskey, "SunkenEdge", 0, conf, CONF_sunken_edge);
\r
961 gppi(sesskey, "WindowBorder", 1, conf, CONF_window_border);
\r
962 gppi(sesskey, "CurType", 0, conf, CONF_cursor_type);
\r
963 gppi(sesskey, "BlinkCur", 0, conf, CONF_blink_cur);
\r
964 /* pedantic compiler tells me I can't use conf, CONF_beep as an int * :-) */
\r
965 gppi(sesskey, "Beep", 1, conf, CONF_beep);
\r
966 gppi(sesskey, "BeepInd", 0, conf, CONF_beep_ind);
\r
967 gppfile(sesskey, "BellWaveFile", conf, CONF_bell_wavefile);
\r
968 gppi(sesskey, "BellOverload", 1, conf, CONF_bellovl);
\r
969 gppi(sesskey, "BellOverloadN", 5, conf, CONF_bellovl_n);
\r
970 i = gppi_raw(sesskey, "BellOverloadT", 2*TICKSPERSEC
\r
971 #ifdef PUTTY_UNIX_H
\r
975 conf_set_int(conf, CONF_bellovl_t, i
\r
976 #ifdef PUTTY_UNIX_H
\r
980 i = gppi_raw(sesskey, "BellOverloadS", 5*TICKSPERSEC
\r
981 #ifdef PUTTY_UNIX_H
\r
985 conf_set_int(conf, CONF_bellovl_s, i
\r
986 #ifdef PUTTY_UNIX_H
\r
990 gppi(sesskey, "ScrollbackLines", 2000, conf, CONF_savelines);
\r
991 gppi(sesskey, "DECOriginMode", 0, conf, CONF_dec_om);
\r
992 gppi(sesskey, "AutoWrapMode", 1, conf, CONF_wrap_mode);
\r
993 gppi(sesskey, "LFImpliesCR", 0, conf, CONF_lfhascr);
\r
994 gppi(sesskey, "CRImpliesLF", 0, conf, CONF_crhaslf);
\r
995 gppi(sesskey, "DisableArabicShaping", 0, conf, CONF_arabicshaping);
\r
996 gppi(sesskey, "DisableBidi", 0, conf, CONF_bidi);
\r
997 gppi(sesskey, "WinNameAlways", 1, conf, CONF_win_name_always);
\r
998 gpps(sesskey, "WinTitle", "", conf, CONF_wintitle);
\r
999 gppi(sesskey, "TermWidth", 80, conf, CONF_width);
\r
1000 gppi(sesskey, "TermHeight", 24, conf, CONF_height);
\r
1001 gppfont(sesskey, "Font", conf, CONF_font);
\r
1002 gppi(sesskey, "FontQuality", FQ_DEFAULT, conf, CONF_font_quality);
\r
1003 gppi(sesskey, "FontVTMode", VT_UNICODE, conf, CONF_vtmode);
\r
1004 gppi(sesskey, "UseSystemColours", 0, conf, CONF_system_colour);
\r
1005 gppi(sesskey, "TryPalette", 0, conf, CONF_try_palette);
\r
1006 gppi(sesskey, "ANSIColour", 1, conf, CONF_ansi_colour);
\r
1007 gppi(sesskey, "Xterm256Colour", 1, conf, CONF_xterm_256_colour);
\r
1008 i = gppi_raw(sesskey, "BoldAsColour", 1); conf_set_int(conf, CONF_bold_style, i+1);
\r
1010 for (i = 0; i < 22; i++) {
\r
1011 static const char *const defaults[] = {
\r
1012 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
\r
1013 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
\r
1014 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
\r
1015 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
\r
1016 "85,255,255", "187,187,187", "255,255,255"
\r
1018 char buf[20], *buf2;
\r
1020 sprintf(buf, "Colour%d", i);
\r
1021 buf2 = gpps_raw(sesskey, buf, defaults[i]);
\r
1022 if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
\r
1023 conf_set_int_int(conf, CONF_colours, i*3+0, c0);
\r
1024 conf_set_int_int(conf, CONF_colours, i*3+1, c1);
\r
1025 conf_set_int_int(conf, CONF_colours, i*3+2, c2);
\r
1029 gppi(sesskey, "RawCNP", 0, conf, CONF_rawcnp);
\r
1030 gppi(sesskey, "PasteRTF", 0, conf, CONF_rtf_paste);
\r
1031 gppi(sesskey, "MouseIsXterm", 0, conf, CONF_mouse_is_xterm);
\r
1032 gppi(sesskey, "RectSelect", 0, conf, CONF_rect_select);
\r
1033 gppi(sesskey, "MouseOverride", 1, conf, CONF_mouse_override);
\r
1034 for (i = 0; i < 256; i += 32) {
\r
1035 static const char *const defaults[] = {
\r
1036 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
\r
1037 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
\r
1038 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
\r
1039 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
\r
1040 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
\r
1041 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
\r
1042 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
\r
1043 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
\r
1045 char buf[20], *buf2, *p;
\r
1047 sprintf(buf, "Wordness%d", i);
\r
1048 buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);
\r
1050 for (j = i; j < i + 32; j++) {
\r
1052 while (*p && *p != ',')
\r
1056 conf_set_int_int(conf, CONF_wordness, j, atoi(q));
\r
1061 * The empty default for LineCodePage will be converted later
\r
1062 * into a plausible default for the locale.
\r
1064 gpps(sesskey, "LineCodePage", "", conf, CONF_line_codepage);
\r
1065 gppi(sesskey, "CJKAmbigWide", 0, conf, CONF_cjk_ambig_wide);
\r
1066 gppi(sesskey, "UTF8Override", 1, conf, CONF_utf8_override);
\r
1067 gpps(sesskey, "Printer", "", conf, CONF_printer);
\r
1068 gppi(sesskey, "CapsLockCyr", 0, conf, CONF_xlat_capslockcyr);
\r
1069 gppi(sesskey, "ScrollBar", 1, conf, CONF_scrollbar);
\r
1070 gppi(sesskey, "ScrollBarFullScreen", 0, conf, CONF_scrollbar_in_fullscreen);
\r
1071 gppi(sesskey, "ScrollOnKey", 0, conf, CONF_scroll_on_key);
\r
1072 gppi(sesskey, "ScrollOnDisp", 1, conf, CONF_scroll_on_disp);
\r
1073 gppi(sesskey, "EraseToScrollback", 1, conf, CONF_erase_to_scrollback);
\r
1074 gppi(sesskey, "LockSize", 0, conf, CONF_resize_action);
\r
1075 gppi(sesskey, "BCE", 1, conf, CONF_bce);
\r
1076 gppi(sesskey, "BlinkText", 0, conf, CONF_blinktext);
\r
1077 gppi(sesskey, "X11Forward", 0, conf, CONF_x11_forward);
\r
1078 gpps(sesskey, "X11Display", "", conf, CONF_x11_display);
\r
1079 gppi(sesskey, "X11AuthType", X11_MIT, conf, CONF_x11_auth);
\r
1080 gppfile(sesskey, "X11AuthFile", conf, CONF_xauthfile);
\r
1082 gppi(sesskey, "LocalPortAcceptAll", 0, conf, CONF_lport_acceptall);
\r
1083 gppi(sesskey, "RemotePortAcceptAll", 0, conf, CONF_rport_acceptall);
\r
1084 gppmap(sesskey, "PortForwardings", conf, CONF_portfwd);
\r
1085 i = gppi_raw(sesskey, "BugIgnore1", 0); conf_set_int(conf, CONF_sshbug_ignore1, 2-i);
\r
1086 i = gppi_raw(sesskey, "BugPlainPW1", 0); conf_set_int(conf, CONF_sshbug_plainpw1, 2-i);
\r
1087 i = gppi_raw(sesskey, "BugRSA1", 0); conf_set_int(conf, CONF_sshbug_rsa1, 2-i);
\r
1088 i = gppi_raw(sesskey, "BugIgnore2", 0); conf_set_int(conf, CONF_sshbug_ignore2, 2-i);
\r
1091 i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);
\r
1092 if (2-i == AUTO) {
\r
1093 i = gppi_raw(sesskey, "BuggyMAC", 0);
\r
1095 conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);
\r
1098 i = gppi_raw(sesskey, "BugDeriveKey2", 0); conf_set_int(conf, CONF_sshbug_derivekey2, 2-i);
\r
1099 i = gppi_raw(sesskey, "BugRSAPad2", 0); conf_set_int(conf, CONF_sshbug_rsapad2, 2-i);
\r
1100 i = gppi_raw(sesskey, "BugPKSessID2", 0); conf_set_int(conf, CONF_sshbug_pksessid2, 2-i);
\r
1101 i = gppi_raw(sesskey, "BugRekey2", 0); conf_set_int(conf, CONF_sshbug_rekey2, 2-i);
\r
1102 i = gppi_raw(sesskey, "BugMaxPkt2", 0); conf_set_int(conf, CONF_sshbug_maxpkt2, 2-i);
\r
1103 i = gppi_raw(sesskey, "BugOldGex2", 0); conf_set_int(conf, CONF_sshbug_oldgex2, 2-i);
\r
1104 i = gppi_raw(sesskey, "BugWinadj", 0); conf_set_int(conf, CONF_sshbug_winadj, 2-i);
\r
1105 i = gppi_raw(sesskey, "BugChanReq", 0); conf_set_int(conf, CONF_sshbug_chanreq, 2-i);
\r
1106 conf_set_int(conf, CONF_ssh_simple, FALSE);
\r
1107 gppi(sesskey, "StampUtmp", 1, conf, CONF_stamp_utmp);
\r
1108 gppi(sesskey, "LoginShell", 1, conf, CONF_login_shell);
\r
1109 gppi(sesskey, "ScrollbarOnLeft", 0, conf, CONF_scrollbar_on_left);
\r
1110 gppi(sesskey, "ShadowBold", 0, conf, CONF_shadowbold);
\r
1111 gppfont(sesskey, "BoldFont", conf, CONF_boldfont);
\r
1112 gppfont(sesskey, "WideFont", conf, CONF_widefont);
\r
1113 gppfont(sesskey, "WideBoldFont", conf, CONF_wideboldfont);
\r
1114 gppi(sesskey, "ShadowBoldOffset", 1, conf, CONF_shadowboldoffset);
\r
1115 gpps(sesskey, "SerialLine", "", conf, CONF_serline);
\r
1116 gppi(sesskey, "SerialSpeed", 9600, conf, CONF_serspeed);
\r
1117 gppi(sesskey, "SerialDataBits", 8, conf, CONF_serdatabits);
\r
1118 gppi(sesskey, "SerialStopHalfbits", 2, conf, CONF_serstopbits);
\r
1119 gppi(sesskey, "SerialParity", SER_PAR_NONE, conf, CONF_serparity);
\r
1120 gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, conf, CONF_serflow);
\r
1121 gpps(sesskey, "WindowClass", "", conf, CONF_winclass);
\r
1122 gppi(sesskey, "ConnectionSharing", 0, conf, CONF_ssh_connection_sharing);
\r
1123 gppi(sesskey, "ConnectionSharingUpstream", 1, conf, CONF_ssh_connection_sharing_upstream);
\r
1124 gppi(sesskey, "ConnectionSharingDownstream", 1, conf, CONF_ssh_connection_sharing_downstream);
\r
1125 gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys);
\r
1128 void do_defaults(const char *session, Conf *conf)
\r
1130 load_settings(session, conf);
\r
1133 static int sessioncmp(const void *av, const void *bv)
\r
1135 const char *a = *(const char *const *) av;
\r
1136 const char *b = *(const char *const *) bv;
\r
1139 * Alphabetical order, except that "Default Settings" is a
\r
1140 * special case and comes first.
\r
1142 if (!strcmp(a, "Default Settings"))
\r
1143 return -1; /* a comes first */
\r
1144 if (!strcmp(b, "Default Settings"))
\r
1145 return +1; /* b comes first */
\r
1147 * FIXME: perhaps we should ignore the first & in determining
\r
1150 return strcmp(a, b); /* otherwise, compare normally */
\r
1153 void get_sesslist(struct sesslist *list, int allocate)
\r
1155 char otherbuf[2048];
\r
1156 int buflen, bufsize, i;
\r
1162 buflen = bufsize = 0;
\r
1163 list->buffer = NULL;
\r
1164 if ((handle = enum_settings_start()) != NULL) {
\r
1166 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
\r
1168 int len = strlen(otherbuf) + 1;
\r
1169 if (bufsize < buflen + len) {
\r
1170 bufsize = buflen + len + 2048;
\r
1171 list->buffer = sresize(list->buffer, bufsize, char);
\r
1173 strcpy(list->buffer + buflen, otherbuf);
\r
1174 buflen += strlen(list->buffer + buflen) + 1;
\r
1177 enum_settings_finish(handle);
\r
1179 list->buffer = sresize(list->buffer, buflen + 1, char);
\r
1180 list->buffer[buflen] = '\0';
\r
1183 * Now set up the list of sessions. Note that "Default
\r
1184 * Settings" must always be claimed to exist, even if it
\r
1189 list->nsessions = 1; /* "Default Settings" counts as one */
\r
1191 if (strcmp(p, "Default Settings"))
\r
1192 list->nsessions++;
\r
1198 list->sessions = snewn(list->nsessions + 1, const char *);
\r
1199 list->sessions[0] = "Default Settings";
\r
1203 if (strcmp(p, "Default Settings"))
\r
1204 list->sessions[i++] = p;
\r
1210 qsort(list->sessions, i, sizeof(const char *), sessioncmp);
\r
1212 sfree(list->buffer);
\r
1213 sfree(list->sessions);
\r
1214 list->buffer = NULL;
\r
1215 list->sessions = NULL;
\r