2 * settings.c: read and write saved sessions. (platform-independent)
\r
11 /* The cipher order given here is the default order. */
\r
12 static const struct keyval ciphernames[] = {
\r
13 { "aes", CIPHER_AES },
\r
14 { "blowfish", CIPHER_BLOWFISH },
\r
15 { "3des", CIPHER_3DES },
\r
16 { "WARN", CIPHER_WARN },
\r
17 { "arcfour", CIPHER_ARCFOUR },
\r
18 { "des", CIPHER_DES }
\r
21 static const struct keyval kexnames[] = {
\r
22 { "dh-gex-sha1", KEX_DHGEX },
\r
23 { "dh-group14-sha1", KEX_DHGROUP14 },
\r
24 { "dh-group1-sha1", KEX_DHGROUP1 },
\r
26 { "WARN", KEX_WARN }
\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
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
51 * Convenience functions to access the backends[] array
\r
52 * (which is only present in tools that manage settings).
\r
55 Backend *backend_from_name(const char *name)
\r
58 for (p = backends; *p != NULL; p++)
\r
59 if (!strcmp((*p)->name, name))
\r
64 Backend *backend_from_proto(int proto)
\r
67 for (p = backends; *p != NULL; p++)
\r
68 if ((*p)->protocol == proto)
\r
73 int get_remote_username(Config *cfg, char *user, size_t len)
\r
75 if (*cfg->username) {
\r
76 strncpy(user, cfg->username, len);
\r
79 if (cfg->username_from_env) {
\r
80 /* Use local username. */
\r
81 char *luser = get_username();
\r
83 strncpy(user, luser, len);
\r
93 return (*user != '\0');
\r
96 static void gpps(void *handle, const char *name, const char *def,
\r
99 if (!read_setting_s(handle, name, val, len)) {
\r
102 pdef = platform_default_s(name);
\r
104 strncpy(val, pdef, len);
\r
107 strncpy(val, def, len);
\r
110 val[len - 1] = '\0';
\r
115 * gppfont and gppfile cannot have local defaults, since the very
\r
116 * format of a Filename or Font is platform-dependent. So the
\r
117 * platform-dependent functions MUST return some sort of value.
\r
119 static void gppfont(void *handle, const char *name, FontSpec *result)
\r
121 if (!read_setting_fontspec(handle, name, result))
\r
122 *result = platform_default_fontspec(name);
\r
124 static void gppfile(void *handle, const char *name, Filename *result)
\r
126 if (!read_setting_filename(handle, name, result))
\r
127 *result = platform_default_filename(name);
\r
130 static void gppi(void *handle, char *name, int def, int *i)
\r
132 def = platform_default_i(name, def);
\r
133 *i = read_setting_i(handle, name, def);
\r
137 * Read a set of name-value pairs in the format we occasionally use:
\r
138 * NAME\tVALUE\0NAME\tVALUE\0\0 in memory
\r
139 * NAME=VALUE,NAME=VALUE, in storage
\r
140 * `def' is in the storage format.
\r
142 static void gppmap(void *handle, char *name, char *def, char *val, int len)
\r
144 char *buf = snewn(2*len, char), *p, *q;
\r
145 gpps(handle, name, def, buf, 2*len);
\r
149 while (*p && *p != ',') {
\r
166 * Write a set of name/value pairs in the above format.
\r
168 static void wmap(void *handle, char const *key, char const *value, int len)
\r
170 char *buf = snewn(2*len, char), *p;
\r
177 if (c == '=' || c == ',' || c == '\\')
\r
187 write_setting_s(handle, key, buf);
\r
191 static int key2val(const struct keyval *mapping, int nmaps, char *key)
\r
194 for (i = 0; i < nmaps; i++)
\r
195 if (!strcmp(mapping[i].s, key)) return mapping[i].v;
\r
199 static const char *val2key(const struct keyval *mapping, int nmaps, int val)
\r
202 for (i = 0; i < nmaps; i++)
\r
203 if (mapping[i].v == val) return mapping[i].s;
\r
208 * Helper function to parse a comma-separated list of strings into
\r
209 * a preference list array of values. Any missing values are added
\r
210 * to the end and duplicates are weeded.
\r
211 * XXX: assumes vals in 'mapping' are small +ve integers
\r
213 static void gprefs(void *sesskey, char *name, char *def,
\r
214 const struct keyval *mapping, int nvals,
\r
217 char commalist[80];
\r
218 char *tokarg = commalist;
\r
220 unsigned long seen = 0; /* bitmap for weeding dups etc */
\r
221 gpps(sesskey, name, def, commalist, sizeof(commalist));
\r
223 /* Grotty parsing of commalist. */
\r
228 key = strtok(tokarg, ","); /* sorry */
\r
231 if (((v = key2val(mapping, nvals, key)) != -1) &&
\r
237 } while (n < nvals);
\r
238 /* Add any missing values (backward compatibility ect). */
\r
241 for (i = 0; i < nvals; i++) {
\r
242 assert(mapping[i].v < 32);
\r
243 if (!(seen & 1<<mapping[i].v)) {
\r
244 array[n] = mapping[i].v;
\r
252 * Write out a preference list.
\r
254 static void wprefs(void *sesskey, char *name,
\r
255 const struct keyval *mapping, int nvals,
\r
258 char buf[80] = ""; /* XXX assumed big enough */
\r
259 int l = sizeof(buf)-1, i;
\r
261 for (i = 0; l > 0 && i < nvals; i++) {
\r
262 const char *s = val2key(mapping, nvals, array[i]);
\r
264 int sl = strlen(s);
\r
266 strncat(buf, ",", l);
\r
269 strncat(buf, s, l);
\r
273 write_setting_s(sesskey, name, buf);
\r
276 char *save_settings(char *section, Config * cfg)
\r
281 sesskey = open_settings_w(section, &errmsg);
\r
284 save_open_settings(sesskey, cfg);
\r
285 close_settings_w(sesskey);
\r
289 void save_open_settings(void *sesskey, Config *cfg)
\r
294 write_setting_i(sesskey, "Present", 1);
\r
295 write_setting_s(sesskey, "HostName", cfg->host);
\r
296 write_setting_filename(sesskey, "LogFileName", cfg->logfilename);
\r
297 write_setting_i(sesskey, "LogType", cfg->logtype);
\r
298 write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
\r
299 write_setting_i(sesskey, "LogFlush", cfg->logflush);
\r
300 write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass);
\r
301 write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata);
\r
304 const Backend *b = backend_from_proto(cfg->protocol);
\r
308 write_setting_s(sesskey, "Protocol", p);
\r
309 write_setting_i(sesskey, "PortNumber", cfg->port);
\r
310 /* The CloseOnExit numbers are arranged in a different order from
\r
311 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
312 write_setting_i(sesskey, "CloseOnExit", (cfg->close_on_exit+2)%3);
\r
313 write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
\r
314 write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
\r
315 write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
\r
316 write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
\r
317 write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives);
\r
318 write_setting_s(sesskey, "TerminalType", cfg->termtype);
\r
319 write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
\r
320 wmap(sesskey, "TerminalModes", cfg->ttymodes, lenof(cfg->ttymodes));
\r
322 /* Address family selection */
\r
323 write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
\r
325 /* proxy settings */
\r
326 write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
\r
327 write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
\r
328 write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost);
\r
329 write_setting_i(sesskey, "ProxyMethod", cfg->proxy_type);
\r
330 write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
\r
331 write_setting_i(sesskey, "ProxyPort", cfg->proxy_port);
\r
332 write_setting_s(sesskey, "ProxyUsername", cfg->proxy_username);
\r
333 write_setting_s(sesskey, "ProxyPassword", cfg->proxy_password);
\r
334 write_setting_s(sesskey, "ProxyTelnetCommand", cfg->proxy_telnet_command);
\r
335 wmap(sesskey, "Environment", cfg->environmt, lenof(cfg->environmt));
\r
336 write_setting_s(sesskey, "UserName", cfg->username);
\r
337 write_setting_i(sesskey, "UserNameFromEnvironment", cfg->username_from_env);
\r
338 write_setting_s(sesskey, "LocalUserName", cfg->localusername);
\r
339 write_setting_i(sesskey, "NoPTY", cfg->nopty);
\r
340 write_setting_i(sesskey, "Compression", cfg->compression);
\r
341 write_setting_i(sesskey, "TryAgent", cfg->tryagent);
\r
342 write_setting_i(sesskey, "AgentFwd", cfg->agentfwd);
\r
343 write_setting_i(sesskey, "GssapiFwd", cfg->gssapifwd);
\r
344 write_setting_i(sesskey, "ChangeUsername", cfg->change_username);
\r
345 wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX,
\r
346 cfg->ssh_cipherlist);
\r
347 wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist);
\r
348 write_setting_i(sesskey, "RekeyTime", cfg->ssh_rekey_time);
\r
349 write_setting_s(sesskey, "RekeyBytes", cfg->ssh_rekey_data);
\r
350 write_setting_i(sesskey, "SshNoAuth", cfg->ssh_no_userauth);
\r
351 write_setting_i(sesskey, "SshBanner", cfg->ssh_show_banner);
\r
352 write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
\r
353 write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
\r
354 write_setting_i(sesskey, "AuthGSSAPI", cfg->try_gssapi_auth);
\r
356 wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs,
\r
358 write_setting_filename(sesskey, "GSSCustom", cfg->ssh_gss_custom);
\r
360 write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
\r
361 write_setting_i(sesskey, "SshProt", cfg->sshprot);
\r
362 write_setting_s(sesskey, "LogHost", cfg->loghost);
\r
363 write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc);
\r
364 write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile);
\r
365 write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
\r
366 write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ);
\r
367 write_setting_i(sesskey, "PassiveTelnet", cfg->passive_telnet);
\r
368 write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete);
\r
369 write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend);
\r
370 write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type);
\r
371 write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k);
\r
372 write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c);
\r
373 write_setting_i(sesskey, "NoMouseReporting", cfg->no_mouse_rep);
\r
374 write_setting_i(sesskey, "NoRemoteResize", cfg->no_remote_resize);
\r
375 write_setting_i(sesskey, "NoAltScreen", cfg->no_alt_screen);
\r
376 write_setting_i(sesskey, "NoRemoteWinTitle", cfg->no_remote_wintitle);
\r
377 write_setting_i(sesskey, "RemoteQTitleAction", cfg->remote_qtitle_action);
\r
378 write_setting_i(sesskey, "NoDBackspace", cfg->no_dbackspace);
\r
379 write_setting_i(sesskey, "NoRemoteCharset", cfg->no_remote_charset);
\r
380 write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor);
\r
381 write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad);
\r
382 write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad);
\r
383 write_setting_i(sesskey, "AltF4", cfg->alt_f4);
\r
384 write_setting_i(sesskey, "AltSpace", cfg->alt_space);
\r
385 write_setting_i(sesskey, "AltOnly", cfg->alt_only);
\r
386 write_setting_i(sesskey, "ComposeKey", cfg->compose_key);
\r
387 write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys);
\r
388 write_setting_i(sesskey, "TelnetKey", cfg->telnet_keyboard);
\r
389 write_setting_i(sesskey, "TelnetRet", cfg->telnet_newline);
\r
390 write_setting_i(sesskey, "LocalEcho", cfg->localecho);
\r
391 write_setting_i(sesskey, "LocalEdit", cfg->localedit);
\r
392 write_setting_s(sesskey, "Answerback", cfg->answerback);
\r
393 write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop);
\r
394 write_setting_i(sesskey, "FullScreenOnAltEnter", cfg->fullscreenonaltenter);
\r
395 write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr);
\r
396 write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge);
\r
397 write_setting_i(sesskey, "WindowBorder", cfg->window_border);
\r
398 write_setting_i(sesskey, "CurType", cfg->cursor_type);
\r
399 write_setting_i(sesskey, "BlinkCur", cfg->blink_cur);
\r
400 write_setting_i(sesskey, "Beep", cfg->beep);
\r
401 write_setting_i(sesskey, "BeepInd", cfg->beep_ind);
\r
402 write_setting_filename(sesskey, "BellWaveFile", cfg->bell_wavefile);
\r
403 write_setting_i(sesskey, "BellOverload", cfg->bellovl);
\r
404 write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n);
\r
405 write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t
\r
406 #ifdef PUTTY_UNIX_H
\r
410 write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s
\r
411 #ifdef PUTTY_UNIX_H
\r
415 write_setting_i(sesskey, "ScrollbackLines", cfg->savelines);
\r
416 write_setting_i(sesskey, "DECOriginMode", cfg->dec_om);
\r
417 write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode);
\r
418 write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr);
\r
419 write_setting_i(sesskey, "CRImpliesLF", cfg->crhaslf);
\r
420 write_setting_i(sesskey, "DisableArabicShaping", cfg->arabicshaping);
\r
421 write_setting_i(sesskey, "DisableBidi", cfg->bidi);
\r
422 write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always);
\r
423 write_setting_s(sesskey, "WinTitle", cfg->wintitle);
\r
424 write_setting_i(sesskey, "TermWidth", cfg->width);
\r
425 write_setting_i(sesskey, "TermHeight", cfg->height);
\r
426 write_setting_fontspec(sesskey, "Font", cfg->font);
\r
427 write_setting_i(sesskey, "FontQuality", cfg->font_quality);
\r
428 write_setting_i(sesskey, "FontVTMode", cfg->vtmode);
\r
429 write_setting_i(sesskey, "UseSystemColours", cfg->system_colour);
\r
430 write_setting_i(sesskey, "TryPalette", cfg->try_palette);
\r
431 write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour);
\r
432 write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour);
\r
433 write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour);
\r
435 for (i = 0; i < 22; i++) {
\r
436 char buf[20], buf2[30];
\r
437 sprintf(buf, "Colour%d", i);
\r
438 sprintf(buf2, "%d,%d,%d", cfg->colours[i][0],
\r
439 cfg->colours[i][1], cfg->colours[i][2]);
\r
440 write_setting_s(sesskey, buf, buf2);
\r
442 write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
\r
443 write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste);
\r
444 write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
\r
445 write_setting_i(sesskey, "RectSelect", cfg->rect_select);
\r
446 write_setting_i(sesskey, "MouseOverride", cfg->mouse_override);
\r
447 for (i = 0; i < 256; i += 32) {
\r
448 char buf[20], buf2[256];
\r
450 sprintf(buf, "Wordness%d", i);
\r
452 for (j = i; j < i + 32; j++) {
\r
453 sprintf(buf2 + strlen(buf2), "%s%d",
\r
454 (*buf2 ? "," : ""), cfg->wordness[j]);
\r
456 write_setting_s(sesskey, buf, buf2);
\r
458 write_setting_s(sesskey, "LineCodePage", cfg->line_codepage);
\r
459 write_setting_i(sesskey, "CJKAmbigWide", cfg->cjk_ambig_wide);
\r
460 write_setting_i(sesskey, "UTF8Override", cfg->utf8_override);
\r
461 write_setting_s(sesskey, "Printer", cfg->printer);
\r
462 write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
\r
463 write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
\r
464 write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen);
\r
465 write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key);
\r
466 write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp);
\r
467 write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback);
\r
468 write_setting_i(sesskey, "LockSize", cfg->resize_action);
\r
469 write_setting_i(sesskey, "BCE", cfg->bce);
\r
470 write_setting_i(sesskey, "BlinkText", cfg->blinktext);
\r
471 write_setting_i(sesskey, "X11Forward", cfg->x11_forward);
\r
472 write_setting_s(sesskey, "X11Display", cfg->x11_display);
\r
473 write_setting_i(sesskey, "X11AuthType", cfg->x11_auth);
\r
474 write_setting_filename(sesskey, "X11AuthFile", cfg->xauthfile);
\r
475 write_setting_i(sesskey, "LocalPortAcceptAll", cfg->lport_acceptall);
\r
476 write_setting_i(sesskey, "RemotePortAcceptAll", cfg->rport_acceptall);
\r
477 wmap(sesskey, "PortForwardings", cfg->portfwd, lenof(cfg->portfwd));
\r
478 write_setting_i(sesskey, "BugIgnore1", 2-cfg->sshbug_ignore1);
\r
479 write_setting_i(sesskey, "BugPlainPW1", 2-cfg->sshbug_plainpw1);
\r
480 write_setting_i(sesskey, "BugRSA1", 2-cfg->sshbug_rsa1);
\r
481 write_setting_i(sesskey, "BugIgnore2", 2-cfg->sshbug_ignore2);
\r
482 write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2);
\r
483 write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
\r
484 write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
\r
485 write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
\r
486 write_setting_i(sesskey, "BugRekey2", 2-cfg->sshbug_rekey2);
\r
487 write_setting_i(sesskey, "BugMaxPkt2", 2-cfg->sshbug_maxpkt2);
\r
488 write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
\r
489 write_setting_i(sesskey, "LoginShell", cfg->login_shell);
\r
490 write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left);
\r
491 write_setting_fontspec(sesskey, "BoldFont", cfg->boldfont);
\r
492 write_setting_fontspec(sesskey, "WideFont", cfg->widefont);
\r
493 write_setting_fontspec(sesskey, "WideBoldFont", cfg->wideboldfont);
\r
494 write_setting_i(sesskey, "ShadowBold", cfg->shadowbold);
\r
495 write_setting_i(sesskey, "ShadowBoldOffset", cfg->shadowboldoffset);
\r
496 write_setting_s(sesskey, "SerialLine", cfg->serline);
\r
497 write_setting_i(sesskey, "SerialSpeed", cfg->serspeed);
\r
498 write_setting_i(sesskey, "SerialDataBits", cfg->serdatabits);
\r
499 write_setting_i(sesskey, "SerialStopHalfbits", cfg->serstopbits);
\r
500 write_setting_i(sesskey, "SerialParity", cfg->serparity);
\r
501 write_setting_i(sesskey, "SerialFlowControl", cfg->serflow);
\r
502 write_setting_s(sesskey, "WindowClass", cfg->winclass);
\r
505 void load_settings(char *section, Config * cfg)
\r
509 sesskey = open_settings_r(section);
\r
510 load_open_settings(sesskey, cfg);
\r
511 close_settings_r(sesskey);
\r
513 if (cfg_launchable(cfg))
\r
514 add_session_to_jumplist(section);
\r
517 void load_open_settings(void *sesskey, Config *cfg)
\r
522 cfg->ssh_subsys = 0; /* FIXME: load this properly */
\r
523 cfg->remote_cmd_ptr = NULL;
\r
524 cfg->remote_cmd_ptr2 = NULL;
\r
525 cfg->ssh_nc_host[0] = '\0';
\r
527 gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
\r
528 gppfile(sesskey, "LogFileName", &cfg->logfilename);
\r
529 gppi(sesskey, "LogType", 0, &cfg->logtype);
\r
530 gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
\r
531 gppi(sesskey, "LogFlush", 1, &cfg->logflush);
\r
532 gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass);
\r
533 gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata);
\r
535 gpps(sesskey, "Protocol", "default", prot, 10);
\r
536 cfg->protocol = default_protocol;
\r
537 cfg->port = default_port;
\r
539 const Backend *b = backend_from_name(prot);
\r
541 cfg->protocol = b->protocol;
\r
542 gppi(sesskey, "PortNumber", default_port, &cfg->port);
\r
546 /* Address family selection */
\r
547 gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
\r
549 /* The CloseOnExit numbers are arranged in a different order from
\r
550 * the standard FORCE_ON / FORCE_OFF / AUTO. */
\r
551 gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
\r
552 gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close);
\r
554 /* This is two values for backward compatibility with 0.50/0.51 */
\r
555 int pingmin, pingsec;
\r
556 gppi(sesskey, "PingInterval", 0, &pingmin);
\r
557 gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
\r
558 cfg->ping_interval = pingmin * 60 + pingsec;
\r
560 gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
\r
561 gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives);
\r
562 gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
\r
563 sizeof(cfg->termtype));
\r
564 gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
\r
565 sizeof(cfg->termspeed));
\r
567 /* This hardcodes a big set of defaults in any new saved
\r
568 * sessions. Let's hope we don't change our mind. */
\r
570 char *def = dupstr("");
\r
571 /* Default: all set to "auto" */
\r
572 for (i = 0; ttymodes[i]; i++) {
\r
573 char *def2 = dupprintf("%s%s=A,", def, ttymodes[i]);
\r
577 gppmap(sesskey, "TerminalModes", def,
\r
578 cfg->ttymodes, lenof(cfg->ttymodes));
\r
582 /* proxy settings */
\r
583 gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list,
\r
584 sizeof(cfg->proxy_exclude_list));
\r
585 gppi(sesskey, "ProxyDNS", 1, &i); cfg->proxy_dns = (i+1)%3;
\r
586 gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost);
\r
587 gppi(sesskey, "ProxyMethod", -1, &cfg->proxy_type);
\r
588 if (cfg->proxy_type == -1) {
\r
590 gppi(sesskey, "ProxyType", 0, &i);
\r
592 cfg->proxy_type = PROXY_NONE;
\r
594 cfg->proxy_type = PROXY_HTTP;
\r
596 cfg->proxy_type = PROXY_TELNET;
\r
598 cfg->proxy_type = PROXY_CMD;
\r
600 gppi(sesskey, "ProxySOCKSVersion", 5, &i);
\r
602 cfg->proxy_type = PROXY_SOCKS5;
\r
604 cfg->proxy_type = PROXY_SOCKS4;
\r
607 gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,
\r
608 sizeof(cfg->proxy_host));
\r
609 gppi(sesskey, "ProxyPort", 80, &cfg->proxy_port);
\r
610 gpps(sesskey, "ProxyUsername", "", cfg->proxy_username,
\r
611 sizeof(cfg->proxy_username));
\r
612 gpps(sesskey, "ProxyPassword", "", cfg->proxy_password,
\r
613 sizeof(cfg->proxy_password));
\r
614 gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
\r
615 cfg->proxy_telnet_command, sizeof(cfg->proxy_telnet_command));
\r
616 gppmap(sesskey, "Environment", "", cfg->environmt, lenof(cfg->environmt));
\r
617 gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
\r
618 gppi(sesskey, "UserNameFromEnvironment", 0, &cfg->username_from_env);
\r
619 gpps(sesskey, "LocalUserName", "", cfg->localusername,
\r
620 sizeof(cfg->localusername));
\r
621 gppi(sesskey, "NoPTY", 0, &cfg->nopty);
\r
622 gppi(sesskey, "Compression", 0, &cfg->compression);
\r
623 gppi(sesskey, "TryAgent", 1, &cfg->tryagent);
\r
624 gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd);
\r
625 gppi(sesskey, "ChangeUsername", 0, &cfg->change_username);
\r
626 gppi(sesskey, "GssapiFwd", 0, &cfg->gssapifwd);
\r
627 gprefs(sesskey, "Cipher", "\0",
\r
628 ciphernames, CIPHER_MAX, cfg->ssh_cipherlist);
\r
630 /* Backward-compatibility: we used to have an option to
\r
631 * disable gex under the "bugs" panel after one report of
\r
632 * a server which offered it then choked, but we never got
\r
633 * a server version string or any other reports. */
\r
634 char *default_kexes;
\r
635 gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i;
\r
637 default_kexes = "dh-group14-sha1,dh-group1-sha1,rsa,WARN,dh-gex-sha1";
\r
639 default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN";
\r
640 gprefs(sesskey, "KEX", default_kexes,
\r
641 kexnames, KEX_MAX, cfg->ssh_kexlist);
\r
643 gppi(sesskey, "RekeyTime", 60, &cfg->ssh_rekey_time);
\r
644 gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data,
\r
645 sizeof(cfg->ssh_rekey_data));
\r
646 gppi(sesskey, "SshProt", 2, &cfg->sshprot);
\r
647 gpps(sesskey, "LogHost", "", cfg->loghost, sizeof(cfg->loghost));
\r
648 gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
\r
649 gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth);
\r
650 gppi(sesskey, "SshBanner", 1, &cfg->ssh_show_banner);
\r
651 gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
\r
652 gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth);
\r
653 gppi(sesskey, "AuthGSSAPI", 1, &cfg->try_gssapi_auth);
\r
655 gprefs(sesskey, "GSSLibs", "\0",
\r
656 gsslibkeywords, ngsslibs, cfg->ssh_gsslist);
\r
657 gppfile(sesskey, "GSSCustom", &cfg->ssh_gss_custom);
\r
659 gppi(sesskey, "SshNoShell", 0, &cfg->ssh_no_shell);
\r
660 gppfile(sesskey, "PublicKeyFile", &cfg->keyfile);
\r
661 gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd,
\r
662 sizeof(cfg->remote_cmd));
\r
663 gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ);
\r
664 gppi(sesskey, "PassiveTelnet", 0, &cfg->passive_telnet);
\r
665 gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete);
\r
666 gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend);
\r
667 gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type);
\r
668 gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k);
\r
669 gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c);
\r
670 gppi(sesskey, "NoMouseReporting", 0, &cfg->no_mouse_rep);
\r
671 gppi(sesskey, "NoRemoteResize", 0, &cfg->no_remote_resize);
\r
672 gppi(sesskey, "NoAltScreen", 0, &cfg->no_alt_screen);
\r
673 gppi(sesskey, "NoRemoteWinTitle", 0, &cfg->no_remote_wintitle);
\r
675 /* Backward compatibility */
\r
676 int no_remote_qtitle;
\r
677 gppi(sesskey, "NoRemoteQTitle", 1, &no_remote_qtitle);
\r
678 /* We deliberately interpret the old setting of "no response" as
\r
679 * "empty string". This changes the behaviour, but hopefully for
\r
680 * the better; the user can always recover the old behaviour. */
\r
681 gppi(sesskey, "RemoteQTitleAction",
\r
682 no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
\r
683 &cfg->remote_qtitle_action);
\r
685 gppi(sesskey, "NoDBackspace", 0, &cfg->no_dbackspace);
\r
686 gppi(sesskey, "NoRemoteCharset", 0, &cfg->no_remote_charset);
\r
687 gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor);
\r
688 gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad);
\r
689 gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad);
\r
690 gppi(sesskey, "AltF4", 1, &cfg->alt_f4);
\r
691 gppi(sesskey, "AltSpace", 0, &cfg->alt_space);
\r
692 gppi(sesskey, "AltOnly", 0, &cfg->alt_only);
\r
693 gppi(sesskey, "ComposeKey", 0, &cfg->compose_key);
\r
694 gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys);
\r
695 gppi(sesskey, "TelnetKey", 0, &cfg->telnet_keyboard);
\r
696 gppi(sesskey, "TelnetRet", 1, &cfg->telnet_newline);
\r
697 gppi(sesskey, "LocalEcho", AUTO, &cfg->localecho);
\r
698 gppi(sesskey, "LocalEdit", AUTO, &cfg->localedit);
\r
699 gpps(sesskey, "Answerback", "PuTTY", cfg->answerback,
\r
700 sizeof(cfg->answerback));
\r
701 gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop);
\r
702 gppi(sesskey, "FullScreenOnAltEnter", 0, &cfg->fullscreenonaltenter);
\r
703 gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr);
\r
704 gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge);
\r
705 gppi(sesskey, "WindowBorder", 1, &cfg->window_border);
\r
706 gppi(sesskey, "CurType", 0, &cfg->cursor_type);
\r
707 gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur);
\r
708 /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */
\r
709 gppi(sesskey, "Beep", 1, &cfg->beep);
\r
710 gppi(sesskey, "BeepInd", 0, &cfg->beep_ind);
\r
711 gppfile(sesskey, "BellWaveFile", &cfg->bell_wavefile);
\r
712 gppi(sesskey, "BellOverload", 1, &cfg->bellovl);
\r
713 gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n);
\r
714 gppi(sesskey, "BellOverloadT", 2*TICKSPERSEC
\r
715 #ifdef PUTTY_UNIX_H
\r
720 #ifdef PUTTY_UNIX_H
\r
724 gppi(sesskey, "BellOverloadS", 5*TICKSPERSEC
\r
725 #ifdef PUTTY_UNIX_H
\r
730 #ifdef PUTTY_UNIX_H
\r
734 gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines);
\r
735 gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om);
\r
736 gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode);
\r
737 gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr);
\r
738 gppi(sesskey, "CRImpliesLF", 0, &cfg->crhaslf);
\r
739 gppi(sesskey, "DisableArabicShaping", 0, &cfg->arabicshaping);
\r
740 gppi(sesskey, "DisableBidi", 0, &cfg->bidi);
\r
741 gppi(sesskey, "WinNameAlways", 1, &cfg->win_name_always);
\r
742 gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle));
\r
743 gppi(sesskey, "TermWidth", 80, &cfg->width);
\r
744 gppi(sesskey, "TermHeight", 24, &cfg->height);
\r
745 gppfont(sesskey, "Font", &cfg->font);
\r
746 gppi(sesskey, "FontQuality", FQ_DEFAULT, &cfg->font_quality);
\r
747 gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode);
\r
748 gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour);
\r
749 gppi(sesskey, "TryPalette", 0, &cfg->try_palette);
\r
750 gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour);
\r
751 gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour);
\r
752 gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
\r
754 for (i = 0; i < 22; i++) {
\r
755 static const char *const defaults[] = {
\r
756 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
\r
757 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
\r
758 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
\r
759 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
\r
760 "85,255,255", "187,187,187", "255,255,255"
\r
762 char buf[20], buf2[30];
\r
764 sprintf(buf, "Colour%d", i);
\r
765 gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2));
\r
766 if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
\r
767 cfg->colours[i][0] = c0;
\r
768 cfg->colours[i][1] = c1;
\r
769 cfg->colours[i][2] = c2;
\r
772 gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
\r
773 gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste);
\r
774 gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
\r
775 gppi(sesskey, "RectSelect", 0, &cfg->rect_select);
\r
776 gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override);
\r
777 for (i = 0; i < 256; i += 32) {
\r
778 static const char *const defaults[] = {
\r
779 "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
780 "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
781 "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
782 "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
783 "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
784 "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
785 "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
786 "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
788 char buf[20], buf2[256], *p;
\r
790 sprintf(buf, "Wordness%d", i);
\r
791 gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2));
\r
793 for (j = i; j < i + 32; j++) {
\r
795 while (*p && *p != ',')
\r
799 cfg->wordness[j] = atoi(q);
\r
803 * The empty default for LineCodePage will be converted later
\r
804 * into a plausible default for the locale.
\r
806 gpps(sesskey, "LineCodePage", "", cfg->line_codepage,
\r
807 sizeof(cfg->line_codepage));
\r
808 gppi(sesskey, "CJKAmbigWide", 0, &cfg->cjk_ambig_wide);
\r
809 gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override);
\r
810 gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer));
\r
811 gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
\r
812 gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
\r
813 gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen);
\r
814 gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key);
\r
815 gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp);
\r
816 gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback);
\r
817 gppi(sesskey, "LockSize", 0, &cfg->resize_action);
\r
818 gppi(sesskey, "BCE", 1, &cfg->bce);
\r
819 gppi(sesskey, "BlinkText", 0, &cfg->blinktext);
\r
820 gppi(sesskey, "X11Forward", 0, &cfg->x11_forward);
\r
821 gpps(sesskey, "X11Display", "", cfg->x11_display,
\r
822 sizeof(cfg->x11_display));
\r
823 gppi(sesskey, "X11AuthType", X11_MIT, &cfg->x11_auth);
\r
824 gppfile(sesskey, "X11AuthFile", &cfg->xauthfile);
\r
826 gppi(sesskey, "LocalPortAcceptAll", 0, &cfg->lport_acceptall);
\r
827 gppi(sesskey, "RemotePortAcceptAll", 0, &cfg->rport_acceptall);
\r
828 gppmap(sesskey, "PortForwardings", "", cfg->portfwd, lenof(cfg->portfwd));
\r
829 gppi(sesskey, "BugIgnore1", 0, &i); cfg->sshbug_ignore1 = 2-i;
\r
830 gppi(sesskey, "BugPlainPW1", 0, &i); cfg->sshbug_plainpw1 = 2-i;
\r
831 gppi(sesskey, "BugRSA1", 0, &i); cfg->sshbug_rsa1 = 2-i;
\r
832 gppi(sesskey, "BugIgnore2", 0, &i); cfg->sshbug_ignore2 = 2-i;
\r
835 gppi(sesskey, "BugHMAC2", 0, &i); cfg->sshbug_hmac2 = 2-i;
\r
836 if (cfg->sshbug_hmac2 == AUTO) {
\r
837 gppi(sesskey, "BuggyMAC", 0, &i);
\r
839 cfg->sshbug_hmac2 = FORCE_ON;
\r
842 gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
\r
843 gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
\r
844 gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
\r
845 gppi(sesskey, "BugRekey2", 0, &i); cfg->sshbug_rekey2 = 2-i;
\r
846 gppi(sesskey, "BugMaxPkt2", 0, &i); cfg->sshbug_maxpkt2 = 2-i;
\r
847 cfg->ssh_simple = FALSE;
\r
848 gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
\r
849 gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
\r
850 gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left);
\r
851 gppi(sesskey, "ShadowBold", 0, &cfg->shadowbold);
\r
852 gppfont(sesskey, "BoldFont", &cfg->boldfont);
\r
853 gppfont(sesskey, "WideFont", &cfg->widefont);
\r
854 gppfont(sesskey, "WideBoldFont", &cfg->wideboldfont);
\r
855 gppi(sesskey, "ShadowBoldOffset", 1, &cfg->shadowboldoffset);
\r
856 gpps(sesskey, "SerialLine", "", cfg->serline, sizeof(cfg->serline));
\r
857 gppi(sesskey, "SerialSpeed", 9600, &cfg->serspeed);
\r
858 gppi(sesskey, "SerialDataBits", 8, &cfg->serdatabits);
\r
859 gppi(sesskey, "SerialStopHalfbits", 2, &cfg->serstopbits);
\r
860 gppi(sesskey, "SerialParity", SER_PAR_NONE, &cfg->serparity);
\r
861 gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, &cfg->serflow);
\r
862 gpps(sesskey, "WindowClass", "", cfg->winclass, sizeof(cfg->winclass));
\r
865 void do_defaults(char *session, Config * cfg)
\r
867 load_settings(session, cfg);
\r
870 static int sessioncmp(const void *av, const void *bv)
\r
872 const char *a = *(const char *const *) av;
\r
873 const char *b = *(const char *const *) bv;
\r
876 * Alphabetical order, except that "Default Settings" is a
\r
877 * special case and comes first.
\r
879 if (!strcmp(a, "Default Settings"))
\r
880 return -1; /* a comes first */
\r
881 if (!strcmp(b, "Default Settings"))
\r
882 return +1; /* b comes first */
\r
884 * FIXME: perhaps we should ignore the first & in determining
\r
887 return strcmp(a, b); /* otherwise, compare normally */
\r
890 void get_sesslist(struct sesslist *list, int allocate)
\r
892 char otherbuf[2048];
\r
893 int buflen, bufsize, i;
\r
899 buflen = bufsize = 0;
\r
900 list->buffer = NULL;
\r
901 if ((handle = enum_settings_start()) != NULL) {
\r
903 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
\r
905 int len = strlen(otherbuf) + 1;
\r
906 if (bufsize < buflen + len) {
\r
907 bufsize = buflen + len + 2048;
\r
908 list->buffer = sresize(list->buffer, bufsize, char);
\r
910 strcpy(list->buffer + buflen, otherbuf);
\r
911 buflen += strlen(list->buffer + buflen) + 1;
\r
914 enum_settings_finish(handle);
\r
916 list->buffer = sresize(list->buffer, buflen + 1, char);
\r
917 list->buffer[buflen] = '\0';
\r
920 * Now set up the list of sessions. Note that "Default
\r
921 * Settings" must always be claimed to exist, even if it
\r
926 list->nsessions = 1; /* "Default Settings" counts as one */
\r
928 if (strcmp(p, "Default Settings"))
\r
935 list->sessions = snewn(list->nsessions + 1, char *);
\r
936 list->sessions[0] = "Default Settings";
\r
940 if (strcmp(p, "Default Settings"))
\r
941 list->sessions[i++] = p;
\r
947 qsort(list->sessions, i, sizeof(char *), sessioncmp);
\r
949 sfree(list->buffer);
\r
950 sfree(list->sessions);
\r
951 list->buffer = NULL;
\r
952 list->sessions = NULL;
\r