2 * settings.c: read and write saved sessions.
11 static void gpps(void *handle
, char *name
, char *def
, char *val
, int len
)
13 if (!read_setting_s(handle
, name
, val
, len
)) {
14 strncpy(val
, def
, len
);
19 static void gppi(void *handle
, char *name
, int def
, int *i
)
21 *i
= read_setting_i(handle
, name
, def
);
24 void save_settings(char *section
, int do_host
, Config
* cfg
)
30 sesskey
= open_settings_w(section
);
34 write_setting_i(sesskey
, "Present", 1);
36 write_setting_s(sesskey
, "HostName", cfg
->host
);
37 write_setting_s(sesskey
, "LogFileName", cfg
->logfilename
);
38 write_setting_i(sesskey
, "LogType", cfg
->logtype
);
39 write_setting_i(sesskey
, "LogFileClash", cfg
->logxfovr
);
42 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
43 if (backends
[i
].protocol
== cfg
->protocol
) {
47 write_setting_s(sesskey
, "Protocol", p
);
48 write_setting_i(sesskey
, "PortNumber", cfg
->port
);
49 write_setting_i(sesskey
, "CloseOnExit", cfg
->close_on_exit
);
50 write_setting_i(sesskey
, "WarnOnClose", !!cfg
->warn_on_close
);
51 write_setting_i(sesskey
, "PingInterval", cfg
->ping_interval
/ 60); /* minutes */
52 write_setting_i(sesskey
, "PingIntervalSecs", cfg
->ping_interval
% 60); /* seconds */
53 write_setting_s(sesskey
, "TerminalType", cfg
->termtype
);
54 write_setting_s(sesskey
, "TerminalSpeed", cfg
->termspeed
);
56 char buf
[2 * sizeof(cfg
->environmt
)], *p
, *q
;
62 if (c
== '=' || c
== ',' || c
== '\\')
72 write_setting_s(sesskey
, "Environment", buf
);
74 write_setting_s(sesskey
, "UserName", cfg
->username
);
75 write_setting_s(sesskey
, "LocalUserName", cfg
->localusername
);
76 write_setting_i(sesskey
, "NoPTY", cfg
->nopty
);
77 write_setting_i(sesskey
, "Compression", cfg
->compression
);
78 write_setting_i(sesskey
, "AgentFwd", cfg
->agentfwd
);
79 write_setting_s(sesskey
, "Cipher",
80 cfg
->cipher
== CIPHER_BLOWFISH ?
"blowfish" :
81 cfg
->cipher
== CIPHER_DES ?
"des" :
82 cfg
->cipher
== CIPHER_AES ?
"aes" : "3des");
83 write_setting_i(sesskey
, "AuthTIS", cfg
->try_tis_auth
);
84 write_setting_i(sesskey
, "SshProt", cfg
->sshprot
);
85 write_setting_i(sesskey
, "BuggyMAC", cfg
->buggymac
);
86 write_setting_s(sesskey
, "PublicKeyFile", cfg
->keyfile
);
87 write_setting_s(sesskey
, "RemoteCommand", cfg
->remote_cmd
);
88 write_setting_i(sesskey
, "RFCEnviron", cfg
->rfc_environ
);
89 write_setting_i(sesskey
, "PassiveTelnet", cfg
->passive_telnet
);
90 write_setting_i(sesskey
, "BackspaceIsDelete", cfg
->bksp_is_delete
);
91 write_setting_i(sesskey
, "RXVTHomeEnd", cfg
->rxvt_homeend
);
92 write_setting_i(sesskey
, "LinuxFunctionKeys", cfg
->funky_type
);
93 write_setting_i(sesskey
, "NoApplicationKeys", cfg
->no_applic_k
);
94 write_setting_i(sesskey
, "NoApplicationCursors", cfg
->no_applic_c
);
95 write_setting_i(sesskey
, "ApplicationCursorKeys", cfg
->app_cursor
);
96 write_setting_i(sesskey
, "ApplicationKeypad", cfg
->app_keypad
);
97 write_setting_i(sesskey
, "NetHackKeypad", cfg
->nethack_keypad
);
98 write_setting_i(sesskey
, "AltF4", cfg
->alt_f4
);
99 write_setting_i(sesskey
, "AltSpace", cfg
->alt_space
);
100 write_setting_i(sesskey
, "AltOnly", cfg
->alt_only
);
101 write_setting_i(sesskey
, "ComposeKey", cfg
->compose_key
);
102 write_setting_i(sesskey
, "CtrlAltKeys", cfg
->ctrlaltkeys
);
103 write_setting_i(sesskey
, "TelnetKey", cfg
->telnet_keyboard
);
104 write_setting_i(sesskey
, "LocalEcho", cfg
->localecho
);
105 write_setting_i(sesskey
, "LocalEdit", cfg
->localedit
);
106 write_setting_s(sesskey
, "Answerback", cfg
->answerback
);
107 write_setting_i(sesskey
, "AlwaysOnTop", cfg
->alwaysontop
);
108 write_setting_i(sesskey
, "HideMousePtr", cfg
->hide_mouseptr
);
109 write_setting_i(sesskey
, "SunkenEdge", cfg
->sunken_edge
);
110 write_setting_i(sesskey
, "CurType", cfg
->cursor_type
);
111 write_setting_i(sesskey
, "BlinkCur", cfg
->blink_cur
);
112 write_setting_i(sesskey
, "Beep", cfg
->beep
);
113 write_setting_i(sesskey
, "BeepInd", cfg
->beep_ind
);
114 write_setting_s(sesskey
, "BellWaveFile", cfg
->bell_wavefile
);
115 write_setting_i(sesskey
, "BellOverload", cfg
->bellovl
);
116 write_setting_i(sesskey
, "BellOverloadN", cfg
->bellovl_n
);
117 write_setting_i(sesskey
, "BellOverloadT", cfg
->bellovl_t
);
118 write_setting_i(sesskey
, "BellOverloadS", cfg
->bellovl_s
);
119 write_setting_i(sesskey
, "ScrollbackLines", cfg
->savelines
);
120 write_setting_i(sesskey
, "DECOriginMode", cfg
->dec_om
);
121 write_setting_i(sesskey
, "AutoWrapMode", cfg
->wrap_mode
);
122 write_setting_i(sesskey
, "LFImpliesCR", cfg
->lfhascr
);
123 write_setting_i(sesskey
, "WinNameAlways", cfg
->win_name_always
);
124 write_setting_s(sesskey
, "WinTitle", cfg
->wintitle
);
125 write_setting_i(sesskey
, "TermWidth", cfg
->width
);
126 write_setting_i(sesskey
, "TermHeight", cfg
->height
);
127 write_setting_s(sesskey
, "Font", cfg
->font
);
128 write_setting_i(sesskey
, "FontIsBold", cfg
->fontisbold
);
129 write_setting_i(sesskey
, "FontCharSet", cfg
->fontcharset
);
130 write_setting_i(sesskey
, "FontHeight", cfg
->fontheight
);
131 write_setting_i(sesskey
, "FontVTMode", cfg
->vtmode
);
132 write_setting_i(sesskey
, "TryPalette", cfg
->try_palette
);
133 write_setting_i(sesskey
, "BoldAsColour", cfg
->bold_colour
);
134 for (i
= 0; i
< 22; i
++) {
135 char buf
[20], buf2
[30];
136 sprintf(buf
, "Colour%d", i
);
137 sprintf(buf2
, "%d,%d,%d", cfg
->colours
[i
][0],
138 cfg
->colours
[i
][1], cfg
->colours
[i
][2]);
139 write_setting_s(sesskey
, buf
, buf2
);
141 write_setting_i(sesskey
, "RawCNP", cfg
->rawcnp
);
142 write_setting_i(sesskey
, "MouseIsXterm", cfg
->mouse_is_xterm
);
143 for (i
= 0; i
< 256; i
+= 32) {
144 char buf
[20], buf2
[256];
146 sprintf(buf
, "Wordness%d", i
);
148 for (j
= i
; j
< i
+ 32; j
++) {
149 sprintf(buf2
+ strlen(buf2
), "%s%d",
150 (*buf2 ?
"," : ""), cfg
->wordness
[j
]);
152 write_setting_s(sesskey
, buf
, buf2
);
154 write_setting_s(sesskey
, "LineCodePage", cfg
->line_codepage
);
155 write_setting_i(sesskey
, "ScrollBar", cfg
->scrollbar
);
156 write_setting_i(sesskey
, "ScrollOnKey", cfg
->scroll_on_key
);
157 write_setting_i(sesskey
, "ScrollOnDisp", cfg
->scroll_on_disp
);
158 write_setting_i(sesskey
, "LockSize", cfg
->locksize
);
159 write_setting_i(sesskey
, "BCE", cfg
->bce
);
160 write_setting_i(sesskey
, "BlinkText", cfg
->blinktext
);
161 write_setting_i(sesskey
, "X11Forward", cfg
->x11_forward
);
162 write_setting_s(sesskey
, "X11Display", cfg
->x11_display
);
163 write_setting_i(sesskey
, "LocalPortAcceptAll", cfg
->lport_acceptall
);
165 char buf
[2 * sizeof(cfg
->portfwd
)], *p
, *q
;
171 if (c
== '=' || c
== ',' || c
== '\\')
181 write_setting_s(sesskey
, "PortForwardings", buf
);
184 close_settings_w(sesskey
);
187 void load_settings(char *section
, int do_host
, Config
* cfg
)
193 sesskey
= open_settings_r(section
);
195 cfg
->ssh_subsys
= 0; /* FIXME: load this properly */
196 cfg
->remote_cmd_ptr
= cfg
->remote_cmd
;
198 gpps(sesskey
, "HostName", "", cfg
->host
, sizeof(cfg
->host
));
199 gppi(sesskey
, "PortNumber", default_port
, &cfg
->port
);
200 gpps(sesskey
, "LogFileName", "putty.log",
201 cfg
->logfilename
, sizeof(cfg
->logfilename
));
202 gppi(sesskey
, "LogType", 0, &cfg
->logtype
);
203 gppi(sesskey
, "LogFileClash", LGXF_ASK
, &cfg
->logxfovr
);
205 gpps(sesskey
, "Protocol", "default", prot
, 10);
206 cfg
->protocol
= default_protocol
;
207 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
208 if (!strcmp(prot
, backends
[i
].name
)) {
209 cfg
->protocol
= backends
[i
].protocol
;
213 gppi(sesskey
, "CloseOnExit", COE_NORMAL
, &cfg
->close_on_exit
);
214 gppi(sesskey
, "WarnOnClose", 1, &cfg
->warn_on_close
);
216 /* This is two values for backward compatibility with 0.50/0.51 */
217 int pingmin
, pingsec
;
218 gppi(sesskey
, "PingInterval", 0, &pingmin
);
219 gppi(sesskey
, "PingIntervalSecs", 0, &pingsec
);
220 cfg
->ping_interval
= pingmin
* 60 + pingsec
;
222 gpps(sesskey
, "TerminalType", "xterm", cfg
->termtype
,
223 sizeof(cfg
->termtype
));
224 gpps(sesskey
, "TerminalSpeed", "38400,38400", cfg
->termspeed
,
225 sizeof(cfg
->termspeed
));
227 char buf
[2 * sizeof(cfg
->environmt
)], *p
, *q
;
228 gpps(sesskey
, "Environment", "", buf
, sizeof(buf
));
232 while (*p
&& *p
!= ',') {
246 gpps(sesskey
, "UserName", "", cfg
->username
, sizeof(cfg
->username
));
247 gpps(sesskey
, "LocalUserName", "", cfg
->localusername
,
248 sizeof(cfg
->localusername
));
249 gppi(sesskey
, "NoPTY", 0, &cfg
->nopty
);
250 gppi(sesskey
, "Compression", 0, &cfg
->compression
);
251 gppi(sesskey
, "AgentFwd", 0, &cfg
->agentfwd
);
254 gpps(sesskey
, "Cipher", "3des", cipher
, 10);
255 if (!strcmp(cipher
, "blowfish"))
256 cfg
->cipher
= CIPHER_BLOWFISH
;
257 else if (!strcmp(cipher
, "des"))
258 cfg
->cipher
= CIPHER_DES
;
259 else if (!strcmp(cipher
, "aes"))
260 cfg
->cipher
= CIPHER_AES
;
262 cfg
->cipher
= CIPHER_3DES
;
264 gppi(sesskey
, "SshProt", 1, &cfg
->sshprot
);
265 gppi(sesskey
, "BuggyMAC", 0, &cfg
->buggymac
);
266 gppi(sesskey
, "AuthTIS", 0, &cfg
->try_tis_auth
);
267 gpps(sesskey
, "PublicKeyFile", "", cfg
->keyfile
, sizeof(cfg
->keyfile
));
268 gpps(sesskey
, "RemoteCommand", "", cfg
->remote_cmd
,
269 sizeof(cfg
->remote_cmd
));
270 gppi(sesskey
, "RFCEnviron", 0, &cfg
->rfc_environ
);
271 gppi(sesskey
, "PassiveTelnet", 0, &cfg
->passive_telnet
);
272 gppi(sesskey
, "BackspaceIsDelete", 1, &cfg
->bksp_is_delete
);
273 gppi(sesskey
, "RXVTHomeEnd", 0, &cfg
->rxvt_homeend
);
274 gppi(sesskey
, "LinuxFunctionKeys", 0, &cfg
->funky_type
);
275 gppi(sesskey
, "NoApplicationKeys", 0, &cfg
->no_applic_k
);
276 gppi(sesskey
, "NoApplicationCursors", 0, &cfg
->no_applic_c
);
277 gppi(sesskey
, "ApplicationCursorKeys", 0, &cfg
->app_cursor
);
278 gppi(sesskey
, "ApplicationKeypad", 0, &cfg
->app_keypad
);
279 gppi(sesskey
, "NetHackKeypad", 0, &cfg
->nethack_keypad
);
280 gppi(sesskey
, "AltF4", 1, &cfg
->alt_f4
);
281 gppi(sesskey
, "AltSpace", 0, &cfg
->alt_space
);
282 gppi(sesskey
, "AltOnly", 0, &cfg
->alt_only
);
283 gppi(sesskey
, "ComposeKey", 0, &cfg
->compose_key
);
284 gppi(sesskey
, "CtrlAltKeys", 1, &cfg
->ctrlaltkeys
);
285 gppi(sesskey
, "TelnetKey", 0, &cfg
->telnet_keyboard
);
286 gppi(sesskey
, "LocalEcho", LD_BACKEND
, &cfg
->localecho
);
287 gppi(sesskey
, "LocalEdit", LD_BACKEND
, &cfg
->localedit
);
288 gpps(sesskey
, "Answerback", "PuTTY", cfg
->answerback
,
289 sizeof(cfg
->answerback
));
290 gppi(sesskey
, "AlwaysOnTop", 0, &cfg
->alwaysontop
);
291 gppi(sesskey
, "HideMousePtr", 0, &cfg
->hide_mouseptr
);
292 gppi(sesskey
, "SunkenEdge", 0, &cfg
->sunken_edge
);
293 gppi(sesskey
, "CurType", 0, &cfg
->cursor_type
);
294 gppi(sesskey
, "BlinkCur", 0, &cfg
->blink_cur
);
295 /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */
296 gppi(sesskey
, "Beep", 1, &i
); cfg
->beep
= i
;
297 gppi(sesskey
, "BeepInd", 0, &i
); cfg
->beep_ind
= i
;
298 gpps(sesskey
, "BellWaveFile", "", cfg
->bell_wavefile
,
299 sizeof(cfg
->bell_wavefile
));
300 gppi(sesskey
, "BellOverload", 1, &cfg
->bellovl
);
301 gppi(sesskey
, "BellOverloadN", 5, &cfg
->bellovl_n
);
302 gppi(sesskey
, "BellOverloadT", 2000, &cfg
->bellovl_t
);
303 gppi(sesskey
, "BellOverloadS", 5000, &cfg
->bellovl_s
);
304 gppi(sesskey
, "ScrollbackLines", 200, &cfg
->savelines
);
305 gppi(sesskey
, "DECOriginMode", 0, &cfg
->dec_om
);
306 gppi(sesskey
, "AutoWrapMode", 1, &cfg
->wrap_mode
);
307 gppi(sesskey
, "LFImpliesCR", 0, &cfg
->lfhascr
);
308 gppi(sesskey
, "WinNameAlways", 0, &cfg
->win_name_always
);
309 gpps(sesskey
, "WinTitle", "", cfg
->wintitle
, sizeof(cfg
->wintitle
));
310 gppi(sesskey
, "TermWidth", 80, &cfg
->width
);
311 gppi(sesskey
, "TermHeight", 24, &cfg
->height
);
312 gpps(sesskey
, "Font", "Courier", cfg
->font
, sizeof(cfg
->font
));
313 gppi(sesskey
, "FontIsBold", 0, &cfg
->fontisbold
);
314 gppi(sesskey
, "FontCharSet", ANSI_CHARSET
, &cfg
->fontcharset
);
315 gppi(sesskey
, "FontHeight", 10, &cfg
->fontheight
);
316 if (cfg
->fontheight
< 0) {
318 HDC hdc
= GetDC(NULL
);
319 int logpix
= GetDeviceCaps(hdc
, LOGPIXELSY
);
320 ReleaseDC(NULL
, hdc
);
322 oldh
= -cfg
->fontheight
;
323 newh
= MulDiv(oldh
, 72, logpix
) + 1;
324 if (MulDiv(newh
, logpix
, 72) > oldh
)
326 cfg
->fontheight
= newh
;
328 gppi(sesskey
, "FontVTMode", VT_OEMANSI
, (int *) &cfg
->vtmode
);
329 gppi(sesskey
, "TryPalette", 0, &cfg
->try_palette
);
330 gppi(sesskey
, "BoldAsColour", 1, &cfg
->bold_colour
);
331 for (i
= 0; i
< 22; i
++) {
332 static char *defaults
[] = {
333 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
334 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
335 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
336 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
337 "85,255,255", "187,187,187", "255,255,255"
339 char buf
[20], buf2
[30];
341 sprintf(buf
, "Colour%d", i
);
342 gpps(sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
343 if (sscanf(buf2
, "%d,%d,%d", &c0
, &c1
, &c2
) == 3) {
344 cfg
->colours
[i
][0] = c0
;
345 cfg
->colours
[i
][1] = c1
;
346 cfg
->colours
[i
][2] = c2
;
349 gppi(sesskey
, "RawCNP", 0, &cfg
->rawcnp
);
350 gppi(sesskey
, "MouseIsXterm", 0, &cfg
->mouse_is_xterm
);
351 for (i
= 0; i
< 256; i
+= 32) {
352 static char *defaults
[] = {
353 "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",
354 "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",
355 "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",
356 "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",
357 "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",
358 "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",
359 "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",
360 "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"
362 char buf
[20], buf2
[256], *p
;
364 sprintf(buf
, "Wordness%d", i
);
365 gpps(sesskey
, buf
, defaults
[i
/ 32], buf2
, sizeof(buf2
));
367 for (j
= i
; j
< i
+ 32; j
++) {
369 while (*p
&& *p
!= ',')
373 cfg
->wordness
[j
] = atoi(q
);
376 gpps(sesskey
, "LineCodePage", "ISO-8859-1:1987", cfg
->line_codepage
,
377 sizeof(cfg
->line_codepage
));
378 gppi(sesskey
, "ScrollBar", 1, &cfg
->scrollbar
);
379 gppi(sesskey
, "ScrollOnKey", 0, &cfg
->scroll_on_key
);
380 gppi(sesskey
, "ScrollOnDisp", 1, &cfg
->scroll_on_disp
);
381 gppi(sesskey
, "LockSize", 0, &cfg
->locksize
);
382 gppi(sesskey
, "BCE", 0, &cfg
->bce
);
383 gppi(sesskey
, "BlinkText", 0, &cfg
->blinktext
);
384 gppi(sesskey
, "X11Forward", 0, &cfg
->x11_forward
);
385 gpps(sesskey
, "X11Display", "localhost:0", cfg
->x11_display
,
386 sizeof(cfg
->x11_display
));
388 gppi(sesskey
, "LocalPortAcceptAll", 0, &cfg
->lport_acceptall
);
390 char buf
[2 * sizeof(cfg
->portfwd
)], *p
, *q
;
391 gpps(sesskey
, "PortForwardings", "", buf
, sizeof(buf
));
395 while (*p
&& *p
!= ',') {
410 close_settings_r(sesskey
);
413 void do_defaults(char *session
, Config
* cfg
)
416 load_settings(session
, TRUE
, cfg
);
418 load_settings("Default Settings", FALSE
, cfg
);
421 static int sessioncmp(const void *av
, const void *bv
)
423 const char *a
= *(const char *const *) av
;
424 const char *b
= *(const char *const *) bv
;
427 * Alphabetical order, except that "Default Settings" is a
428 * special case and comes first.
430 if (!strcmp(a
, "Default Settings"))
431 return -1; /* a comes first */
432 if (!strcmp(b
, "Default Settings"))
433 return +1; /* b comes first */
434 return strcmp(a
, b
); /* otherwise, compare normally */
437 void get_sesslist(int allocate
)
439 static char otherbuf
[2048];
441 int buflen
, bufsize
, i
;
447 if ((handle
= enum_settings_start()) == NULL
)
450 buflen
= bufsize
= 0;
453 ret
= enum_settings_next(handle
, otherbuf
, sizeof(otherbuf
));
455 int len
= strlen(otherbuf
) + 1;
456 if (bufsize
< buflen
+ len
) {
457 bufsize
= buflen
+ len
+ 2048;
458 buffer
= srealloc(buffer
, bufsize
);
460 strcpy(buffer
+ buflen
, otherbuf
);
461 buflen
+= strlen(buffer
+ buflen
) + 1;
464 enum_settings_finish(handle
);
465 buffer
= srealloc(buffer
, buflen
+ 1);
466 buffer
[buflen
] = '\0';
469 * Now set up the list of sessions. Note that "Default
470 * Settings" must always be claimed to exist, even if it
475 nsessions
= 1; /* "Default Settings" counts as one */
477 if (strcmp(p
, "Default Settings"))
484 sessions
= smalloc((nsessions
+ 1) * sizeof(char *));
485 sessions
[0] = "Default Settings";
489 if (strcmp(p
, "Default Settings"))
496 qsort(sessions
, i
, sizeof(char *), sessioncmp
);