Fixed issue #2931: Make “ChangeList” grids in “Git synchronization” multi-selectable
[TortoiseGit.git] / src / TortoisePlink / SETTINGS.C
blobe55b3c3aaf3ab9803f7b712575a0e87e468dca42
1 /*\r
2  * settings.c: read and write saved sessions. (platform-independent)\r
3  */\r
4 \r
5 #include <assert.h>\r
6 #include <stdio.h>\r
7 #include <stdlib.h>\r
8 #include "putty.h"\r
9 #include "storage.h"\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     { "blowfish",   CIPHER_BLOWFISH,        -1, -1 },\r
15     { "3des",       CIPHER_3DES,            -1, -1 },\r
16     { "WARN",       CIPHER_WARN,            -1, -1 },\r
17     { "arcfour",    CIPHER_ARCFOUR,         -1, -1 },\r
18     { "des",        CIPHER_DES,             -1, -1 }\r
19 };\r
21 static const struct keyvalwhere kexnames[] = {\r
22     { "dh-gex-sha1",        KEX_DHGEX,      -1, -1 },\r
23     { "dh-group14-sha1",    KEX_DHGROUP14,  -1, -1 },\r
24     { "dh-group1-sha1",     KEX_DHGROUP1,   -1, -1 },\r
25     { "rsa",                KEX_RSA,        KEX_WARN, -1 },\r
26     { "WARN",               KEX_WARN,       -1, -1 }\r
27 };\r
29 /*\r
30  * All the terminal modes that we know about for the "TerminalModes"\r
31  * setting. (Also used by config.c for the drop-down list.)\r
32  * This is currently precisely the same as the set in ssh.c, but could\r
33  * in principle differ if other backends started to support tty modes\r
34  * (e.g., the pty backend).\r
35  */\r
36 const char *const ttymodes[] = {\r
37     "INTR",     "QUIT",     "ERASE",    "KILL",     "EOF",\r
38     "EOL",      "EOL2",     "START",    "STOP",     "SUSP",\r
39     "DSUSP",    "REPRINT",  "WERASE",   "LNEXT",    "FLUSH",\r
40     "SWTCH",    "STATUS",   "DISCARD",  "IGNPAR",   "PARMRK",\r
41     "INPCK",    "ISTRIP",   "INLCR",    "IGNCR",    "ICRNL",\r
42     "IUCLC",    "IXON",     "IXANY",    "IXOFF",    "IMAXBEL",\r
43     "ISIG",     "ICANON",   "XCASE",    "ECHO",     "ECHOE",\r
44     "ECHOK",    "ECHONL",   "NOFLSH",   "TOSTOP",   "IEXTEN",\r
45     "ECHOCTL",  "ECHOKE",   "PENDIN",   "OPOST",    "OLCUC",\r
46     "ONLCR",    "OCRNL",    "ONOCR",    "ONLRET",   "CS7",\r
47     "CS8",      "PARENB",   "PARODD",   NULL\r
48 };\r
50 /*\r
51  * Convenience functions to access the backends[] array\r
52  * (which is only present in tools that manage settings).\r
53  */\r
55 Backend *backend_from_name(const char *name)\r
56 {\r
57     Backend **p;\r
58     for (p = backends; *p != NULL; p++)\r
59         if (!strcmp((*p)->name, name))\r
60             return *p;\r
61     return NULL;\r
62 }\r
64 Backend *backend_from_proto(int proto)\r
65 {\r
66     Backend **p;\r
67     for (p = backends; *p != NULL; p++)\r
68         if ((*p)->protocol == proto)\r
69             return *p;\r
70     return NULL;\r
71 }\r
73 char *get_remote_username(Conf *conf)\r
74 {\r
75     char *username = conf_get_str(conf, CONF_username);\r
76     if (*username) {\r
77         return dupstr(username);\r
78     } else if (conf_get_int(conf, CONF_username_from_env)) {\r
79         /* Use local username. */\r
80         return get_username();     /* might still be NULL */\r
81     } else {\r
82         return NULL;\r
83     }\r
84 }\r
86 static char *gpps_raw(void *handle, const char *name, const char *def)\r
87 {\r
88     char *ret = read_setting_s(handle, name);\r
89     if (!ret)\r
90         ret = platform_default_s(name);\r
91     if (!ret)\r
92         ret = def ? dupstr(def) : NULL;   /* permit NULL as final fallback */\r
93     return ret;\r
94 }\r
96 static void gpps(void *handle, const char *name, const char *def,\r
97                  Conf *conf, int primary)\r
98 {\r
99     char *val = gpps_raw(handle, name, def);\r
100     conf_set_str(conf, primary, val);\r
101     sfree(val);\r
104 /*\r
105  * gppfont and gppfile cannot have local defaults, since the very\r
106  * format of a Filename or FontSpec is platform-dependent. So the\r
107  * platform-dependent functions MUST return some sort of value.\r
108  */\r
109 static void gppfont(void *handle, const char *name, Conf *conf, int primary)\r
111     FontSpec *result = read_setting_fontspec(handle, name);\r
112     if (!result)\r
113         result = platform_default_fontspec(name);\r
114     conf_set_fontspec(conf, primary, result);\r
115     fontspec_free(result);\r
117 static void gppfile(void *handle, const char *name, Conf *conf, int primary)\r
119     Filename *result = read_setting_filename(handle, name);\r
120     if (!result)\r
121         result = platform_default_filename(name);\r
122     conf_set_filename(conf, primary, result);\r
123     filename_free(result);\r
126 static int gppi_raw(void *handle, char *name, int def)\r
128     def = platform_default_i(name, def);\r
129     return read_setting_i(handle, name, def);\r
132 static void gppi(void *handle, char *name, int def, Conf *conf, int primary)\r
134     conf_set_int(conf, primary, gppi_raw(handle, name, def));\r
137 /*\r
138  * Read a set of name-value pairs in the format we occasionally use:\r
139  *   NAME\tVALUE\0NAME\tVALUE\0\0 in memory\r
140  *   NAME=VALUE,NAME=VALUE, in storage\r
141  * If there's no "=VALUE" (e.g. just NAME,NAME,NAME) then those keys\r
142  * are mapped to the empty string.\r
143  */\r
144 static int gppmap(void *handle, char *name, Conf *conf, int primary)\r
146     char *buf, *p, *q, *key, *val;\r
148     /*\r
149      * Start by clearing any existing subkeys of this key from conf.\r
150      */\r
151     while ((key = conf_get_str_nthstrkey(conf, primary, 0)) != NULL)\r
152         conf_del_str_str(conf, primary, key);\r
154     /*\r
155      * Now read a serialised list from the settings and unmarshal it\r
156      * into its components.\r
157      */\r
158     buf = gpps_raw(handle, name, NULL);\r
159     if (!buf)\r
160         return FALSE;\r
162     p = buf;\r
163     while (*p) {\r
164         q = buf;\r
165         val = NULL;\r
166         while (*p && *p != ',') {\r
167             int c = *p++;\r
168             if (c == '=')\r
169                 c = '\0';\r
170             if (c == '\\')\r
171                 c = *p++;\r
172             *q++ = c;\r
173             if (!c)\r
174                 val = q;\r
175         }\r
176         if (*p == ',')\r
177             p++;\r
178         if (!val)\r
179             val = q;\r
180         *q = '\0';\r
182         if (primary == CONF_portfwd && strchr(buf, 'D') != NULL) {\r
183             /*\r
184              * Backwards-compatibility hack: dynamic forwardings are\r
185              * indexed in the data store as a third type letter in the\r
186              * key, 'D' alongside 'L' and 'R' - but really, they\r
187              * should be filed under 'L' with a special _value_,\r
188              * because local and dynamic forwardings both involve\r
189              * _listening_ on a local port, and are hence mutually\r
190              * exclusive on the same port number. So here we translate\r
191              * the legacy storage format into the sensible internal\r
192              * form, by finding the D and turning it into a L.\r
193              */\r
194             char *newkey = dupstr(buf);\r
195             *strchr(newkey, 'D') = 'L';\r
196             conf_set_str_str(conf, primary, newkey, "D");\r
197             sfree(newkey);\r
198         } else {\r
199             conf_set_str_str(conf, primary, buf, val);\r
200         }\r
201     }\r
202     sfree(buf);\r
204     return TRUE;\r
207 /*\r
208  * Write a set of name/value pairs in the above format, or just the\r
209  * names if include_values is FALSE.\r
210  */\r
211 static void wmap(void *handle, char const *outkey, Conf *conf, int primary,\r
212                  int include_values)\r
214     char *buf, *p, *q, *key, *realkey, *val;\r
215     int len;\r
217     len = 1;                           /* allow for NUL */\r
219     for (val = conf_get_str_strs(conf, primary, NULL, &key);\r
220          val != NULL;\r
221          val = conf_get_str_strs(conf, primary, key, &key))\r
222         len += 2 + 2 * (strlen(key) + strlen(val));   /* allow for escaping */\r
224     buf = snewn(len, char);\r
225     p = buf;\r
227     for (val = conf_get_str_strs(conf, primary, NULL, &key);\r
228          val != NULL;\r
229          val = conf_get_str_strs(conf, primary, key, &key)) {\r
231         if (primary == CONF_portfwd && !strcmp(val, "D")) {\r
232             /*\r
233              * Backwards-compatibility hack, as above: translate from\r
234              * the sensible internal representation of dynamic\r
235              * forwardings (key "L<port>", value "D") to the\r
236              * conceptually incoherent legacy storage format (key\r
237              * "D<port>", value empty).\r
238              */\r
239             char *L;\r
241             realkey = key;             /* restore it at end of loop */\r
242             val = "";\r
243             key = dupstr(key);\r
244             L = strchr(key, 'L');\r
245             if (L) *L = 'D';\r
246         } else {\r
247             realkey = NULL;\r
248         }\r
250         if (p != buf)\r
251             *p++ = ',';\r
252         for (q = key; *q; q++) {\r
253             if (*q == '=' || *q == ',' || *q == '\\')\r
254                 *p++ = '\\';\r
255             *p++ = *q;\r
256         }\r
257         if (include_values) {\r
258             *p++ = '=';\r
259             for (q = val; *q; q++) {\r
260                 if (*q == '=' || *q == ',' || *q == '\\')\r
261                     *p++ = '\\';\r
262                 *p++ = *q;\r
263             }\r
264         }\r
266         if (realkey) {\r
267             free(key);\r
268             key = realkey;\r
269         }\r
270     }\r
271     *p = '\0';\r
272     write_setting_s(handle, outkey, buf);\r
273     sfree(buf);\r
276 static int key2val(const struct keyvalwhere *mapping,\r
277                    int nmaps, char *key)\r
279     int i;\r
280     for (i = 0; i < nmaps; i++)\r
281         if (!strcmp(mapping[i].s, key)) return mapping[i].v;\r
282     return -1;\r
285 static const char *val2key(const struct keyvalwhere *mapping,\r
286                            int nmaps, int val)\r
288     int i;\r
289     for (i = 0; i < nmaps; i++)\r
290         if (mapping[i].v == val) return mapping[i].s;\r
291     return NULL;\r
294 /*\r
295  * Helper function to parse a comma-separated list of strings into\r
296  * a preference list array of values. Any missing values are added\r
297  * to the end and duplicates are weeded.\r
298  * XXX: assumes vals in 'mapping' are small +ve integers\r
299  */\r
300 static void gprefs(void *sesskey, char *name, char *def,\r
301                    const struct keyvalwhere *mapping, int nvals,\r
302                    Conf *conf, int primary)\r
304     char *commalist;\r
305     char *p, *q;\r
306     int i, j, n, v, pos;\r
307     unsigned long seen = 0;            /* bitmap for weeding dups etc */\r
309     /*\r
310      * Fetch the string which we'll parse as a comma-separated list.\r
311      */\r
312     commalist = gpps_raw(sesskey, name, def);\r
314     /*\r
315      * Go through that list and convert it into values.\r
316      */\r
317     n = 0;\r
318     p = commalist;\r
319     while (1) {\r
320         while (*p && *p == ',') p++;\r
321         if (!*p)\r
322             break;                     /* no more words */\r
324         q = p;\r
325         while (*p && *p != ',') p++;\r
326         if (*p) *p++ = '\0';\r
328         v = key2val(mapping, nvals, q);\r
329         if (v != -1 && !(seen & (1 << v))) {\r
330             seen |= (1 << v);\r
331             conf_set_int_int(conf, primary, n, v);\r
332             n++;\r
333         }\r
334     }\r
336     sfree(commalist);\r
338     /*\r
339      * Now go through 'mapping' and add values that weren't mentioned\r
340      * in the list we fetched. We may have to loop over it multiple\r
341      * times so that we add values before other values whose default\r
342      * positions depend on them.\r
343      */\r
344     while (n < nvals) {\r
345         for (i = 0; i < nvals; i++) {\r
346             assert(mapping[i].v < 32);\r
348             if (!(seen & (1 << mapping[i].v))) {\r
349                 /*\r
350                  * This element needs adding. But can we add it yet?\r
351                  */\r
352                 if (mapping[i].vrel != -1 && !(seen & (1 << mapping[i].vrel)))\r
353                     continue;          /* nope */\r
355                 /*\r
356                  * OK, we can work out where to add this element, so\r
357                  * do so.\r
358                  */\r
359                 if (mapping[i].vrel == -1) {\r
360                     pos = (mapping[i].where < 0 ? n : 0);\r
361                 } else {\r
362                     for (j = 0; j < n; j++)\r
363                         if (conf_get_int_int(conf, primary, j) ==\r
364                             mapping[i].vrel)\r
365                             break;\r
366                     assert(j < n);     /* implied by (seen & (1<<vrel)) */\r
367                     pos = (mapping[i].where < 0 ? j : j+1);\r
368                 }\r
370                 /*\r
371                  * And add it.\r
372                  */\r
373                 for (j = n-1; j >= pos; j--)\r
374                     conf_set_int_int(conf, primary, j+1,\r
375                                      conf_get_int_int(conf, primary, j));\r
376                 conf_set_int_int(conf, primary, pos, mapping[i].v);\r
377                 n++;\r
378             }\r
379         }\r
380     }\r
383 /* \r
384  * Write out a preference list.\r
385  */\r
386 static void wprefs(void *sesskey, char *name,\r
387                    const struct keyvalwhere *mapping, int nvals,\r
388                    Conf *conf, int primary)\r
390     char *buf, *p;\r
391     int i, maxlen;\r
393     for (maxlen = i = 0; i < nvals; i++) {\r
394         const char *s = val2key(mapping, nvals,\r
395                                 conf_get_int_int(conf, primary, i));\r
396         if (s) {\r
397             maxlen += (maxlen > 0 ? 1 : 0) + strlen(s);\r
398         }\r
399     }\r
401     buf = snewn(maxlen + 1, char);\r
402     p = buf;\r
404     for (i = 0; i < nvals; i++) {\r
405         const char *s = val2key(mapping, nvals,\r
406                                 conf_get_int_int(conf, primary, i));\r
407         if (s) {\r
408             p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);\r
409         }\r
410     }\r
412     assert(p - buf == maxlen);\r
413     *p = '\0';\r
415     write_setting_s(sesskey, name, buf);\r
417     sfree(buf);\r
420 char *save_settings(char *section, Conf *conf)\r
422     void *sesskey;\r
423     char *errmsg;\r
425     sesskey = open_settings_w(section, &errmsg);\r
426     if (!sesskey)\r
427         return errmsg;\r
428     save_open_settings(sesskey, conf);\r
429     close_settings_w(sesskey);\r
430     return NULL;\r
433 void save_open_settings(void *sesskey, Conf *conf)\r
435     int i;\r
436     char *p;\r
438     write_setting_i(sesskey, "Present", 1);\r
439     write_setting_s(sesskey, "HostName", conf_get_str(conf, CONF_host));\r
440     write_setting_filename(sesskey, "LogFileName", conf_get_filename(conf, CONF_logfilename));\r
441     write_setting_i(sesskey, "LogType", conf_get_int(conf, CONF_logtype));\r
442     write_setting_i(sesskey, "LogFileClash", conf_get_int(conf, CONF_logxfovr));\r
443     write_setting_i(sesskey, "LogFlush", conf_get_int(conf, CONF_logflush));\r
444     write_setting_i(sesskey, "SSHLogOmitPasswords", conf_get_int(conf, CONF_logomitpass));\r
445     write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata));\r
446     p = "raw";\r
447     {\r
448         const Backend *b = backend_from_proto(conf_get_int(conf, CONF_protocol));\r
449         if (b)\r
450             p = b->name;\r
451     }\r
452     write_setting_s(sesskey, "Protocol", p);\r
453     write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));\r
454     /* The CloseOnExit numbers are arranged in a different order from\r
455      * the standard FORCE_ON / FORCE_OFF / AUTO. */\r
456     write_setting_i(sesskey, "CloseOnExit", (conf_get_int(conf, CONF_close_on_exit)+2)%3);\r
457     write_setting_i(sesskey, "WarnOnClose", !!conf_get_int(conf, CONF_warn_on_close));\r
458     write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60);      /* minutes */\r
459     write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60);  /* seconds */\r
460     write_setting_i(sesskey, "TCPNoDelay", conf_get_int(conf, CONF_tcp_nodelay));\r
461     write_setting_i(sesskey, "TCPKeepalives", conf_get_int(conf, CONF_tcp_keepalives));\r
462     write_setting_s(sesskey, "TerminalType", conf_get_str(conf, CONF_termtype));\r
463     write_setting_s(sesskey, "TerminalSpeed", conf_get_str(conf, CONF_termspeed));\r
464     wmap(sesskey, "TerminalModes", conf, CONF_ttymodes, TRUE);\r
466     /* Address family selection */\r
467     write_setting_i(sesskey, "AddressFamily", conf_get_int(conf, CONF_addressfamily));\r
469     /* proxy settings */\r
470     write_setting_s(sesskey, "ProxyExcludeList", conf_get_str(conf, CONF_proxy_exclude_list));\r
471     write_setting_i(sesskey, "ProxyDNS", (conf_get_int(conf, CONF_proxy_dns)+2)%3);\r
472     write_setting_i(sesskey, "ProxyLocalhost", conf_get_int(conf, CONF_even_proxy_localhost));\r
473     write_setting_i(sesskey, "ProxyMethod", conf_get_int(conf, CONF_proxy_type));\r
474     write_setting_s(sesskey, "ProxyHost", conf_get_str(conf, CONF_proxy_host));\r
475     write_setting_i(sesskey, "ProxyPort", conf_get_int(conf, CONF_proxy_port));\r
476     write_setting_s(sesskey, "ProxyUsername", conf_get_str(conf, CONF_proxy_username));\r
477     write_setting_s(sesskey, "ProxyPassword", conf_get_str(conf, CONF_proxy_password));\r
478     write_setting_s(sesskey, "ProxyTelnetCommand", conf_get_str(conf, CONF_proxy_telnet_command));\r
479     wmap(sesskey, "Environment", conf, CONF_environmt, TRUE);\r
480     write_setting_s(sesskey, "UserName", conf_get_str(conf, CONF_username));\r
481     write_setting_i(sesskey, "UserNameFromEnvironment", conf_get_int(conf, CONF_username_from_env));\r
482     write_setting_s(sesskey, "LocalUserName", conf_get_str(conf, CONF_localusername));\r
483     write_setting_i(sesskey, "NoPTY", conf_get_int(conf, CONF_nopty));\r
484     write_setting_i(sesskey, "Compression", conf_get_int(conf, CONF_compression));\r
485     write_setting_i(sesskey, "TryAgent", conf_get_int(conf, CONF_tryagent));\r
486     write_setting_i(sesskey, "AgentFwd", conf_get_int(conf, CONF_agentfwd));\r
487     write_setting_i(sesskey, "GssapiFwd", conf_get_int(conf, CONF_gssapifwd));\r
488     write_setting_i(sesskey, "ChangeUsername", conf_get_int(conf, CONF_change_username));\r
489     wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);\r
490     wprefs(sesskey, "KEX", kexnames, KEX_MAX, conf, CONF_ssh_kexlist);\r
491     write_setting_i(sesskey, "RekeyTime", conf_get_int(conf, CONF_ssh_rekey_time));\r
492     write_setting_s(sesskey, "RekeyBytes", conf_get_str(conf, CONF_ssh_rekey_data));\r
493     write_setting_i(sesskey, "SshNoAuth", conf_get_int(conf, CONF_ssh_no_userauth));\r
494     write_setting_i(sesskey, "SshBanner", conf_get_int(conf, CONF_ssh_show_banner));\r
495     write_setting_i(sesskey, "AuthTIS", conf_get_int(conf, CONF_try_tis_auth));\r
496     write_setting_i(sesskey, "AuthKI", conf_get_int(conf, CONF_try_ki_auth));\r
497     write_setting_i(sesskey, "AuthGSSAPI", conf_get_int(conf, CONF_try_gssapi_auth));\r
498 #ifndef NO_GSSAPI\r
499     wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);\r
500     write_setting_filename(sesskey, "GSSCustom", conf_get_filename(conf, CONF_ssh_gss_custom));\r
501 #endif\r
502     write_setting_i(sesskey, "SshNoShell", conf_get_int(conf, CONF_ssh_no_shell));\r
503     write_setting_i(sesskey, "SshProt", conf_get_int(conf, CONF_sshprot));\r
504     write_setting_s(sesskey, "LogHost", conf_get_str(conf, CONF_loghost));\r
505     write_setting_i(sesskey, "SSH2DES", conf_get_int(conf, CONF_ssh2_des_cbc));\r
506     write_setting_filename(sesskey, "PublicKeyFile", conf_get_filename(conf, CONF_keyfile));\r
507     write_setting_s(sesskey, "RemoteCommand", conf_get_str(conf, CONF_remote_cmd));\r
508     write_setting_i(sesskey, "RFCEnviron", conf_get_int(conf, CONF_rfc_environ));\r
509     write_setting_i(sesskey, "PassiveTelnet", conf_get_int(conf, CONF_passive_telnet));\r
510     write_setting_i(sesskey, "BackspaceIsDelete", conf_get_int(conf, CONF_bksp_is_delete));\r
511     write_setting_i(sesskey, "RXVTHomeEnd", conf_get_int(conf, CONF_rxvt_homeend));\r
512     write_setting_i(sesskey, "LinuxFunctionKeys", conf_get_int(conf, CONF_funky_type));\r
513     write_setting_i(sesskey, "NoApplicationKeys", conf_get_int(conf, CONF_no_applic_k));\r
514     write_setting_i(sesskey, "NoApplicationCursors", conf_get_int(conf, CONF_no_applic_c));\r
515     write_setting_i(sesskey, "NoMouseReporting", conf_get_int(conf, CONF_no_mouse_rep));\r
516     write_setting_i(sesskey, "NoRemoteResize", conf_get_int(conf, CONF_no_remote_resize));\r
517     write_setting_i(sesskey, "NoAltScreen", conf_get_int(conf, CONF_no_alt_screen));\r
518     write_setting_i(sesskey, "NoRemoteWinTitle", conf_get_int(conf, CONF_no_remote_wintitle));\r
519     write_setting_i(sesskey, "RemoteQTitleAction", conf_get_int(conf, CONF_remote_qtitle_action));\r
520     write_setting_i(sesskey, "NoDBackspace", conf_get_int(conf, CONF_no_dbackspace));\r
521     write_setting_i(sesskey, "NoRemoteCharset", conf_get_int(conf, CONF_no_remote_charset));\r
522     write_setting_i(sesskey, "ApplicationCursorKeys", conf_get_int(conf, CONF_app_cursor));\r
523     write_setting_i(sesskey, "ApplicationKeypad", conf_get_int(conf, CONF_app_keypad));\r
524     write_setting_i(sesskey, "NetHackKeypad", conf_get_int(conf, CONF_nethack_keypad));\r
525     write_setting_i(sesskey, "AltF4", conf_get_int(conf, CONF_alt_f4));\r
526     write_setting_i(sesskey, "AltSpace", conf_get_int(conf, CONF_alt_space));\r
527     write_setting_i(sesskey, "AltOnly", conf_get_int(conf, CONF_alt_only));\r
528     write_setting_i(sesskey, "ComposeKey", conf_get_int(conf, CONF_compose_key));\r
529     write_setting_i(sesskey, "CtrlAltKeys", conf_get_int(conf, CONF_ctrlaltkeys));\r
530     write_setting_i(sesskey, "TelnetKey", conf_get_int(conf, CONF_telnet_keyboard));\r
531     write_setting_i(sesskey, "TelnetRet", conf_get_int(conf, CONF_telnet_newline));\r
532     write_setting_i(sesskey, "LocalEcho", conf_get_int(conf, CONF_localecho));\r
533     write_setting_i(sesskey, "LocalEdit", conf_get_int(conf, CONF_localedit));\r
534     write_setting_s(sesskey, "Answerback", conf_get_str(conf, CONF_answerback));\r
535     write_setting_i(sesskey, "AlwaysOnTop", conf_get_int(conf, CONF_alwaysontop));\r
536     write_setting_i(sesskey, "FullScreenOnAltEnter", conf_get_int(conf, CONF_fullscreenonaltenter));\r
537     write_setting_i(sesskey, "HideMousePtr", conf_get_int(conf, CONF_hide_mouseptr));\r
538     write_setting_i(sesskey, "SunkenEdge", conf_get_int(conf, CONF_sunken_edge));\r
539     write_setting_i(sesskey, "WindowBorder", conf_get_int(conf, CONF_window_border));\r
540     write_setting_i(sesskey, "CurType", conf_get_int(conf, CONF_cursor_type));\r
541     write_setting_i(sesskey, "BlinkCur", conf_get_int(conf, CONF_blink_cur));\r
542     write_setting_i(sesskey, "Beep", conf_get_int(conf, CONF_beep));\r
543     write_setting_i(sesskey, "BeepInd", conf_get_int(conf, CONF_beep_ind));\r
544     write_setting_filename(sesskey, "BellWaveFile", conf_get_filename(conf, CONF_bell_wavefile));\r
545     write_setting_i(sesskey, "BellOverload", conf_get_int(conf, CONF_bellovl));\r
546     write_setting_i(sesskey, "BellOverloadN", conf_get_int(conf, CONF_bellovl_n));\r
547     write_setting_i(sesskey, "BellOverloadT", conf_get_int(conf, CONF_bellovl_t)\r
548 #ifdef PUTTY_UNIX_H\r
549                     * 1000\r
550 #endif\r
551                     );\r
552     write_setting_i(sesskey, "BellOverloadS", conf_get_int(conf, CONF_bellovl_s)\r
553 #ifdef PUTTY_UNIX_H\r
554                     * 1000\r
555 #endif\r
556                     );\r
557     write_setting_i(sesskey, "ScrollbackLines", conf_get_int(conf, CONF_savelines));\r
558     write_setting_i(sesskey, "DECOriginMode", conf_get_int(conf, CONF_dec_om));\r
559     write_setting_i(sesskey, "AutoWrapMode", conf_get_int(conf, CONF_wrap_mode));\r
560     write_setting_i(sesskey, "LFImpliesCR", conf_get_int(conf, CONF_lfhascr));\r
561     write_setting_i(sesskey, "CRImpliesLF", conf_get_int(conf, CONF_crhaslf));\r
562     write_setting_i(sesskey, "DisableArabicShaping", conf_get_int(conf, CONF_arabicshaping));\r
563     write_setting_i(sesskey, "DisableBidi", conf_get_int(conf, CONF_bidi));\r
564     write_setting_i(sesskey, "WinNameAlways", conf_get_int(conf, CONF_win_name_always));\r
565     write_setting_s(sesskey, "WinTitle", conf_get_str(conf, CONF_wintitle));\r
566     write_setting_i(sesskey, "TermWidth", conf_get_int(conf, CONF_width));\r
567     write_setting_i(sesskey, "TermHeight", conf_get_int(conf, CONF_height));\r
568     write_setting_fontspec(sesskey, "Font", conf_get_fontspec(conf, CONF_font));\r
569     write_setting_i(sesskey, "FontQuality", conf_get_int(conf, CONF_font_quality));\r
570     write_setting_i(sesskey, "FontVTMode", conf_get_int(conf, CONF_vtmode));\r
571     write_setting_i(sesskey, "UseSystemColours", conf_get_int(conf, CONF_system_colour));\r
572     write_setting_i(sesskey, "TryPalette", conf_get_int(conf, CONF_try_palette));\r
573     write_setting_i(sesskey, "ANSIColour", conf_get_int(conf, CONF_ansi_colour));\r
574     write_setting_i(sesskey, "Xterm256Colour", conf_get_int(conf, CONF_xterm_256_colour));\r
575     write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_style)-1);\r
577     for (i = 0; i < 22; i++) {\r
578         char buf[20], buf2[30];\r
579         sprintf(buf, "Colour%d", i);\r
580         sprintf(buf2, "%d,%d,%d",\r
581                 conf_get_int_int(conf, CONF_colours, i*3+0),\r
582                 conf_get_int_int(conf, CONF_colours, i*3+1),\r
583                 conf_get_int_int(conf, CONF_colours, i*3+2));\r
584         write_setting_s(sesskey, buf, buf2);\r
585     }\r
586     write_setting_i(sesskey, "RawCNP", conf_get_int(conf, CONF_rawcnp));\r
587     write_setting_i(sesskey, "PasteRTF", conf_get_int(conf, CONF_rtf_paste));\r
588     write_setting_i(sesskey, "MouseIsXterm", conf_get_int(conf, CONF_mouse_is_xterm));\r
589     write_setting_i(sesskey, "RectSelect", conf_get_int(conf, CONF_rect_select));\r
590     write_setting_i(sesskey, "MouseOverride", conf_get_int(conf, CONF_mouse_override));\r
591     for (i = 0; i < 256; i += 32) {\r
592         char buf[20], buf2[256];\r
593         int j;\r
594         sprintf(buf, "Wordness%d", i);\r
595         *buf2 = '\0';\r
596         for (j = i; j < i + 32; j++) {\r
597             sprintf(buf2 + strlen(buf2), "%s%d",\r
598                     (*buf2 ? "," : ""),\r
599                     conf_get_int_int(conf, CONF_wordness, j));\r
600         }\r
601         write_setting_s(sesskey, buf, buf2);\r
602     }\r
603     write_setting_s(sesskey, "LineCodePage", conf_get_str(conf, CONF_line_codepage));\r
604     write_setting_i(sesskey, "CJKAmbigWide", conf_get_int(conf, CONF_cjk_ambig_wide));\r
605     write_setting_i(sesskey, "UTF8Override", conf_get_int(conf, CONF_utf8_override));\r
606     write_setting_s(sesskey, "Printer", conf_get_str(conf, CONF_printer));\r
607     write_setting_i(sesskey, "CapsLockCyr", conf_get_int(conf, CONF_xlat_capslockcyr));\r
608     write_setting_i(sesskey, "ScrollBar", conf_get_int(conf, CONF_scrollbar));\r
609     write_setting_i(sesskey, "ScrollBarFullScreen", conf_get_int(conf, CONF_scrollbar_in_fullscreen));\r
610     write_setting_i(sesskey, "ScrollOnKey", conf_get_int(conf, CONF_scroll_on_key));\r
611     write_setting_i(sesskey, "ScrollOnDisp", conf_get_int(conf, CONF_scroll_on_disp));\r
612     write_setting_i(sesskey, "EraseToScrollback", conf_get_int(conf, CONF_erase_to_scrollback));\r
613     write_setting_i(sesskey, "LockSize", conf_get_int(conf, CONF_resize_action));\r
614     write_setting_i(sesskey, "BCE", conf_get_int(conf, CONF_bce));\r
615     write_setting_i(sesskey, "BlinkText", conf_get_int(conf, CONF_blinktext));\r
616     write_setting_i(sesskey, "X11Forward", conf_get_int(conf, CONF_x11_forward));\r
617     write_setting_s(sesskey, "X11Display", conf_get_str(conf, CONF_x11_display));\r
618     write_setting_i(sesskey, "X11AuthType", conf_get_int(conf, CONF_x11_auth));\r
619     write_setting_filename(sesskey, "X11AuthFile", conf_get_filename(conf, CONF_xauthfile));\r
620     write_setting_i(sesskey, "LocalPortAcceptAll", conf_get_int(conf, CONF_lport_acceptall));\r
621     write_setting_i(sesskey, "RemotePortAcceptAll", conf_get_int(conf, CONF_rport_acceptall));\r
622     wmap(sesskey, "PortForwardings", conf, CONF_portfwd, TRUE);\r
623     write_setting_i(sesskey, "BugIgnore1", 2-conf_get_int(conf, CONF_sshbug_ignore1));\r
624     write_setting_i(sesskey, "BugPlainPW1", 2-conf_get_int(conf, CONF_sshbug_plainpw1));\r
625     write_setting_i(sesskey, "BugRSA1", 2-conf_get_int(conf, CONF_sshbug_rsa1));\r
626     write_setting_i(sesskey, "BugIgnore2", 2-conf_get_int(conf, CONF_sshbug_ignore2));\r
627     write_setting_i(sesskey, "BugHMAC2", 2-conf_get_int(conf, CONF_sshbug_hmac2));\r
628     write_setting_i(sesskey, "BugDeriveKey2", 2-conf_get_int(conf, CONF_sshbug_derivekey2));\r
629     write_setting_i(sesskey, "BugRSAPad2", 2-conf_get_int(conf, CONF_sshbug_rsapad2));\r
630     write_setting_i(sesskey, "BugPKSessID2", 2-conf_get_int(conf, CONF_sshbug_pksessid2));\r
631     write_setting_i(sesskey, "BugRekey2", 2-conf_get_int(conf, CONF_sshbug_rekey2));\r
632     write_setting_i(sesskey, "BugMaxPkt2", 2-conf_get_int(conf, CONF_sshbug_maxpkt2));\r
633     write_setting_i(sesskey, "BugOldGex2", 2-conf_get_int(conf, CONF_sshbug_oldgex2));\r
634     write_setting_i(sesskey, "BugWinadj", 2-conf_get_int(conf, CONF_sshbug_winadj));\r
635     write_setting_i(sesskey, "BugChanReq", 2-conf_get_int(conf, CONF_sshbug_chanreq));\r
636     write_setting_i(sesskey, "StampUtmp", conf_get_int(conf, CONF_stamp_utmp));\r
637     write_setting_i(sesskey, "LoginShell", conf_get_int(conf, CONF_login_shell));\r
638     write_setting_i(sesskey, "ScrollbarOnLeft", conf_get_int(conf, CONF_scrollbar_on_left));\r
639     write_setting_fontspec(sesskey, "BoldFont", conf_get_fontspec(conf, CONF_boldfont));\r
640     write_setting_fontspec(sesskey, "WideFont", conf_get_fontspec(conf, CONF_widefont));\r
641     write_setting_fontspec(sesskey, "WideBoldFont", conf_get_fontspec(conf, CONF_wideboldfont));\r
642     write_setting_i(sesskey, "ShadowBold", conf_get_int(conf, CONF_shadowbold));\r
643     write_setting_i(sesskey, "ShadowBoldOffset", conf_get_int(conf, CONF_shadowboldoffset));\r
644     write_setting_s(sesskey, "SerialLine", conf_get_str(conf, CONF_serline));\r
645     write_setting_i(sesskey, "SerialSpeed", conf_get_int(conf, CONF_serspeed));\r
646     write_setting_i(sesskey, "SerialDataBits", conf_get_int(conf, CONF_serdatabits));\r
647     write_setting_i(sesskey, "SerialStopHalfbits", conf_get_int(conf, CONF_serstopbits));\r
648     write_setting_i(sesskey, "SerialParity", conf_get_int(conf, CONF_serparity));\r
649     write_setting_i(sesskey, "SerialFlowControl", conf_get_int(conf, CONF_serflow));\r
650     write_setting_s(sesskey, "WindowClass", conf_get_str(conf, CONF_winclass));\r
651     write_setting_i(sesskey, "ConnectionSharing", conf_get_int(conf, CONF_ssh_connection_sharing));\r
652     write_setting_i(sesskey, "ConnectionSharingUpstream", conf_get_int(conf, CONF_ssh_connection_sharing_upstream));\r
653     write_setting_i(sesskey, "ConnectionSharingDownstream", conf_get_int(conf, CONF_ssh_connection_sharing_downstream));\r
654     wmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys, FALSE);\r
657 void load_settings(char *section, Conf *conf)\r
659     void *sesskey;\r
661     sesskey = open_settings_r(section);\r
662     load_open_settings(sesskey, conf);\r
663     close_settings_r(sesskey);\r
665     if (conf_launchable(conf))\r
666         add_session_to_jumplist(section);\r
669 void load_open_settings(void *sesskey, Conf *conf)\r
671     int i;\r
672     char *prot;\r
674     conf_set_int(conf, CONF_ssh_subsys, 0);   /* FIXME: load this properly */\r
675     conf_set_str(conf, CONF_remote_cmd, "");\r
676     conf_set_str(conf, CONF_remote_cmd2, "");\r
677     conf_set_str(conf, CONF_ssh_nc_host, "");\r
679     gpps(sesskey, "HostName", "", conf, CONF_host);\r
680     gppfile(sesskey, "LogFileName", conf, CONF_logfilename);\r
681     gppi(sesskey, "LogType", 0, conf, CONF_logtype);\r
682     gppi(sesskey, "LogFileClash", LGXF_ASK, conf, CONF_logxfovr);\r
683     gppi(sesskey, "LogFlush", 1, conf, CONF_logflush);\r
684     gppi(sesskey, "SSHLogOmitPasswords", 1, conf, CONF_logomitpass);\r
685     gppi(sesskey, "SSHLogOmitData", 0, conf, CONF_logomitdata);\r
687     prot = gpps_raw(sesskey, "Protocol", "default");\r
688     conf_set_int(conf, CONF_protocol, default_protocol);\r
689     conf_set_int(conf, CONF_port, default_port);\r
690     {\r
691         const Backend *b = backend_from_name(prot);\r
692         if (b) {\r
693             conf_set_int(conf, CONF_protocol, b->protocol);\r
694             gppi(sesskey, "PortNumber", default_port, conf, CONF_port);\r
695         }\r
696     }\r
697     sfree(prot);\r
699     /* Address family selection */\r
700     gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, conf, CONF_addressfamily);\r
702     /* The CloseOnExit numbers are arranged in a different order from\r
703      * the standard FORCE_ON / FORCE_OFF / AUTO. */\r
704     i = gppi_raw(sesskey, "CloseOnExit", 1); conf_set_int(conf, CONF_close_on_exit, (i+1)%3);\r
705     gppi(sesskey, "WarnOnClose", 1, conf, CONF_warn_on_close);\r
706     {\r
707         /* This is two values for backward compatibility with 0.50/0.51 */\r
708         int pingmin, pingsec;\r
709         pingmin = gppi_raw(sesskey, "PingInterval", 0);\r
710         pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);\r
711         conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);\r
712     }\r
713     gppi(sesskey, "TCPNoDelay", 1, conf, CONF_tcp_nodelay);\r
714     gppi(sesskey, "TCPKeepalives", 0, conf, CONF_tcp_keepalives);\r
715     gpps(sesskey, "TerminalType", "xterm", conf, CONF_termtype);\r
716     gpps(sesskey, "TerminalSpeed", "38400,38400", conf, CONF_termspeed);\r
717     if (!gppmap(sesskey, "TerminalModes", conf, CONF_ttymodes)) {\r
718         /* This hardcodes a big set of defaults in any new saved\r
719          * sessions. Let's hope we don't change our mind. */\r
720         for (i = 0; ttymodes[i]; i++)\r
721             conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");\r
722     }\r
724     /* proxy settings */\r
725     gpps(sesskey, "ProxyExcludeList", "", conf, CONF_proxy_exclude_list);\r
726     i = gppi_raw(sesskey, "ProxyDNS", 1); conf_set_int(conf, CONF_proxy_dns, (i+1)%3);\r
727     gppi(sesskey, "ProxyLocalhost", 0, conf, CONF_even_proxy_localhost);\r
728     gppi(sesskey, "ProxyMethod", -1, conf, CONF_proxy_type);\r
729     if (conf_get_int(conf, CONF_proxy_type) == -1) {\r
730         int i;\r
731         i = gppi_raw(sesskey, "ProxyType", 0);\r
732         if (i == 0)\r
733             conf_set_int(conf, CONF_proxy_type, PROXY_NONE);\r
734         else if (i == 1)\r
735             conf_set_int(conf, CONF_proxy_type, PROXY_HTTP);\r
736         else if (i == 3)\r
737             conf_set_int(conf, CONF_proxy_type, PROXY_TELNET);\r
738         else if (i == 4)\r
739             conf_set_int(conf, CONF_proxy_type, PROXY_CMD);\r
740         else {\r
741             i = gppi_raw(sesskey, "ProxySOCKSVersion", 5);\r
742             if (i == 5)\r
743                 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS5);\r
744             else\r
745                 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS4);\r
746         }\r
747     }\r
748     gpps(sesskey, "ProxyHost", "proxy", conf, CONF_proxy_host);\r
749     gppi(sesskey, "ProxyPort", 80, conf, CONF_proxy_port);\r
750     gpps(sesskey, "ProxyUsername", "", conf, CONF_proxy_username);\r
751     gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);\r
752     gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",\r
753          conf, CONF_proxy_telnet_command);\r
754     gppmap(sesskey, "Environment", conf, CONF_environmt);\r
755     gpps(sesskey, "UserName", "", conf, CONF_username);\r
756     gppi(sesskey, "UserNameFromEnvironment", 0, conf, CONF_username_from_env);\r
757     gpps(sesskey, "LocalUserName", "", conf, CONF_localusername);\r
758     gppi(sesskey, "NoPTY", 0, conf, CONF_nopty);\r
759     gppi(sesskey, "Compression", 0, conf, CONF_compression);\r
760     gppi(sesskey, "TryAgent", 1, conf, CONF_tryagent);\r
761     gppi(sesskey, "AgentFwd", 0, conf, CONF_agentfwd);\r
762     gppi(sesskey, "ChangeUsername", 0, conf, CONF_change_username);\r
763     gppi(sesskey, "GssapiFwd", 0, conf, CONF_gssapifwd);\r
764     gprefs(sesskey, "Cipher", "\0",\r
765            ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);\r
766     {\r
767         /* Backward-compatibility: we used to have an option to\r
768          * disable gex under the "bugs" panel after one report of\r
769          * a server which offered it then choked, but we never got\r
770          * a server version string or any other reports. */\r
771         char *default_kexes;\r
772         i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);\r
773         if (i == FORCE_ON)\r
774             default_kexes = "dh-group14-sha1,dh-group1-sha1,rsa,WARN,dh-gex-sha1";\r
775         else\r
776             default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN";\r
777         gprefs(sesskey, "KEX", default_kexes,\r
778                kexnames, KEX_MAX, conf, CONF_ssh_kexlist);\r
779     }\r
780     gppi(sesskey, "RekeyTime", 60, conf, CONF_ssh_rekey_time);\r
781     gpps(sesskey, "RekeyBytes", "1G", conf, CONF_ssh_rekey_data);\r
782     /* SSH-2 only by default */\r
783     gppi(sesskey, "SshProt", 3, conf, CONF_sshprot);\r
784     gpps(sesskey, "LogHost", "", conf, CONF_loghost);\r
785     gppi(sesskey, "SSH2DES", 0, conf, CONF_ssh2_des_cbc);\r
786     gppi(sesskey, "SshNoAuth", 0, conf, CONF_ssh_no_userauth);\r
787     gppi(sesskey, "SshBanner", 1, conf, CONF_ssh_show_banner);\r
788     gppi(sesskey, "AuthTIS", 0, conf, CONF_try_tis_auth);\r
789     gppi(sesskey, "AuthKI", 1, conf, CONF_try_ki_auth);\r
790     gppi(sesskey, "AuthGSSAPI", 1, conf, CONF_try_gssapi_auth);\r
791 #ifndef NO_GSSAPI\r
792     gprefs(sesskey, "GSSLibs", "\0",\r
793            gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);\r
794     gppfile(sesskey, "GSSCustom", conf, CONF_ssh_gss_custom);\r
795 #endif\r
796     gppi(sesskey, "SshNoShell", 0, conf, CONF_ssh_no_shell);\r
797     gppfile(sesskey, "PublicKeyFile", conf, CONF_keyfile);\r
798     gpps(sesskey, "RemoteCommand", "", conf, CONF_remote_cmd);\r
799     gppi(sesskey, "RFCEnviron", 0, conf, CONF_rfc_environ);\r
800     gppi(sesskey, "PassiveTelnet", 0, conf, CONF_passive_telnet);\r
801     gppi(sesskey, "BackspaceIsDelete", 1, conf, CONF_bksp_is_delete);\r
802     gppi(sesskey, "RXVTHomeEnd", 0, conf, CONF_rxvt_homeend);\r
803     gppi(sesskey, "LinuxFunctionKeys", 0, conf, CONF_funky_type);\r
804     gppi(sesskey, "NoApplicationKeys", 0, conf, CONF_no_applic_k);\r
805     gppi(sesskey, "NoApplicationCursors", 0, conf, CONF_no_applic_c);\r
806     gppi(sesskey, "NoMouseReporting", 0, conf, CONF_no_mouse_rep);\r
807     gppi(sesskey, "NoRemoteResize", 0, conf, CONF_no_remote_resize);\r
808     gppi(sesskey, "NoAltScreen", 0, conf, CONF_no_alt_screen);\r
809     gppi(sesskey, "NoRemoteWinTitle", 0, conf, CONF_no_remote_wintitle);\r
810     {\r
811         /* Backward compatibility */\r
812         int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);\r
813         /* We deliberately interpret the old setting of "no response" as\r
814          * "empty string". This changes the behaviour, but hopefully for\r
815          * the better; the user can always recover the old behaviour. */\r
816         gppi(sesskey, "RemoteQTitleAction",\r
817              no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,\r
818              conf, CONF_remote_qtitle_action);\r
819     }\r
820     gppi(sesskey, "NoDBackspace", 0, conf, CONF_no_dbackspace);\r
821     gppi(sesskey, "NoRemoteCharset", 0, conf, CONF_no_remote_charset);\r
822     gppi(sesskey, "ApplicationCursorKeys", 0, conf, CONF_app_cursor);\r
823     gppi(sesskey, "ApplicationKeypad", 0, conf, CONF_app_keypad);\r
824     gppi(sesskey, "NetHackKeypad", 0, conf, CONF_nethack_keypad);\r
825     gppi(sesskey, "AltF4", 1, conf, CONF_alt_f4);\r
826     gppi(sesskey, "AltSpace", 0, conf, CONF_alt_space);\r
827     gppi(sesskey, "AltOnly", 0, conf, CONF_alt_only);\r
828     gppi(sesskey, "ComposeKey", 0, conf, CONF_compose_key);\r
829     gppi(sesskey, "CtrlAltKeys", 1, conf, CONF_ctrlaltkeys);\r
830     gppi(sesskey, "TelnetKey", 0, conf, CONF_telnet_keyboard);\r
831     gppi(sesskey, "TelnetRet", 1, conf, CONF_telnet_newline);\r
832     gppi(sesskey, "LocalEcho", AUTO, conf, CONF_localecho);\r
833     gppi(sesskey, "LocalEdit", AUTO, conf, CONF_localedit);\r
834     gpps(sesskey, "Answerback", "PuTTY", conf, CONF_answerback);\r
835     gppi(sesskey, "AlwaysOnTop", 0, conf, CONF_alwaysontop);\r
836     gppi(sesskey, "FullScreenOnAltEnter", 0, conf, CONF_fullscreenonaltenter);\r
837     gppi(sesskey, "HideMousePtr", 0, conf, CONF_hide_mouseptr);\r
838     gppi(sesskey, "SunkenEdge", 0, conf, CONF_sunken_edge);\r
839     gppi(sesskey, "WindowBorder", 1, conf, CONF_window_border);\r
840     gppi(sesskey, "CurType", 0, conf, CONF_cursor_type);\r
841     gppi(sesskey, "BlinkCur", 0, conf, CONF_blink_cur);\r
842     /* pedantic compiler tells me I can't use conf, CONF_beep as an int * :-) */\r
843     gppi(sesskey, "Beep", 1, conf, CONF_beep);\r
844     gppi(sesskey, "BeepInd", 0, conf, CONF_beep_ind);\r
845     gppfile(sesskey, "BellWaveFile", conf, CONF_bell_wavefile);\r
846     gppi(sesskey, "BellOverload", 1, conf, CONF_bellovl);\r
847     gppi(sesskey, "BellOverloadN", 5, conf, CONF_bellovl_n);\r
848     i = gppi_raw(sesskey, "BellOverloadT", 2*TICKSPERSEC\r
849 #ifdef PUTTY_UNIX_H\r
850                                    *1000\r
851 #endif\r
852                                    );\r
853     conf_set_int(conf, CONF_bellovl_t, i\r
854 #ifdef PUTTY_UNIX_H\r
855                  / 1000\r
856 #endif\r
857                  );\r
858     i = gppi_raw(sesskey, "BellOverloadS", 5*TICKSPERSEC\r
859 #ifdef PUTTY_UNIX_H\r
860                                    *1000\r
861 #endif\r
862                                    );\r
863     conf_set_int(conf, CONF_bellovl_s, i\r
864 #ifdef PUTTY_UNIX_H\r
865                  / 1000\r
866 #endif\r
867                  );\r
868     gppi(sesskey, "ScrollbackLines", 2000, conf, CONF_savelines);\r
869     gppi(sesskey, "DECOriginMode", 0, conf, CONF_dec_om);\r
870     gppi(sesskey, "AutoWrapMode", 1, conf, CONF_wrap_mode);\r
871     gppi(sesskey, "LFImpliesCR", 0, conf, CONF_lfhascr);\r
872     gppi(sesskey, "CRImpliesLF", 0, conf, CONF_crhaslf);\r
873     gppi(sesskey, "DisableArabicShaping", 0, conf, CONF_arabicshaping);\r
874     gppi(sesskey, "DisableBidi", 0, conf, CONF_bidi);\r
875     gppi(sesskey, "WinNameAlways", 1, conf, CONF_win_name_always);\r
876     gpps(sesskey, "WinTitle", "", conf, CONF_wintitle);\r
877     gppi(sesskey, "TermWidth", 80, conf, CONF_width);\r
878     gppi(sesskey, "TermHeight", 24, conf, CONF_height);\r
879     gppfont(sesskey, "Font", conf, CONF_font);\r
880     gppi(sesskey, "FontQuality", FQ_DEFAULT, conf, CONF_font_quality);\r
881     gppi(sesskey, "FontVTMode", VT_UNICODE, conf, CONF_vtmode);\r
882     gppi(sesskey, "UseSystemColours", 0, conf, CONF_system_colour);\r
883     gppi(sesskey, "TryPalette", 0, conf, CONF_try_palette);\r
884     gppi(sesskey, "ANSIColour", 1, conf, CONF_ansi_colour);\r
885     gppi(sesskey, "Xterm256Colour", 1, conf, CONF_xterm_256_colour);\r
886     i = gppi_raw(sesskey, "BoldAsColour", 1); conf_set_int(conf, CONF_bold_style, i+1);\r
888     for (i = 0; i < 22; i++) {\r
889         static const char *const defaults[] = {\r
890             "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",\r
891             "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",\r
892             "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",\r
893             "85,85,255", "187,0,187", "255,85,255", "0,187,187",\r
894             "85,255,255", "187,187,187", "255,255,255"\r
895         };\r
896         char buf[20], *buf2;\r
897         int c0, c1, c2;\r
898         sprintf(buf, "Colour%d", i);\r
899         buf2 = gpps_raw(sesskey, buf, defaults[i]);\r
900         if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {\r
901             conf_set_int_int(conf, CONF_colours, i*3+0, c0);\r
902             conf_set_int_int(conf, CONF_colours, i*3+1, c1);\r
903             conf_set_int_int(conf, CONF_colours, i*3+2, c2);\r
904         }\r
905         sfree(buf2);\r
906     }\r
907     gppi(sesskey, "RawCNP", 0, conf, CONF_rawcnp);\r
908     gppi(sesskey, "PasteRTF", 0, conf, CONF_rtf_paste);\r
909     gppi(sesskey, "MouseIsXterm", 0, conf, CONF_mouse_is_xterm);\r
910     gppi(sesskey, "RectSelect", 0, conf, CONF_rect_select);\r
911     gppi(sesskey, "MouseOverride", 1, conf, CONF_mouse_override);\r
912     for (i = 0; i < 256; i += 32) {\r
913         static const char *const defaults[] = {\r
914             "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
915             "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
916             "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
917             "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
918             "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
919             "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
920             "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
921             "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
922         };\r
923         char buf[20], *buf2, *p;\r
924         int j;\r
925         sprintf(buf, "Wordness%d", i);\r
926         buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);\r
927         p = buf2;\r
928         for (j = i; j < i + 32; j++) {\r
929             char *q = p;\r
930             while (*p && *p != ',')\r
931                 p++;\r
932             if (*p == ',')\r
933                 *p++ = '\0';\r
934             conf_set_int_int(conf, CONF_wordness, j, atoi(q));\r
935         }\r
936         sfree(buf2);\r
937     }\r
938     /*\r
939      * The empty default for LineCodePage will be converted later\r
940      * into a plausible default for the locale.\r
941      */\r
942     gpps(sesskey, "LineCodePage", "", conf, CONF_line_codepage);\r
943     gppi(sesskey, "CJKAmbigWide", 0, conf, CONF_cjk_ambig_wide);\r
944     gppi(sesskey, "UTF8Override", 1, conf, CONF_utf8_override);\r
945     gpps(sesskey, "Printer", "", conf, CONF_printer);\r
946     gppi(sesskey, "CapsLockCyr", 0, conf, CONF_xlat_capslockcyr);\r
947     gppi(sesskey, "ScrollBar", 1, conf, CONF_scrollbar);\r
948     gppi(sesskey, "ScrollBarFullScreen", 0, conf, CONF_scrollbar_in_fullscreen);\r
949     gppi(sesskey, "ScrollOnKey", 0, conf, CONF_scroll_on_key);\r
950     gppi(sesskey, "ScrollOnDisp", 1, conf, CONF_scroll_on_disp);\r
951     gppi(sesskey, "EraseToScrollback", 1, conf, CONF_erase_to_scrollback);\r
952     gppi(sesskey, "LockSize", 0, conf, CONF_resize_action);\r
953     gppi(sesskey, "BCE", 1, conf, CONF_bce);\r
954     gppi(sesskey, "BlinkText", 0, conf, CONF_blinktext);\r
955     gppi(sesskey, "X11Forward", 0, conf, CONF_x11_forward);\r
956     gpps(sesskey, "X11Display", "", conf, CONF_x11_display);\r
957     gppi(sesskey, "X11AuthType", X11_MIT, conf, CONF_x11_auth);\r
958     gppfile(sesskey, "X11AuthFile", conf, CONF_xauthfile);\r
960     gppi(sesskey, "LocalPortAcceptAll", 0, conf, CONF_lport_acceptall);\r
961     gppi(sesskey, "RemotePortAcceptAll", 0, conf, CONF_rport_acceptall);\r
962     gppmap(sesskey, "PortForwardings", conf, CONF_portfwd);\r
963     i = gppi_raw(sesskey, "BugIgnore1", 0); conf_set_int(conf, CONF_sshbug_ignore1, 2-i);\r
964     i = gppi_raw(sesskey, "BugPlainPW1", 0); conf_set_int(conf, CONF_sshbug_plainpw1, 2-i);\r
965     i = gppi_raw(sesskey, "BugRSA1", 0); conf_set_int(conf, CONF_sshbug_rsa1, 2-i);\r
966     i = gppi_raw(sesskey, "BugIgnore2", 0); conf_set_int(conf, CONF_sshbug_ignore2, 2-i);\r
967     {\r
968         int i;\r
969         i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);\r
970         if (2-i == AUTO) {\r
971             i = gppi_raw(sesskey, "BuggyMAC", 0);\r
972             if (i == 1)\r
973                 conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);\r
974         }\r
975     }\r
976     i = gppi_raw(sesskey, "BugDeriveKey2", 0); conf_set_int(conf, CONF_sshbug_derivekey2, 2-i);\r
977     i = gppi_raw(sesskey, "BugRSAPad2", 0); conf_set_int(conf, CONF_sshbug_rsapad2, 2-i);\r
978     i = gppi_raw(sesskey, "BugPKSessID2", 0); conf_set_int(conf, CONF_sshbug_pksessid2, 2-i);\r
979     i = gppi_raw(sesskey, "BugRekey2", 0); conf_set_int(conf, CONF_sshbug_rekey2, 2-i);\r
980     i = gppi_raw(sesskey, "BugMaxPkt2", 0); conf_set_int(conf, CONF_sshbug_maxpkt2, 2-i);\r
981     i = gppi_raw(sesskey, "BugOldGex2", 0); conf_set_int(conf, CONF_sshbug_oldgex2, 2-i);\r
982     i = gppi_raw(sesskey, "BugWinadj", 0); conf_set_int(conf, CONF_sshbug_winadj, 2-i);\r
983     i = gppi_raw(sesskey, "BugChanReq", 0); conf_set_int(conf, CONF_sshbug_chanreq, 2-i);\r
984     conf_set_int(conf, CONF_ssh_simple, FALSE);\r
985     gppi(sesskey, "StampUtmp", 1, conf, CONF_stamp_utmp);\r
986     gppi(sesskey, "LoginShell", 1, conf, CONF_login_shell);\r
987     gppi(sesskey, "ScrollbarOnLeft", 0, conf, CONF_scrollbar_on_left);\r
988     gppi(sesskey, "ShadowBold", 0, conf, CONF_shadowbold);\r
989     gppfont(sesskey, "BoldFont", conf, CONF_boldfont);\r
990     gppfont(sesskey, "WideFont", conf, CONF_widefont);\r
991     gppfont(sesskey, "WideBoldFont", conf, CONF_wideboldfont);\r
992     gppi(sesskey, "ShadowBoldOffset", 1, conf, CONF_shadowboldoffset);\r
993     gpps(sesskey, "SerialLine", "", conf, CONF_serline);\r
994     gppi(sesskey, "SerialSpeed", 9600, conf, CONF_serspeed);\r
995     gppi(sesskey, "SerialDataBits", 8, conf, CONF_serdatabits);\r
996     gppi(sesskey, "SerialStopHalfbits", 2, conf, CONF_serstopbits);\r
997     gppi(sesskey, "SerialParity", SER_PAR_NONE, conf, CONF_serparity);\r
998     gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, conf, CONF_serflow);\r
999     gpps(sesskey, "WindowClass", "", conf, CONF_winclass);\r
1000     gppi(sesskey, "ConnectionSharing", 0, conf, CONF_ssh_connection_sharing);\r
1001     gppi(sesskey, "ConnectionSharingUpstream", 1, conf, CONF_ssh_connection_sharing_upstream);\r
1002     gppi(sesskey, "ConnectionSharingDownstream", 1, conf, CONF_ssh_connection_sharing_downstream);\r
1003     gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys);\r
1006 void do_defaults(char *session, Conf *conf)\r
1008     load_settings(session, conf);\r
1011 static int sessioncmp(const void *av, const void *bv)\r
1013     const char *a = *(const char *const *) av;\r
1014     const char *b = *(const char *const *) bv;\r
1016     /*\r
1017      * Alphabetical order, except that "Default Settings" is a\r
1018      * special case and comes first.\r
1019      */\r
1020     if (!strcmp(a, "Default Settings"))\r
1021         return -1;                     /* a comes first */\r
1022     if (!strcmp(b, "Default Settings"))\r
1023         return +1;                     /* b comes first */\r
1024     /*\r
1025      * FIXME: perhaps we should ignore the first & in determining\r
1026      * sort order.\r
1027      */\r
1028     return strcmp(a, b);               /* otherwise, compare normally */\r
1031 void get_sesslist(struct sesslist *list, int allocate)\r
1033     char otherbuf[2048];\r
1034     int buflen, bufsize, i;\r
1035     char *p, *ret;\r
1036     void *handle;\r
1038     if (allocate) {\r
1040         buflen = bufsize = 0;\r
1041         list->buffer = NULL;\r
1042         if ((handle = enum_settings_start()) != NULL) {\r
1043             do {\r
1044                 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));\r
1045                 if (ret) {\r
1046                     int len = strlen(otherbuf) + 1;\r
1047                     if (bufsize < buflen + len) {\r
1048                         bufsize = buflen + len + 2048;\r
1049                         list->buffer = sresize(list->buffer, bufsize, char);\r
1050                     }\r
1051                     strcpy(list->buffer + buflen, otherbuf);\r
1052                     buflen += strlen(list->buffer + buflen) + 1;\r
1053                 }\r
1054             } while (ret);\r
1055             enum_settings_finish(handle);\r
1056         }\r
1057         list->buffer = sresize(list->buffer, buflen + 1, char);\r
1058         list->buffer[buflen] = '\0';\r
1060         /*\r
1061          * Now set up the list of sessions. Note that "Default\r
1062          * Settings" must always be claimed to exist, even if it\r
1063          * doesn't really.\r
1064          */\r
1066         p = list->buffer;\r
1067         list->nsessions = 1;           /* "Default Settings" counts as one */\r
1068         while (*p) {\r
1069             if (strcmp(p, "Default Settings"))\r
1070                 list->nsessions++;\r
1071             while (*p)\r
1072                 p++;\r
1073             p++;\r
1074         }\r
1076         list->sessions = snewn(list->nsessions + 1, char *);\r
1077         list->sessions[0] = "Default Settings";\r
1078         p = list->buffer;\r
1079         i = 1;\r
1080         while (*p) {\r
1081             if (strcmp(p, "Default Settings"))\r
1082                 list->sessions[i++] = p;\r
1083             while (*p)\r
1084                 p++;\r
1085             p++;\r
1086         }\r
1088         qsort(list->sessions, i, sizeof(char *), sessioncmp);\r
1089     } else {\r
1090         sfree(list->buffer);\r
1091         sfree(list->sessions);\r
1092         list->buffer = NULL;\r
1093         list->sessions = NULL;\r
1094     }\r