2 * settings.c: read and write saved sessions. (platform-independent)
\r
12 * Tables of string <-> enum value mappings
\r
14 struct keyval { char *s; int v; };
\r
16 /* The cipher order given here is the default order. */
\r
17 static const struct keyval ciphernames[] = {
\r
18 { "aes", CIPHER_AES },
\r
19 { "blowfish", CIPHER_BLOWFISH },
\r
20 { "3des", CIPHER_3DES },
\r
21 { "WARN", CIPHER_WARN },
\r
22 { "arcfour", CIPHER_ARCFOUR },
\r
23 { "des", CIPHER_DES }
\r
26 static const struct keyval kexnames[] = {
\r
27 { "dh-gex-sha1", KEX_DHGEX },
\r
28 { "dh-group14-sha1", KEX_DHGROUP14 },
\r
29 { "dh-group1-sha1", KEX_DHGROUP1 },
\r
30 { "WARN", KEX_WARN }
\r
34 * All the terminal modes that we know about for the "TerminalModes"
\r
35 * setting. (Also used by config.c for the drop-down list.)
\r
36 * This is currently precisely the same as the set in ssh.c, but could
\r
37 * in principle differ if other backends started to support tty modes
\r
38 * (e.g., the pty backend).
\r
40 const char *const ttymodes[] = {
\r
41 "INTR", "QUIT", "ERASE", "KILL", "EOF",
\r
42 "EOL", "EOL2", "START", "STOP", "SUSP",
\r
43 "DSUSP", "REPRINT", "WERASE", "LNEXT", "FLUSH",
\r
44 "SWTCH", "STATUS", "DISCARD", "IGNPAR", "PARMRK",
\r
45 "INPCK", "ISTRIP", "INLCR", "IGNCR", "ICRNL",
\r
46 "IUCLC", "IXON", "IXANY", "IXOFF", "IMAXBEL",
\r
47 "ISIG", "ICANON", "XCASE", "ECHO", "ECHOE",
\r
48 "ECHOK", "ECHONL", "NOFLSH", "TOSTOP", "IEXTEN",
\r
49 "ECHOCTL", "ECHOKE", "PENDIN", "OPOST", "OLCUC",
\r
50 "ONLCR", "OCRNL", "ONOCR", "ONLRET", "CS7",
\r
51 "CS8", "PARENB", "PARODD", NULL
\r
54 static void gpps(void *handle, const char *name, const char *def,
\r
57 if (!read_setting_s(handle, name, val, len)) {
\r
60 pdef = platform_default_s(name);
\r
62 strncpy(val, pdef, len);
\r
65 strncpy(val, def, len);
\r
68 val[len - 1] = '\0';
\r
73 * gppfont and gppfile cannot have local defaults, since the very
\r
74 * format of a Filename or Font is platform-dependent. So the
\r
75 * platform-dependent functions MUST return some sort of value.
\r
77 static void gppfont(void *handle, const char *name, FontSpec *result)
\r
79 if (!read_setting_fontspec(handle, name, result))
\r
80 *result = platform_default_fontspec(name);
\r
82 static void gppfile(void *handle, const char *name, Filename *result)
\r
84 if (!read_setting_filename(handle, name, result))
\r
85 *result = platform_default_filename(name);
\r
88 static void gppi(void *handle, char *name, int def, int *i)
\r
90 def = platform_default_i(name, def);
\r
91 *i = read_setting_i(handle, name, def);
\r
95 * Read a set of name-value pairs in the format we occasionally use:
\r
96 * NAME\tVALUE\0NAME\tVALUE\0\0 in memory
\r
97 * NAME=VALUE,NAME=VALUE, in storage
\r
98 * `def' is in the storage format.
\r
100 static void gppmap(void *handle, char *name, char *def, char *val, int len)
\r
102 char *buf = snewn(2*len, char), *p, *q;
\r
103 gpps(handle, name, def, buf, 2*len);
\r
107 while (*p && *p != ',') {
\r
124 * Write a set of name/value pairs in the above format.
\r
126 static void wmap(void *handle, char const *key, char const *value, int len)
\r
128 char *buf = snewn(2*len, char), *p;
\r
135 if (c == '=' || c == ',' || c == '\\')
\r
145 write_setting_s(handle, key, buf);
\r
149 static int key2val(const struct keyval *mapping, int nmaps, char *key)
\r
152 for (i = 0; i < nmaps; i++)
\r
153 if (!strcmp(mapping[i].s, key)) return mapping[i].v;
\r
157 static const char *val2key(const struct keyval *mapping, int nmaps, int val)
\r
160 for (i = 0; i < nmaps; i++)
\r
161 if (mapping[i].v == val) return mapping[i].s;
\r
166 * Helper function to parse a comma-separated list of strings into
\r
167 * a preference list array of values. Any missing values are added
\r
168 * to the end and duplicates are weeded.
\r
169 * XXX: assumes vals in 'mapping' are small +ve integers
\r
171 static void gprefs(void *sesskey, char *name, char *def,
\r
172 const struct keyval *mapping, int nvals,
\r
175 char commalist[80];
\r
176 char *tokarg = commalist;
\r
178 unsigned long seen = 0; /* bitmap for weeding dups etc */
\r
179 gpps(sesskey, name, def, commalist, sizeof(commalist));
\r
181 /* Grotty parsing of commalist. */
\r
186 key = strtok(tokarg, ","); /* sorry */
\r
189 if (((v = key2val(mapping, nvals, key)) != -1) &&
\r
195 } while (n < nvals);
\r
196 /* Add any missing values (backward compatibility ect). */
\r
199 for (i = 0; i < nvals; i++) {
\r
200 assert(mapping[i].v < 32);
\r
201 if (!(seen & 1<<mapping[i].v)) {
\r
202 array[n] = mapping[i].v;
\r
210 * Write out a preference list.
\r
212 static void wprefs(void *sesskey, char *name,
\r
213 const struct keyval *mapping, int nvals,
\r
216 char buf[80] = ""; /* XXX assumed big enough */
\r
217 int l = sizeof(buf)-1, i;
\r
219 for (i = 0; l > 0 && i < nvals; i++) {
\r
220 const char *s = val2key(mapping, nvals, array[i]);
\r
222 int sl = strlen(s);
\r
224 strncat(buf, ",", l);
\r
227 strncat(buf, s, l);
\r
231 write_setting_s(sesskey, name, buf);
\r
234 char *save_settings(char *section, Config * cfg)
\r
239 sesskey = open_settings_w(section, &errmsg);
\r
242 save_open_settings(sesskey, cfg);
\r
243 close_settings_w(sesskey);
\r
247 void save_open_settings(void *sesskey, Config *cfg)
\r
252 write_setting_i(sesskey, "Present", 1);
\r
253 write_setting_s(sesskey, "HostName", cfg->host);
\r
254 write_setting_filename(sesskey, "LogFileName", cfg->logfilename);
\r
255 write_setting_i(sesskey, "LogType", cfg->logtype);
\r
256 write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
\r
257 write_setting_i(sesskey, "LogFlush", cfg->logflush);
\r
258 write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass);
\r
259 write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata);
\r
261 for (i = 0; backends[i].name != NULL; i++)
\r
262 if (backends[i].protocol == cfg->protocol) {
\r
263 p = backends[i].name;
\r
266 write_setting_s(sesskey, "Protocol", p);
\r
267 write_setting_i(sesskey, "PortNumber", cfg->port);
\r
268 /* The CloseOnExit numbers are arranged in a different order from
\r
269 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
270 write_setting_i(sesskey, "CloseOnExit", (cfg->close_on_exit+2)%3);
\r
271 write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
\r
272 write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
\r
273 write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
\r
274 write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
\r
275 write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives);
\r
276 write_setting_s(sesskey, "TerminalType", cfg->termtype);
\r
277 write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
\r
278 wmap(sesskey, "TerminalModes", cfg->ttymodes, lenof(cfg->ttymodes));
\r
280 /* Address family selection */
\r
281 write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
\r
283 /* proxy settings */
\r
284 write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
\r
285 write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
\r
286 write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost);
\r
287 write_setting_i(sesskey, "ProxyMethod", cfg->proxy_type);
\r
288 write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
\r
289 write_setting_i(sesskey, "ProxyPort", cfg->proxy_port);
\r
290 write_setting_s(sesskey, "ProxyUsername", cfg->proxy_username);
\r
291 write_setting_s(sesskey, "ProxyPassword", cfg->proxy_password);
\r
292 write_setting_s(sesskey, "ProxyTelnetCommand", cfg->proxy_telnet_command);
\r
293 wmap(sesskey, "Environment", cfg->environmt, lenof(cfg->environmt));
\r
294 write_setting_s(sesskey, "UserName", cfg->username);
\r
295 write_setting_s(sesskey, "LocalUserName", cfg->localusername);
\r
296 write_setting_i(sesskey, "NoPTY", cfg->nopty);
\r
297 write_setting_i(sesskey, "Compression", cfg->compression);
\r
298 write_setting_i(sesskey, "TryAgent", cfg->tryagent);
\r
299 write_setting_i(sesskey, "AgentFwd", cfg->agentfwd);
\r
300 write_setting_i(sesskey, "ChangeUsername", cfg->change_username);
\r
301 wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX,
\r
302 cfg->ssh_cipherlist);
\r
303 wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist);
\r
304 write_setting_i(sesskey, "RekeyTime", cfg->ssh_rekey_time);
\r
305 write_setting_s(sesskey, "RekeyBytes", cfg->ssh_rekey_data);
\r
306 write_setting_i(sesskey, "SshNoAuth", cfg->ssh_no_userauth);
\r
307 write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
\r
308 write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
\r
309 write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
\r
310 write_setting_i(sesskey, "SshProt", cfg->sshprot);
\r
311 write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc);
\r
312 write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile);
\r
313 write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
\r
314 write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ);
\r
315 write_setting_i(sesskey, "PassiveTelnet", cfg->passive_telnet);
\r
316 write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete);
\r
317 write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend);
\r
318 write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type);
\r
319 write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k);
\r
320 write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c);
\r
321 write_setting_i(sesskey, "NoMouseReporting", cfg->no_mouse_rep);
\r
322 write_setting_i(sesskey, "NoRemoteResize", cfg->no_remote_resize);
\r
323 write_setting_i(sesskey, "NoAltScreen", cfg->no_alt_screen);
\r
324 write_setting_i(sesskey, "NoRemoteWinTitle", cfg->no_remote_wintitle);
\r
325 write_setting_i(sesskey, "RemoteQTitleAction", cfg->remote_qtitle_action);
\r
326 write_setting_i(sesskey, "NoDBackspace", cfg->no_dbackspace);
\r
327 write_setting_i(sesskey, "NoRemoteCharset", cfg->no_remote_charset);
\r
328 write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor);
\r
329 write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad);
\r
330 write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad);
\r
331 write_setting_i(sesskey, "AltF4", cfg->alt_f4);
\r
332 write_setting_i(sesskey, "AltSpace", cfg->alt_space);
\r
333 write_setting_i(sesskey, "AltOnly", cfg->alt_only);
\r
334 write_setting_i(sesskey, "ComposeKey", cfg->compose_key);
\r
335 write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys);
\r
336 write_setting_i(sesskey, "TelnetKey", cfg->telnet_keyboard);
\r
337 write_setting_i(sesskey, "TelnetRet", cfg->telnet_newline);
\r
338 write_setting_i(sesskey, "LocalEcho", cfg->localecho);
\r
339 write_setting_i(sesskey, "LocalEdit", cfg->localedit);
\r
340 write_setting_s(sesskey, "Answerback", cfg->answerback);
\r
341 write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop);
\r
342 write_setting_i(sesskey, "FullScreenOnAltEnter", cfg->fullscreenonaltenter);
\r
343 write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr);
\r
344 write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge);
\r
345 write_setting_i(sesskey, "WindowBorder", cfg->window_border);
\r
346 write_setting_i(sesskey, "CurType", cfg->cursor_type);
\r
347 write_setting_i(sesskey, "BlinkCur", cfg->blink_cur);
\r
348 write_setting_i(sesskey, "Beep", cfg->beep);
\r
349 write_setting_i(sesskey, "BeepInd", cfg->beep_ind);
\r
350 write_setting_filename(sesskey, "BellWaveFile", cfg->bell_wavefile);
\r
351 write_setting_i(sesskey, "BellOverload", cfg->bellovl);
\r
352 write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n);
\r
353 write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t
\r
354 #ifdef PUTTY_UNIX_H
\r
358 write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s
\r
359 #ifdef PUTTY_UNIX_H
\r
363 write_setting_i(sesskey, "ScrollbackLines", cfg->savelines);
\r
364 write_setting_i(sesskey, "DECOriginMode", cfg->dec_om);
\r
365 write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode);
\r
366 write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr);
\r
367 write_setting_i(sesskey, "DisableArabicShaping", cfg->arabicshaping);
\r
368 write_setting_i(sesskey, "DisableBidi", cfg->bidi);
\r
369 write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always);
\r
370 write_setting_s(sesskey, "WinTitle", cfg->wintitle);
\r
371 write_setting_i(sesskey, "TermWidth", cfg->width);
\r
372 write_setting_i(sesskey, "TermHeight", cfg->height);
\r
373 write_setting_fontspec(sesskey, "Font", cfg->font);
\r
374 write_setting_i(sesskey, "FontQuality", cfg->font_quality);
\r
375 write_setting_i(sesskey, "FontVTMode", cfg->vtmode);
\r
376 write_setting_i(sesskey, "UseSystemColours", cfg->system_colour);
\r
377 write_setting_i(sesskey, "TryPalette", cfg->try_palette);
\r
378 write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour);
\r
379 write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour);
\r
380 write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour);
\r
382 for (i = 0; i < 22; i++) {
\r
383 char buf[20], buf2[30];
\r
384 sprintf(buf, "Colour%d", i);
\r
385 sprintf(buf2, "%d,%d,%d", cfg->colours[i][0],
\r
386 cfg->colours[i][1], cfg->colours[i][2]);
\r
387 write_setting_s(sesskey, buf, buf2);
\r
389 write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
\r
390 write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste);
\r
391 write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
\r
392 write_setting_i(sesskey, "RectSelect", cfg->rect_select);
\r
393 write_setting_i(sesskey, "MouseOverride", cfg->mouse_override);
\r
394 for (i = 0; i < 256; i += 32) {
\r
395 char buf[20], buf2[256];
\r
397 sprintf(buf, "Wordness%d", i);
\r
399 for (j = i; j < i + 32; j++) {
\r
400 sprintf(buf2 + strlen(buf2), "%s%d",
\r
401 (*buf2 ? "," : ""), cfg->wordness[j]);
\r
403 write_setting_s(sesskey, buf, buf2);
\r
405 write_setting_s(sesskey, "LineCodePage", cfg->line_codepage);
\r
406 write_setting_i(sesskey, "CJKAmbigWide", cfg->cjk_ambig_wide);
\r
407 write_setting_i(sesskey, "UTF8Override", cfg->utf8_override);
\r
408 write_setting_s(sesskey, "Printer", cfg->printer);
\r
409 write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
\r
410 write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
\r
411 write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen);
\r
412 write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key);
\r
413 write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp);
\r
414 write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback);
\r
415 write_setting_i(sesskey, "LockSize", cfg->resize_action);
\r
416 write_setting_i(sesskey, "BCE", cfg->bce);
\r
417 write_setting_i(sesskey, "BlinkText", cfg->blinktext);
\r
418 write_setting_i(sesskey, "X11Forward", cfg->x11_forward);
\r
419 write_setting_s(sesskey, "X11Display", cfg->x11_display);
\r
420 write_setting_i(sesskey, "X11AuthType", cfg->x11_auth);
\r
421 write_setting_i(sesskey, "LocalPortAcceptAll", cfg->lport_acceptall);
\r
422 write_setting_i(sesskey, "RemotePortAcceptAll", cfg->rport_acceptall);
\r
423 wmap(sesskey, "PortForwardings", cfg->portfwd, lenof(cfg->portfwd));
\r
424 write_setting_i(sesskey, "BugIgnore1", 2-cfg->sshbug_ignore1);
\r
425 write_setting_i(sesskey, "BugPlainPW1", 2-cfg->sshbug_plainpw1);
\r
426 write_setting_i(sesskey, "BugRSA1", 2-cfg->sshbug_rsa1);
\r
427 write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2);
\r
428 write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
\r
429 write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
\r
430 write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
\r
431 write_setting_i(sesskey, "BugRekey2", 2-cfg->sshbug_rekey2);
\r
432 write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
\r
433 write_setting_i(sesskey, "LoginShell", cfg->login_shell);
\r
434 write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left);
\r
435 write_setting_fontspec(sesskey, "BoldFont", cfg->boldfont);
\r
436 write_setting_fontspec(sesskey, "WideFont", cfg->widefont);
\r
437 write_setting_fontspec(sesskey, "WideBoldFont", cfg->wideboldfont);
\r
438 write_setting_i(sesskey, "ShadowBold", cfg->shadowbold);
\r
439 write_setting_i(sesskey, "ShadowBoldOffset", cfg->shadowboldoffset);
\r
440 write_setting_s(sesskey, "SerialLine", cfg->serline);
\r
441 write_setting_i(sesskey, "SerialSpeed", cfg->serspeed);
\r
442 write_setting_i(sesskey, "SerialDataBits", cfg->serdatabits);
\r
443 write_setting_i(sesskey, "SerialStopHalfbits", cfg->serstopbits);
\r
444 write_setting_i(sesskey, "SerialParity", cfg->serparity);
\r
445 write_setting_i(sesskey, "SerialFlowControl", cfg->serflow);
\r
448 void load_settings(char *section, Config * cfg)
\r
452 sesskey = open_settings_r(section);
\r
453 load_open_settings(sesskey, cfg);
\r
454 close_settings_r(sesskey);
\r
457 void load_open_settings(void *sesskey, Config *cfg)
\r
462 cfg->ssh_subsys = 0; /* FIXME: load this properly */
\r
463 cfg->remote_cmd_ptr = NULL;
\r
464 cfg->remote_cmd_ptr2 = NULL;
\r
465 cfg->ssh_nc_host[0] = '\0';
\r
467 gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
\r
468 gppfile(sesskey, "LogFileName", &cfg->logfilename);
\r
469 gppi(sesskey, "LogType", 0, &cfg->logtype);
\r
470 gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
\r
471 gppi(sesskey, "LogFlush", 1, &cfg->logflush);
\r
472 gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass);
\r
473 gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata);
\r
475 gpps(sesskey, "Protocol", "default", prot, 10);
\r
476 cfg->protocol = default_protocol;
\r
477 cfg->port = default_port;
\r
478 for (i = 0; backends[i].name != NULL; i++)
\r
479 if (!strcmp(prot, backends[i].name)) {
\r
480 cfg->protocol = backends[i].protocol;
\r
481 gppi(sesskey, "PortNumber", default_port, &cfg->port);
\r
485 /* Address family selection */
\r
486 gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
\r
488 /* The CloseOnExit numbers are arranged in a different order from
\r
489 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
490 gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
\r
491 gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close);
\r
493 /* This is two values for backward compatibility with 0.50/0.51 */
\r
494 int pingmin, pingsec;
\r
495 gppi(sesskey, "PingInterval", 0, &pingmin);
\r
496 gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
\r
497 cfg->ping_interval = pingmin * 60 + pingsec;
\r
499 gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
\r
500 gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives);
\r
501 gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
\r
502 sizeof(cfg->termtype));
\r
503 gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
\r
504 sizeof(cfg->termspeed));
\r
506 /* This hardcodes a big set of defaults in any new saved
\r
507 * sessions. Let's hope we don't change our mind. */
\r
509 char *def = dupstr("");
\r
510 /* Default: all set to "auto" */
\r
511 for (i = 0; ttymodes[i]; i++) {
\r
512 char *def2 = dupprintf("%s%s=A,", def, ttymodes[i]);
\r
516 gppmap(sesskey, "TerminalModes", def,
\r
517 cfg->ttymodes, lenof(cfg->ttymodes));
\r
521 /* proxy settings */
\r
522 gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list,
\r
523 sizeof(cfg->proxy_exclude_list));
\r
524 gppi(sesskey, "ProxyDNS", 1, &i); cfg->proxy_dns = (i+1)%3;
\r
525 gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost);
\r
526 gppi(sesskey, "ProxyMethod", -1, &cfg->proxy_type);
\r
527 if (cfg->proxy_type == -1) {
\r
529 gppi(sesskey, "ProxyType", 0, &i);
\r
531 cfg->proxy_type = PROXY_NONE;
\r
533 cfg->proxy_type = PROXY_HTTP;
\r
535 cfg->proxy_type = PROXY_TELNET;
\r
537 cfg->proxy_type = PROXY_CMD;
\r
539 gppi(sesskey, "ProxySOCKSVersion", 5, &i);
\r
541 cfg->proxy_type = PROXY_SOCKS5;
\r
543 cfg->proxy_type = PROXY_SOCKS4;
\r
546 gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,
\r
547 sizeof(cfg->proxy_host));
\r
548 gppi(sesskey, "ProxyPort", 80, &cfg->proxy_port);
\r
549 gpps(sesskey, "ProxyUsername", "", cfg->proxy_username,
\r
550 sizeof(cfg->proxy_username));
\r
551 gpps(sesskey, "ProxyPassword", "", cfg->proxy_password,
\r
552 sizeof(cfg->proxy_password));
\r
553 gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
\r
554 cfg->proxy_telnet_command, sizeof(cfg->proxy_telnet_command));
\r
555 gppmap(sesskey, "Environment", "", cfg->environmt, lenof(cfg->environmt));
\r
556 gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
\r
557 gpps(sesskey, "LocalUserName", "", cfg->localusername,
\r
558 sizeof(cfg->localusername));
\r
559 gppi(sesskey, "NoPTY", 0, &cfg->nopty);
\r
560 gppi(sesskey, "Compression", 0, &cfg->compression);
\r
561 gppi(sesskey, "TryAgent", 1, &cfg->tryagent);
\r
562 gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd);
\r
563 gppi(sesskey, "ChangeUsername", 0, &cfg->change_username);
\r
564 gprefs(sesskey, "Cipher", "\0",
\r
565 ciphernames, CIPHER_MAX, cfg->ssh_cipherlist);
\r
567 /* Backward-compatibility: we used to have an option to
\r
568 * disable gex under the "bugs" panel after one report of
\r
569 * a server which offered it then choked, but we never got
\r
570 * a server version string or any other reports. */
\r
571 char *default_kexes;
\r
572 gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i;
\r
574 default_kexes = "dh-group14-sha1,dh-group1-sha1,WARN,dh-gex-sha1";
\r
576 default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,WARN";
\r
577 gprefs(sesskey, "KEX", default_kexes,
\r
578 kexnames, KEX_MAX, cfg->ssh_kexlist);
\r
580 gppi(sesskey, "RekeyTime", 60, &cfg->ssh_rekey_time);
\r
581 gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data,
\r
582 sizeof(cfg->ssh_rekey_data));
\r
583 gppi(sesskey, "SshProt", 2, &cfg->sshprot);
\r
584 gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
\r
585 gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth);
\r
586 gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
\r
587 gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth);
\r
588 gppi(sesskey, "SshNoShell", 0, &cfg->ssh_no_shell);
\r
589 gppfile(sesskey, "PublicKeyFile", &cfg->keyfile);
\r
590 gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd,
\r
591 sizeof(cfg->remote_cmd));
\r
592 gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ);
\r
593 gppi(sesskey, "PassiveTelnet", 0, &cfg->passive_telnet);
\r
594 gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete);
\r
595 gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend);
\r
596 gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type);
\r
597 gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k);
\r
598 gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c);
\r
599 gppi(sesskey, "NoMouseReporting", 0, &cfg->no_mouse_rep);
\r
600 gppi(sesskey, "NoRemoteResize", 0, &cfg->no_remote_resize);
\r
601 gppi(sesskey, "NoAltScreen", 0, &cfg->no_alt_screen);
\r
602 gppi(sesskey, "NoRemoteWinTitle", 0, &cfg->no_remote_wintitle);
\r
604 /* Backward compatibility */
\r
605 int no_remote_qtitle;
\r
606 gppi(sesskey, "NoRemoteQTitle", 1, &no_remote_qtitle);
\r
607 /* We deliberately interpret the old setting of "no response" as
\r
608 * "empty string". This changes the behaviour, but hopefully for
\r
609 * the better; the user can always recover the old behaviour. */
\r
610 gppi(sesskey, "RemoteQTitleAction",
\r
611 no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
\r
612 &cfg->remote_qtitle_action);
\r
614 gppi(sesskey, "NoDBackspace", 0, &cfg->no_dbackspace);
\r
615 gppi(sesskey, "NoRemoteCharset", 0, &cfg->no_remote_charset);
\r
616 gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor);
\r
617 gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad);
\r
618 gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad);
\r
619 gppi(sesskey, "AltF4", 1, &cfg->alt_f4);
\r
620 gppi(sesskey, "AltSpace", 0, &cfg->alt_space);
\r
621 gppi(sesskey, "AltOnly", 0, &cfg->alt_only);
\r
622 gppi(sesskey, "ComposeKey", 0, &cfg->compose_key);
\r
623 gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys);
\r
624 gppi(sesskey, "TelnetKey", 0, &cfg->telnet_keyboard);
\r
625 gppi(sesskey, "TelnetRet", 1, &cfg->telnet_newline);
\r
626 gppi(sesskey, "LocalEcho", AUTO, &cfg->localecho);
\r
627 gppi(sesskey, "LocalEdit", AUTO, &cfg->localedit);
\r
628 gpps(sesskey, "Answerback", "PuTTY", cfg->answerback,
\r
629 sizeof(cfg->answerback));
\r
630 gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop);
\r
631 gppi(sesskey, "FullScreenOnAltEnter", 0, &cfg->fullscreenonaltenter);
\r
632 gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr);
\r
633 gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge);
\r
634 gppi(sesskey, "WindowBorder", 1, &cfg->window_border);
\r
635 gppi(sesskey, "CurType", 0, &cfg->cursor_type);
\r
636 gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur);
\r
637 /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */
\r
638 gppi(sesskey, "Beep", 1, &cfg->beep);
\r
639 gppi(sesskey, "BeepInd", 0, &cfg->beep_ind);
\r
640 gppfile(sesskey, "BellWaveFile", &cfg->bell_wavefile);
\r
641 gppi(sesskey, "BellOverload", 1, &cfg->bellovl);
\r
642 gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n);
\r
643 gppi(sesskey, "BellOverloadT", 2*TICKSPERSEC, &i);
\r
645 #ifdef PUTTY_UNIX_H
\r
649 gppi(sesskey, "BellOverloadS", 5*TICKSPERSEC, &i);
\r
651 #ifdef PUTTY_UNIX_H
\r
655 gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines);
\r
656 gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om);
\r
657 gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode);
\r
658 gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr);
\r
659 gppi(sesskey, "DisableArabicShaping", 0, &cfg->arabicshaping);
\r
660 gppi(sesskey, "DisableBidi", 0, &cfg->bidi);
\r
661 gppi(sesskey, "WinNameAlways", 1, &cfg->win_name_always);
\r
662 gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle));
\r
663 gppi(sesskey, "TermWidth", 80, &cfg->width);
\r
664 gppi(sesskey, "TermHeight", 24, &cfg->height);
\r
665 gppfont(sesskey, "Font", &cfg->font);
\r
666 gppi(sesskey, "FontQuality", FQ_DEFAULT, &cfg->font_quality);
\r
667 gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode);
\r
668 gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour);
\r
669 gppi(sesskey, "TryPalette", 0, &cfg->try_palette);
\r
670 gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour);
\r
671 gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour);
\r
672 gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
\r
674 for (i = 0; i < 22; i++) {
\r
675 static const char *const defaults[] = {
\r
676 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
\r
677 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
\r
678 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
\r
679 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
\r
680 "85,255,255", "187,187,187", "255,255,255"
\r
682 char buf[20], buf2[30];
\r
684 sprintf(buf, "Colour%d", i);
\r
685 gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2));
\r
686 if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
\r
687 cfg->colours[i][0] = c0;
\r
688 cfg->colours[i][1] = c1;
\r
689 cfg->colours[i][2] = c2;
\r
692 gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
\r
693 gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste);
\r
694 gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
\r
695 gppi(sesskey, "RectSelect", 0, &cfg->rect_select);
\r
696 gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override);
\r
697 for (i = 0; i < 256; i += 32) {
\r
698 static const char *const defaults[] = {
\r
699 "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
700 "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
701 "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
702 "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
703 "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
704 "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
705 "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
706 "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
708 char buf[20], buf2[256], *p;
\r
710 sprintf(buf, "Wordness%d", i);
\r
711 gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2));
\r
713 for (j = i; j < i + 32; j++) {
\r
715 while (*p && *p != ',')
\r
719 cfg->wordness[j] = atoi(q);
\r
723 * The empty default for LineCodePage will be converted later
\r
724 * into a plausible default for the locale.
\r
726 gpps(sesskey, "LineCodePage", "", cfg->line_codepage,
\r
727 sizeof(cfg->line_codepage));
\r
728 gppi(sesskey, "CJKAmbigWide", 0, &cfg->cjk_ambig_wide);
\r
729 gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override);
\r
730 gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer));
\r
731 gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
\r
732 gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
\r
733 gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen);
\r
734 gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key);
\r
735 gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp);
\r
736 gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback);
\r
737 gppi(sesskey, "LockSize", 0, &cfg->resize_action);
\r
738 gppi(sesskey, "BCE", 1, &cfg->bce);
\r
739 gppi(sesskey, "BlinkText", 0, &cfg->blinktext);
\r
740 gppi(sesskey, "X11Forward", 0, &cfg->x11_forward);
\r
741 gpps(sesskey, "X11Display", "", cfg->x11_display,
\r
742 sizeof(cfg->x11_display));
\r
743 gppi(sesskey, "X11AuthType", X11_MIT, &cfg->x11_auth);
\r
745 gppi(sesskey, "LocalPortAcceptAll", 0, &cfg->lport_acceptall);
\r
746 gppi(sesskey, "RemotePortAcceptAll", 0, &cfg->rport_acceptall);
\r
747 gppmap(sesskey, "PortForwardings", "", cfg->portfwd, lenof(cfg->portfwd));
\r
748 gppi(sesskey, "BugIgnore1", 0, &i); cfg->sshbug_ignore1 = 2-i;
\r
749 gppi(sesskey, "BugPlainPW1", 0, &i); cfg->sshbug_plainpw1 = 2-i;
\r
750 gppi(sesskey, "BugRSA1", 0, &i); cfg->sshbug_rsa1 = 2-i;
\r
753 gppi(sesskey, "BugHMAC2", 0, &i); cfg->sshbug_hmac2 = 2-i;
\r
754 if (cfg->sshbug_hmac2 == AUTO) {
\r
755 gppi(sesskey, "BuggyMAC", 0, &i);
\r
757 cfg->sshbug_hmac2 = FORCE_ON;
\r
760 gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
\r
761 gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
\r
762 gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
\r
763 gppi(sesskey, "BugRekey2", 0, &i); cfg->sshbug_rekey2 = 2-i;
\r
764 gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
\r
765 gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
\r
766 gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left);
\r
767 gppi(sesskey, "ShadowBold", 0, &cfg->shadowbold);
\r
768 gppfont(sesskey, "BoldFont", &cfg->boldfont);
\r
769 gppfont(sesskey, "WideFont", &cfg->widefont);
\r
770 gppfont(sesskey, "WideBoldFont", &cfg->wideboldfont);
\r
771 gppi(sesskey, "ShadowBoldOffset", 1, &cfg->shadowboldoffset);
\r
772 gpps(sesskey, "SerialLine", "", cfg->serline, sizeof(cfg->serline));
\r
773 gppi(sesskey, "SerialSpeed", 9600, &cfg->serspeed);
\r
774 gppi(sesskey, "SerialDataBits", 8, &cfg->serdatabits);
\r
775 gppi(sesskey, "SerialStopHalfbits", 2, &cfg->serstopbits);
\r
776 gppi(sesskey, "SerialParity", SER_PAR_NONE, &cfg->serparity);
\r
777 gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, &cfg->serflow);
\r
780 void do_defaults(char *session, Config * cfg)
\r
782 load_settings(session, cfg);
\r
785 static int sessioncmp(const void *av, const void *bv)
\r
787 const char *a = *(const char *const *) av;
\r
788 const char *b = *(const char *const *) bv;
\r
791 * Alphabetical order, except that "Default Settings" is a
\r
792 * special case and comes first.
\r
794 if (!strcmp(a, "Default Settings"))
\r
795 return -1; /* a comes first */
\r
796 if (!strcmp(b, "Default Settings"))
\r
797 return +1; /* b comes first */
\r
799 * FIXME: perhaps we should ignore the first & in determining
\r
802 return strcmp(a, b); /* otherwise, compare normally */
\r
805 void get_sesslist(struct sesslist *list, int allocate)
\r
807 char otherbuf[2048];
\r
808 int buflen, bufsize, i;
\r
814 buflen = bufsize = 0;
\r
815 list->buffer = NULL;
\r
816 if ((handle = enum_settings_start()) != NULL) {
\r
818 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
\r
820 int len = strlen(otherbuf) + 1;
\r
821 if (bufsize < buflen + len) {
\r
822 bufsize = buflen + len + 2048;
\r
823 list->buffer = sresize(list->buffer, bufsize, char);
\r
825 strcpy(list->buffer + buflen, otherbuf);
\r
826 buflen += strlen(list->buffer + buflen) + 1;
\r
829 enum_settings_finish(handle);
\r
831 list->buffer = sresize(list->buffer, buflen + 1, char);
\r
832 list->buffer[buflen] = '\0';
\r
835 * Now set up the list of sessions. Note that "Default
\r
836 * Settings" must always be claimed to exist, even if it
\r
841 list->nsessions = 1; /* "Default Settings" counts as one */
\r
843 if (strcmp(p, "Default Settings"))
\r
850 list->sessions = snewn(list->nsessions + 1, char *);
\r
851 list->sessions[0] = "Default Settings";
\r
855 if (strcmp(p, "Default Settings"))
\r
856 list->sessions[i++] = p;
\r
862 qsort(list->sessions, i, sizeof(char *), sessioncmp);
\r
864 sfree(list->buffer);
\r
865 sfree(list->sessions);
\r
866 list->buffer = NULL;
\r
867 list->sessions = NULL;
\r