OSDN Git Service

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