Fixed issue #3848: "Git Sync..." > "Compare tags" does not properly clear state from...
[TortoiseGit.git] / src / TortoisePlink / PUTTY.H
blobbef5fd49b0f8c8695ad677d88ef399498b6e5574
1 #ifndef PUTTY_PUTTY_H\r
2 #define PUTTY_PUTTY_H\r
3 \r
4 #include <stddef.h>                    /* for wchar_t */\r
5 #include <limits.h>                    /* for INT_MAX */\r
6 \r
7 #include "defs.h"\r
8 #include "puttyps.h"\r
9 #include "network.h"\r
10 #include "misc.h"\r
11 #include "marshal.h"\r
13 /*\r
14  * We express various time intervals in unsigned long minutes, but may need to\r
15  * clip some values so that the resulting number of ticks does not overflow an\r
16  * integer value.\r
17  */\r
18 #define MAX_TICK_MINS   (INT_MAX / (60 * TICKSPERSEC))\r
20 /*\r
21  * Fingerprints of the current and previous PGP master keys, to\r
22  * establish a trust path between an executable and other files.\r
23  */\r
24 #define PGP_MASTER_KEY_YEAR "2018"\r
25 #define PGP_MASTER_KEY_DETAILS "RSA, 4096-bit"\r
26 #define PGP_MASTER_KEY_FP                                       \\r
27     "24E1 B1C5 75EA 3C9F F752  A922 76BC 7FE4 EBFD 2D9E"\r
28 #define PGP_PREV_MASTER_KEY_YEAR "2015"\r
29 #define PGP_PREV_MASTER_KEY_DETAILS "RSA, 4096-bit"\r
30 #define PGP_PREV_MASTER_KEY_FP                                  \\r
31     "440D E3B5 B7A1 CA85 B3CC  1718 AB58 5DC6 0467 6F7C"\r
33 /*\r
34  * Definitions of three separate indexing schemes for colour palette\r
35  * entries.\r
36  *\r
37  * Why three? Because history, sorry.\r
38  *\r
39  * Two of the colour indexings are used in escape sequences. The\r
40  * Linux-console style OSC P sequences for setting the palette use an\r
41  * indexing in which the eight standard ANSI SGR colours come first,\r
42  * then their bold versions, and then six extra colours for default\r
43  * fg/bg and the terminal cursor. And the xterm OSC 4 sequences for\r
44  * querying the palette use a related indexing in which the six extra\r
45  * colours are pushed up to indices 256 and onwards, with the previous\r
46  * 16 being the first part of the xterm 256-colour space, and 240\r
47  * additional terminal-accessible colours inserted in the middle.\r
48  *\r
49  * The third indexing is the order that the colours appear in the\r
50  * PuTTY configuration panel, and also the order in which they're\r
51  * described in the saved session files. This order specifies the same\r
52  * set of colours as the OSC P encoding, but in a different order,\r
53  * with the default fg/bg colours (which users are most likely to want\r
54  * to reconfigure) at the start, and the ANSI SGR colours coming\r
55  * later.\r
56  *\r
57  * So all three indices really are needed, because all three appear in\r
58  * protocols or file formats outside the PuTTY binary. (Changing the\r
59  * saved-session encoding would have a backwards-compatibility impact;\r
60  * also, if we ever do, it would be better to replace the numeric\r
61  * indices with descriptive keywords.)\r
62  *\r
63  * Since the OSC 4 encoding contains the full set of colours used in\r
64  * the terminal display, that's the encoding used by front ends to\r
65  * store any actual data associated with their palette entries. So the\r
66  * TermWin palette_set and palette_get_overrides methods use that\r
67  * encoding, and so does the bitwise encoding of attribute words used\r
68  * in terminal redraw operations.\r
69  *\r
70  * The Conf encoding, of course, is used by config.c and settings.c.\r
71  *\r
72  * The aim is that those two sections of the code should never need to\r
73  * come directly into contact, and the only module that should have to\r
74  * deal directly with the mapping between these colour encodings - or\r
75  * to deal _at all_ with the intermediate OSC P encoding - is\r
76  * terminal.c itself.\r
77  */\r
79 #define CONF_NCOLOURS 22               /* 16 + 6 special ones */\r
80 #define OSCP_NCOLOURS 22               /* same as CONF, but different order */\r
81 #define OSC4_NCOLOURS 262              /* 256 + the same 6 special ones */\r
83 /* The list macro for the conf colours also gives the textual names\r
84  * used in the GUI configurer */\r
85 #define CONF_COLOUR_LIST(X)                     \\r
86     X(fg, "Default Foreground")                 \\r
87     X(fg_bold, "Default Bold Foreground")       \\r
88     X(bg, "Default Background")                 \\r
89     X(bg_bold, "Default Bold Background")       \\r
90     X(cursor_fg, "Cursor Text")                 \\r
91     X(cursor_bg, "Cursor Colour")               \\r
92     X(black, "ANSI Black")                      \\r
93     X(black_bold, "ANSI Black Bold")            \\r
94     X(red, "ANSI Red")                          \\r
95     X(red_bold, "ANSI Red Bold")                \\r
96     X(green, "ANSI Green")                      \\r
97     X(green_bold, "ANSI Green Bold")            \\r
98     X(yellow, "ANSI Yellow")                    \\r
99     X(yellow_bold, "ANSI Yellow Bold")          \\r
100     X(blue, "ANSI Blue")                        \\r
101     X(blue_bold, "ANSI Blue Bold")              \\r
102     X(magenta, "ANSI Magenta")                  \\r
103     X(magenta_bold, "ANSI Magenta Bold")        \\r
104     X(cyan, "ANSI Cyan")                        \\r
105     X(cyan_bold, "ANSI Cyan Bold")              \\r
106     X(white, "ANSI White")                      \\r
107     X(white_bold, "ANSI White Bold")            \\r
108     /* end of list */\r
110 #define OSCP_COLOUR_LIST(X)                     \\r
111     X(black)                                    \\r
112     X(red)                                      \\r
113     X(green)                                    \\r
114     X(yellow)                                   \\r
115     X(blue)                                     \\r
116     X(magenta)                                  \\r
117     X(cyan)                                     \\r
118     X(white)                                    \\r
119     X(black_bold)                               \\r
120     X(red_bold)                                 \\r
121     X(green_bold)                               \\r
122     X(yellow_bold)                              \\r
123     X(blue_bold)                                \\r
124     X(magenta_bold)                             \\r
125     X(cyan_bold)                                \\r
126     X(white_bold)                               \\r
127     /*\r
128      * In the OSC 4 indexing, this is where the extra 240 colours go.\r
129      * They consist of:\r
130      *\r
131      *  - 216 colours forming a 6x6x6 cube, with R the most\r
132      *    significant colour and G the least. In other words, these\r
133      *    occupy the space of indices 16 <= i < 232, with each\r
134      *    individual colour found as i = 16 + 36*r + 6*g + b, for all\r
135      *    0 <= r,g,b <= 5.\r
136      *\r
137      *  - The remaining indices, 232 <= i < 256, consist of a uniform\r
138      *    series of grey shades running between black and white (but\r
139      *    not including either, since actual black and white are\r
140      *    already provided in the previous colour cube).\r
141      *\r
142      * After that, we have the remaining 6 special colours:\r
143      */                                         \\r
144     X(fg)                                       \\r
145     X(fg_bold)                                  \\r
146     X(bg)                                       \\r
147     X(bg_bold)                                  \\r
148     X(cursor_fg)                                \\r
149     X(cursor_bg)                                \\r
150     /* end of list */\r
152 /* Enumerations of the colour lists. These are available everywhere in\r
153  * the code. The OSC P encoding shouldn't be used outside terminal.c,\r
154  * but the easiest way to define the OSC 4 enum is to have the OSC P\r
155  * one available to compute with. */\r
156 enum {\r
157     #define ENUM_DECL(id,name) CONF_COLOUR_##id,\r
158     CONF_COLOUR_LIST(ENUM_DECL)\r
159     #undef ENUM_DECL\r
160 };\r
161 enum {\r
162     #define ENUM_DECL(id) OSCP_COLOUR_##id,\r
163     OSCP_COLOUR_LIST(ENUM_DECL)\r
164     #undef ENUM_DECL\r
165 };\r
166 enum {\r
167     #define ENUM_DECL(id) OSC4_COLOUR_##id = \\r
168         OSCP_COLOUR_##id + (OSCP_COLOUR_##id >= 16 ? 240 : 0),\r
169     OSCP_COLOUR_LIST(ENUM_DECL)\r
170     #undef ENUM_DECL\r
171 };\r
173 /* Mapping tables defined in terminal.c */\r
174 extern const int colour_indices_conf_to_oscp[CONF_NCOLOURS];\r
175 extern const int colour_indices_conf_to_osc4[CONF_NCOLOURS];\r
176 extern const int colour_indices_oscp_to_osc4[OSCP_NCOLOURS];\r
178 /* Three attribute types:\r
179  * The ATTRs (normal attributes) are stored with the characters in\r
180  * the main display arrays\r
181  *\r
182  * The TATTRs (temporary attributes) are generated on the fly, they\r
183  * can overlap with characters but not with normal attributes.\r
184  *\r
185  * The LATTRs (line attributes) are an entirely disjoint space of\r
186  * flags.\r
187  *\r
188  * The DATTRs (display attributes) are internal to terminal.c (but\r
189  * defined here because their values have to match the others\r
190  * here); they reuse the TATTR_* space but are always masked off\r
191  * before sending to the front end.\r
192  *\r
193  * ATTR_INVALID is an illegal colour combination.\r
194  */\r
196 #define TATTR_ACTCURS       0x40000000UL      /* active cursor (block) */\r
197 #define TATTR_PASCURS       0x20000000UL      /* passive cursor (box) */\r
198 #define TATTR_RIGHTCURS     0x10000000UL      /* cursor-on-RHS */\r
199 #define TATTR_COMBINING     0x80000000UL      /* combining characters */\r
201 #define DATTR_STARTRUN      0x80000000UL   /* start of redraw run */\r
203 #define TDATTR_MASK         0xF0000000UL\r
204 #define TATTR_MASK (TDATTR_MASK)\r
205 #define DATTR_MASK (TDATTR_MASK)\r
207 #define LATTR_NORM   0x00000000UL\r
208 #define LATTR_WIDE   0x00000001UL\r
209 #define LATTR_TOP    0x00000002UL\r
210 #define LATTR_BOT    0x00000003UL\r
211 #define LATTR_MODE   0x00000003UL\r
212 #define LATTR_WRAPPED 0x00000010UL     /* this line wraps to next */\r
213 #define LATTR_WRAPPED2 0x00000020UL    /* with WRAPPED: CJK wide character\r
214                                           wrapped to next line, so last\r
215                                           single-width cell is empty */\r
217 #define ATTR_INVALID 0x03FFFFU\r
219 /* Use the DC00 page for direct to font. */\r
220 #define CSET_OEMCP   0x0000DC00UL      /* OEM Codepage DTF */\r
221 #define CSET_ACP     0x0000DD00UL      /* Ansi Codepage DTF */\r
223 /* These are internal use overlapping with the UTF-16 surrogates */\r
224 #define CSET_ASCII   0x0000D800UL      /* normal ASCII charset ESC ( B */\r
225 #define CSET_LINEDRW 0x0000D900UL      /* line drawing charset ESC ( 0 */\r
226 #define CSET_SCOACS  0x0000DA00UL      /* SCO Alternate charset */\r
227 #define CSET_GBCHR   0x0000DB00UL      /* UK variant   charset ESC ( A */\r
228 #define CSET_MASK    0xFFFFFF00UL      /* Character set mask */\r
230 #define DIRECT_CHAR(c) ((c&0xFFFFFC00)==0xD800)\r
231 #define DIRECT_FONT(c) ((c&0xFFFFFE00)==0xDC00)\r
233 #define UCSERR       (CSET_LINEDRW|'a') /* UCS Format error character. */\r
234 /*\r
235  * UCSWIDE is a special value used in the terminal data to signify\r
236  * the character cell containing the right-hand half of a CJK wide\r
237  * character. We use 0xDFFF because it's part of the surrogate\r
238  * range and hence won't be used for anything else (it's impossible\r
239  * to input it via UTF-8 because our UTF-8 decoder correctly\r
240  * rejects surrogates).\r
241  */\r
242 #define UCSWIDE      0xDFFF\r
244 #define ATTR_NARROW  0x0800000U\r
245 #define ATTR_WIDE    0x0400000U\r
246 #define ATTR_BOLD    0x0040000U\r
247 #define ATTR_UNDER   0x0080000U\r
248 #define ATTR_REVERSE 0x0100000U\r
249 #define ATTR_BLINK   0x0200000U\r
250 #define ATTR_FGMASK  0x00001FFU /* stores a colour in OSC 4 indexing */\r
251 #define ATTR_BGMASK  0x003FE00U /* stores a colour in OSC 4 indexing */\r
252 #define ATTR_COLOURS 0x003FFFFU\r
253 #define ATTR_DIM     0x1000000U\r
254 #define ATTR_STRIKE  0x2000000U\r
255 #define ATTR_FGSHIFT 0\r
256 #define ATTR_BGSHIFT 9\r
258 #define ATTR_DEFFG   (OSC4_COLOUR_fg << ATTR_FGSHIFT)\r
259 #define ATTR_DEFBG   (OSC4_COLOUR_bg << ATTR_BGSHIFT)\r
260 #define ATTR_DEFAULT (ATTR_DEFFG | ATTR_DEFBG)\r
262 struct sesslist {\r
263     int nsessions;\r
264     const char **sessions;\r
265     char *buffer;                      /* so memory can be freed later */\r
266 };\r
268 struct unicode_data {\r
269     char **uni_tbl;\r
270     bool dbcs_screenfont;\r
271     int font_codepage;\r
272     int line_codepage;\r
273     wchar_t unitab_scoacs[256];\r
274     wchar_t unitab_line[256];\r
275     wchar_t unitab_font[256];\r
276     wchar_t unitab_xterm[256];\r
277     wchar_t unitab_oemcp[256];\r
278     unsigned char unitab_ctrl[256];\r
279 };\r
281 #define LGXF_OVR  1                    /* existing logfile overwrite */\r
282 #define LGXF_APN  0                    /* existing logfile append */\r
283 #define LGXF_ASK -1                    /* existing logfile ask */\r
284 #define LGTYP_NONE  0                  /* logmode: no logging */\r
285 #define LGTYP_ASCII 1                  /* logmode: pure ascii */\r
286 #define LGTYP_DEBUG 2                  /* logmode: all chars of traffic */\r
287 #define LGTYP_PACKETS 3                /* logmode: SSH data packets */\r
288 #define LGTYP_SSHRAW 4                 /* logmode: SSH raw data */\r
290 /*\r
291  * Enumeration of 'special commands' that can be sent during a\r
292  * session, separately from the byte stream of ordinary session data.\r
293  */\r
294 typedef enum {\r
295     /*\r
296      * Commands that are generally useful in multiple backends.\r
297      */\r
298     SS_BRK,    /* serial-line break */\r
299     SS_EOF,    /* end-of-file on session input */\r
300     SS_NOP,    /* transmit data with no effect */\r
301     SS_PING,   /* try to keep the session alive (probably, but not\r
302                 * necessarily, implemented as SS_NOP) */\r
304     /*\r
305      * Commands specific to Telnet.\r
306      */\r
307     SS_AYT,    /* Are You There */\r
308     SS_SYNCH,  /* Synch */\r
309     SS_EC,     /* Erase Character */\r
310     SS_EL,     /* Erase Line */\r
311     SS_GA,     /* Go Ahead */\r
312     SS_ABORT,  /* Abort Process */\r
313     SS_AO,     /* Abort Output */\r
314     SS_IP,     /* Interrupt Process */\r
315     SS_SUSP,   /* Suspend Process */\r
316     SS_EOR,    /* End Of Record */\r
317     SS_EOL,    /* Telnet end-of-line sequence (CRLF, as opposed to CR\r
318                 * NUL that escapes a literal CR) */\r
320     /*\r
321      * Commands specific to SSH.\r
322      */\r
323     SS_REKEY,  /* trigger an immediate repeat key exchange */\r
324     SS_XCERT,  /* cross-certify another host key ('arg' indicates which) */\r
326     /*\r
327      * Send a POSIX-style signal. (Useful in SSH and also pterm.)\r
328      *\r
329      * We use the master list in sshsignals.h to define these enum\r
330      * values, which will come out looking like names of the form\r
331      * SS_SIGABRT, SS_SIGINT etc.\r
332      */\r
333     #define SIGNAL_MAIN(name, text) SS_SIG ## name,\r
334     #define SIGNAL_SUB(name) SS_SIG ## name,\r
335     #include "sshsignals.h"\r
336     #undef SIGNAL_MAIN\r
337     #undef SIGNAL_SUB\r
339     /*\r
340      * These aren't really special commands, but they appear in the\r
341      * enumeration because the list returned from\r
342      * backend_get_specials() will use them to specify the structure\r
343      * of the GUI specials menu.\r
344      */\r
345     SS_SEP,         /* Separator */\r
346     SS_SUBMENU,     /* Start a new submenu with specified name */\r
347     SS_EXITMENU,    /* Exit current submenu, or end of entire specials list */\r
348 } SessionSpecialCode;\r
350 /*\r
351  * The structure type returned from backend_get_specials.\r
352  */\r
353 struct SessionSpecial {\r
354     const char *name;\r
355     SessionSpecialCode code;\r
356     int arg;\r
357 };\r
359 /* Needed by both sshchan.h and sshppl.h */\r
360 typedef void (*add_special_fn_t)(\r
361     void *ctx, const char *text, SessionSpecialCode code, int arg);\r
363 typedef enum {\r
364     MBT_NOTHING,\r
365     MBT_LEFT, MBT_MIDDLE, MBT_RIGHT,   /* `raw' button designations */\r
366     MBT_SELECT, MBT_EXTEND, MBT_PASTE, /* `cooked' button designations */\r
367     MBT_WHEEL_UP, MBT_WHEEL_DOWN       /* mouse wheel */\r
368 } Mouse_Button;\r
370 typedef enum {\r
371     MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE\r
372 } Mouse_Action;\r
374 /* Keyboard modifiers -- keys the user is actually holding down */\r
376 #define PKM_SHIFT       0x01\r
377 #define PKM_CONTROL     0x02\r
378 #define PKM_META        0x04\r
379 #define PKM_ALT         0x08\r
381 /* Keyboard flags that aren't really modifiers */\r
382 #define PKF_CAPSLOCK    0x10\r
383 #define PKF_NUMLOCK     0x20\r
384 #define PKF_REPEAT      0x40\r
386 /* Stand-alone keysyms for function keys */\r
388 typedef enum {\r
389     PK_NULL,            /* No symbol for this key */\r
390     /* Main keypad keys */\r
391     PK_ESCAPE, PK_TAB, PK_BACKSPACE, PK_RETURN, PK_COMPOSE,\r
392     /* Editing keys */\r
393     PK_HOME, PK_INSERT, PK_DELETE, PK_END, PK_PAGEUP, PK_PAGEDOWN,\r
394     /* Cursor keys */\r
395     PK_UP, PK_DOWN, PK_RIGHT, PK_LEFT, PK_REST,\r
396     /* Numeric keypad */                        /* Real one looks like: */\r
397     PK_PF1, PK_PF2, PK_PF3, PK_PF4,             /* PF1 PF2 PF3 PF4 */\r
398     PK_KPCOMMA, PK_KPMINUS, PK_KPDECIMAL,       /*  7   8   9   -  */\r
399     PK_KP0, PK_KP1, PK_KP2, PK_KP3, PK_KP4,     /*  4   5   6   ,  */\r
400     PK_KP5, PK_KP6, PK_KP7, PK_KP8, PK_KP9,     /*  1   2   3  en- */\r
401     PK_KPBIGPLUS, PK_KPENTER,                   /*    0     .  ter */\r
402     /* Top row */\r
403     PK_F1,  PK_F2,  PK_F3,  PK_F4,  PK_F5,\r
404     PK_F6,  PK_F7,  PK_F8,  PK_F9,  PK_F10,\r
405     PK_F11, PK_F12, PK_F13, PK_F14, PK_F15,\r
406     PK_F16, PK_F17, PK_F18, PK_F19, PK_F20,\r
407     PK_PAUSE\r
408 } Key_Sym;\r
410 #define PK_ISEDITING(k) ((k) >= PK_HOME && (k) <= PK_PAGEDOWN)\r
411 #define PK_ISCURSOR(k)  ((k) >= PK_UP && (k) <= PK_REST)\r
412 #define PK_ISKEYPAD(k)  ((k) >= PK_PF1 && (k) <= PK_KPENTER)\r
413 #define PK_ISFKEY(k)    ((k) >= PK_F1 && (k) <= PK_F20)\r
415 enum {\r
416     VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN, VT_UNICODE\r
417 };\r
419 enum {\r
420     /*\r
421      * SSH-2 key exchange algorithms\r
422      */\r
423     KEX_WARN,\r
424     KEX_DHGROUP1,\r
425     KEX_DHGROUP14,\r
426     KEX_DHGEX,\r
427     KEX_RSA,\r
428     KEX_ECDH,\r
429     KEX_MAX\r
430 };\r
432 enum {\r
433     /*\r
434      * SSH-2 host key algorithms\r
435      */\r
436     HK_WARN,\r
437     HK_RSA,\r
438     HK_DSA,\r
439     HK_ECDSA,\r
440     HK_ED25519,\r
441     HK_ED448,\r
442     HK_MAX\r
443 };\r
445 enum {\r
446     /*\r
447      * SSH ciphers (both SSH-1 and SSH-2)\r
448      */\r
449     CIPHER_WARN,                       /* pseudo 'cipher' */\r
450     CIPHER_3DES,\r
451     CIPHER_BLOWFISH,\r
452     CIPHER_AES,                        /* (SSH-2 only) */\r
453     CIPHER_DES,\r
454     CIPHER_ARCFOUR,\r
455     CIPHER_CHACHA20,\r
456     CIPHER_MAX                         /* no. ciphers (inc warn) */\r
457 };\r
459 enum TriState {\r
460     /*\r
461      * Several different bits of the PuTTY configuration seem to be\r
462      * three-way settings whose values are `always yes', `always\r
463      * no', and `decide by some more complex automated means'. This\r
464      * is true of line discipline options (local echo and line\r
465      * editing), proxy DNS, proxy terminal logging, Close On Exit, and\r
466      * SSH server bug workarounds. Accordingly I supply a single enum\r
467      * here to deal with them all.\r
468      */\r
469     FORCE_ON, FORCE_OFF, AUTO\r
470 };\r
472 enum {\r
473     /*\r
474      * Proxy types.\r
475      */\r
476     PROXY_NONE, PROXY_SOCKS4, PROXY_SOCKS5,\r
477     PROXY_HTTP, PROXY_TELNET, PROXY_CMD, PROXY_FUZZ\r
478 };\r
480 enum {\r
481     /*\r
482      * Line discipline options which the backend might try to control.\r
483      */\r
484     LD_EDIT,                           /* local line editing */\r
485     LD_ECHO,                           /* local echo */\r
486     LD_N_OPTIONS\r
487 };\r
489 enum {\r
490     /* Actions on remote window title query */\r
491     TITLE_NONE, TITLE_EMPTY, TITLE_REAL\r
492 };\r
494 enum {\r
495     /* SUPDUP character set options */\r
496     SUPDUP_CHARSET_ASCII, SUPDUP_CHARSET_ITS, SUPDUP_CHARSET_WAITS\r
497 };\r
499 enum {\r
500     /* Protocol back ends. (CONF_protocol) */\r
501     PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH, PROT_SSHCONN,\r
502     /* PROT_SERIAL is supported on a subset of platforms, but it doesn't\r
503      * hurt to define it globally. */\r
504     PROT_SERIAL,\r
505     /* PROT_SUPDUP is the historical RFC 734 protocol. */\r
506     PROT_SUPDUP,\r
507     PROTOCOL_LIMIT, /* upper bound on number of protocols */\r
508 };\r
510 enum {\r
511     /* Bell settings (CONF_beep) */\r
512     BELL_DISABLED, BELL_DEFAULT, BELL_VISUAL, BELL_WAVEFILE, BELL_PCSPEAKER\r
513 };\r
515 enum {\r
516     /* Taskbar flashing indication on bell (CONF_beep_ind) */\r
517     B_IND_DISABLED, B_IND_FLASH, B_IND_STEADY\r
518 };\r
520 enum {\r
521     /* Resize actions (CONF_resize_action) */\r
522     RESIZE_TERM, RESIZE_DISABLED, RESIZE_FONT, RESIZE_EITHER\r
523 };\r
525 enum {\r
526     /* Function key types (CONF_funky_type) */\r
527     FUNKY_TILDE,\r
528     FUNKY_LINUX,\r
529     FUNKY_XTERM,\r
530     FUNKY_VT400,\r
531     FUNKY_VT100P,\r
532     FUNKY_SCO\r
533 };\r
535 enum {\r
536     FQ_DEFAULT, FQ_ANTIALIASED, FQ_NONANTIALIASED, FQ_CLEARTYPE\r
537 };\r
539 enum {\r
540     SER_PAR_NONE, SER_PAR_ODD, SER_PAR_EVEN, SER_PAR_MARK, SER_PAR_SPACE\r
541 };\r
543 enum {\r
544     SER_FLOW_NONE, SER_FLOW_XONXOFF, SER_FLOW_RTSCTS, SER_FLOW_DSRDTR\r
545 };\r
547 /*\r
548  * Tables of string <-> enum value mappings used in settings.c.\r
549  * Defined here so that backends can export their GSS library tables\r
550  * to the cross-platform settings code.\r
551  */\r
552 struct keyvalwhere {\r
553     /*\r
554      * Two fields which define a string and enum value to be\r
555      * equivalent to each other.\r
556      */\r
557     const char *s;\r
558     int v;\r
560     /*\r
561      * The next pair of fields are used by gprefs() in settings.c to\r
562      * arrange that when it reads a list of strings representing a\r
563      * preference list and translates it into the corresponding list\r
564      * of integers, strings not appearing in the list are entered in a\r
565      * configurable position rather than uniformly at the end.\r
566      */\r
568     /*\r
569      * 'vrel' indicates which other value in the list to place this\r
570      * element relative to. It should be a value that has occurred in\r
571      * a 'v' field of some other element of the array, or -1 to\r
572      * indicate that we simply place relative to one or other end of\r
573      * the list.\r
574      *\r
575      * gprefs will try to process the elements in an order which makes\r
576      * this field work (i.e. so that the element referenced has been\r
577      * added before processing this one).\r
578      */\r
579     int vrel;\r
581     /*\r
582      * 'where' indicates whether to place the new value before or\r
583      * after the one referred to by vrel. -1 means before; +1 means\r
584      * after.\r
585      *\r
586      * When vrel is -1, this also implicitly indicates which end of\r
587      * the array to use. So vrel=-1, where=-1 means to place _before_\r
588      * some end of the list (hence, at the last element); vrel=-1,\r
589      * where=+1 means to place _after_ an end (hence, at the first).\r
590      */\r
591     int where;\r
592 };\r
594 #ifndef NO_GSSAPI\r
595 extern const int ngsslibs;\r
596 extern const char *const gsslibnames[]; /* for displaying in configuration */\r
597 extern const struct keyvalwhere gsslibkeywords[]; /* for settings.c */\r
598 #endif\r
600 extern const char *const ttymodes[];\r
602 enum {\r
603     /*\r
604      * Network address types. Used for specifying choice of IPv4/v6\r
605      * in config; also used in proxy.c to indicate whether a given\r
606      * host name has already been resolved or will be resolved at\r
607      * the proxy end.\r
608      */\r
609     ADDRTYPE_UNSPEC,\r
610     ADDRTYPE_IPV4,\r
611     ADDRTYPE_IPV6,\r
612     ADDRTYPE_LOCAL,    /* e.g. Unix domain socket, or Windows named pipe */\r
613     ADDRTYPE_NAME      /* SockAddr storing an unresolved host name */\r
614 };\r
616 /* Backend flags */\r
617 #define BACKEND_RESIZE_FORBIDDEN    0x01   /* Backend does not allow\r
618                                               resizing terminal */\r
619 #define BACKEND_NEEDS_TERMINAL      0x02   /* Backend must have terminal */\r
621 struct Backend {\r
622     const BackendVtable *vt;\r
623 };\r
624 struct BackendVtable {\r
625     char *(*init) (const BackendVtable *vt, Seat *seat,\r
626                    Backend **backend_out, LogContext *logctx, Conf *conf,\r
627                    const char *host, int port, char **realhost,\r
628                    bool nodelay, bool keepalive);\r
630     void (*free) (Backend *be);\r
631     /* Pass in a replacement configuration. */\r
632     void (*reconfig) (Backend *be, Conf *conf);\r
633     /* send() returns the current amount of buffered data. */\r
634     size_t (*send) (Backend *be, const char *buf, size_t len);\r
635     /* sendbuffer() does the same thing but without attempting a send */\r
636     size_t (*sendbuffer) (Backend *be);\r
637     void (*size) (Backend *be, int width, int height);\r
638     void (*special) (Backend *be, SessionSpecialCode code, int arg);\r
639     const SessionSpecial *(*get_specials) (Backend *be);\r
640     bool (*connected) (Backend *be);\r
641     int (*exitcode) (Backend *be);\r
642     /* If back->sendok() returns false, the backend doesn't currently\r
643      * want input data, so the frontend should avoid acquiring any if\r
644      * possible (passing back-pressure on to its sender). */\r
645     bool (*sendok) (Backend *be);\r
646     bool (*ldisc_option_state) (Backend *be, int);\r
647     void (*provide_ldisc) (Backend *be, Ldisc *ldisc);\r
648     /* Tells the back end that the front end  buffer is clearing. */\r
649     void (*unthrottle) (Backend *be, size_t bufsize);\r
650     int (*cfg_info) (Backend *be);\r
652     /* Only implemented in the SSH protocol: check whether a\r
653      * connection-sharing upstream exists for a given configuration. */\r
654     bool (*test_for_upstream)(const char *host, int port, Conf *conf);\r
655     /* Special-purpose function to return additional information to put\r
656      * in a "are you sure you want to close this session" dialog;\r
657      * return NULL if no such info, otherwise caller must free.\r
658      * Only implemented in the SSH protocol, to warn about downstream\r
659      * connections that would be lost if this one were terminated. */\r
660     char *(*close_warn_text)(Backend *be);\r
662     /* 'id' is a machine-readable name for the backend, used in\r
663      * saved-session storage. 'displayname' is a human-readable name\r
664      * for error messages. */\r
665     const char *id, *displayname;\r
667     int protocol;\r
668     int default_port;\r
669     unsigned flags;\r
671     /* Only relevant for the serial protocol: bit masks of which\r
672      * parity and flow control settings are supported. */\r
673     unsigned serial_parity_mask, serial_flow_mask;\r
674 };\r
676 static inline char *backend_init(\r
677     const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,\r
678     Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)\r
679 { return vt->init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka); }\r
680 static inline void backend_free(Backend *be)\r
681 { be->vt->free(be); }\r
682 static inline void backend_reconfig(Backend *be, Conf *conf)\r
683 { be->vt->reconfig(be, conf); }\r
684 static inline size_t backend_send(Backend *be, const char *buf, size_t len)\r
685 { return be->vt->send(be, buf, len); }\r
686 static inline size_t backend_sendbuffer(Backend *be)\r
687 { return be->vt->sendbuffer(be); }\r
688 static inline void backend_size(Backend *be, int width, int height)\r
689 { be->vt->size(be, width, height); }\r
690 static inline void backend_special(\r
691     Backend *be, SessionSpecialCode code, int arg)\r
692 { be->vt->special(be, code, arg); }\r
693 static inline const SessionSpecial *backend_get_specials(Backend *be)\r
694 { return be->vt->get_specials(be); }\r
695 static inline bool backend_connected(Backend *be)\r
696 { return be->vt->connected(be); }\r
697 static inline int backend_exitcode(Backend *be)\r
698 { return be->vt->exitcode(be); }\r
699 static inline bool backend_sendok(Backend *be)\r
700 { return be->vt->sendok(be); }\r
701 static inline bool backend_ldisc_option_state(Backend *be, int state)\r
702 { return be->vt->ldisc_option_state(be, state); }\r
703 static inline void backend_provide_ldisc(Backend *be, Ldisc *ldisc)\r
704 { be->vt->provide_ldisc(be, ldisc); }\r
705 static inline void backend_unthrottle(Backend *be, size_t bufsize)\r
706 { be->vt->unthrottle(be, bufsize); }\r
707 static inline int backend_cfg_info(Backend *be)\r
708 { return be->vt->cfg_info(be); }\r
710 extern const struct BackendVtable *const backends[];\r
711 /*\r
712  * In programs with a config UI, only the first few members of\r
713  * backends[] will be displayed at the top-level; the others will be\r
714  * relegated to a drop-down.\r
715  */\r
716 extern const size_t n_ui_backends;\r
718 /*\r
719  * Suggested default protocol provided by the backend link module.\r
720  * The application is free to ignore this.\r
721  */\r
722 extern const int be_default_protocol;\r
724 /*\r
725  * Name of this particular application, for use in the config box\r
726  * and other pieces of text.\r
727  */\r
728 extern const char *const appname;\r
730 /*\r
731  * Mechanism for getting text strings such as usernames and passwords\r
732  * from the front-end.\r
733  * The fields are mostly modelled after SSH's keyboard-interactive auth.\r
734  * FIXME We should probably mandate a character set/encoding (probably UTF-8).\r
735  *\r
736  * Since many of the pieces of text involved may be chosen by the server,\r
737  * the caller must take care to ensure that the server can't spoof locally-\r
738  * generated prompts such as key passphrase prompts. Some ground rules:\r
739  *  - If the front-end needs to truncate a string, it should lop off the\r
740  *    end.\r
741  *  - The front-end should filter out any dangerous characters and\r
742  *    generally not trust the strings. (But \n is required to behave\r
743  *    vaguely sensibly, at least in `instruction', and ideally in\r
744  *    `prompt[]' too.)\r
745  */\r
746 typedef struct {\r
747     char *prompt;\r
748     bool echo;\r
749     strbuf *result;\r
750 } prompt_t;\r
751 typedef struct {\r
752     /*\r
753      * Indicates whether the information entered is to be used locally\r
754      * (for instance a key passphrase prompt), or is destined for the wire.\r
755      * This is a hint only; the front-end is at liberty not to use this\r
756      * information (so the caller should ensure that the supplied text is\r
757      * sufficient).\r
758      */\r
759     bool to_server;\r
761     /*\r
762      * Indicates whether the prompts originated _at_ the server, so\r
763      * that the front end can display some kind of trust sigil that\r
764      * distinguishes (say) a legit private-key passphrase prompt from\r
765      * a fake one sent by a malicious server.\r
766      */\r
767     bool from_server;\r
769     char *name;         /* Short description, perhaps for dialog box title */\r
770     bool name_reqd;     /* Display of `name' required or optional? */\r
771     char *instruction;  /* Long description, maybe with embedded newlines */\r
772     bool instr_reqd;    /* Display of `instruction' required or optional? */\r
773     size_t n_prompts;   /* May be zero (in which case display the foregoing,\r
774                          * if any, and return success) */\r
775     size_t prompts_size; /* allocated storage capacity for prompts[] */\r
776     prompt_t **prompts;\r
777     void *data;         /* slot for housekeeping data, managed by\r
778                          * seat_get_userpass_input(); initially NULL */\r
779 } prompts_t;\r
780 prompts_t *new_prompts(void);\r
781 void add_prompt(prompts_t *p, char *promptstr, bool echo);\r
782 void prompt_set_result(prompt_t *pr, const char *newstr);\r
783 char *prompt_get_result(prompt_t *pr);\r
784 const char *prompt_get_result_ref(prompt_t *pr);\r
785 void free_prompts(prompts_t *p);\r
787 /*\r
788  * Data type definitions for true-colour terminal display.\r
789  * 'optionalrgb' describes a single RGB colour, which overrides the\r
790  * other colour settings if 'enabled' is nonzero, and is ignored\r
791  * otherwise. 'truecolour' contains a pair of those for foreground and\r
792  * background.\r
793  */\r
794 typedef struct optionalrgb {\r
795     bool enabled;\r
796     unsigned char r, g, b;\r
797 } optionalrgb;\r
798 extern const optionalrgb optionalrgb_none;\r
799 typedef struct truecolour {\r
800     optionalrgb fg, bg;\r
801 } truecolour;\r
802 #define optionalrgb_equal(r1,r2) (                              \\r
803         (r1).enabled==(r2).enabled &&                           \\r
804         (r1).r==(r2).r && (r1).g==(r2).g && (r1).b==(r2).b)\r
805 #define truecolour_equal(c1,c2) (               \\r
806         optionalrgb_equal((c1).fg, (c2).fg) &&  \\r
807         optionalrgb_equal((c1).bg, (c2).bg))\r
809 /*\r
810  * Enumeration of clipboards. We provide some standard ones cross-\r
811  * platform, and then permit each platform to extend this enumeration\r
812  * further by defining PLATFORM_CLIPBOARDS in its own header file.\r
813  *\r
814  * CLIP_NULL is a non-clipboard, writes to which are ignored and reads\r
815  * from which return no data.\r
816  *\r
817  * CLIP_LOCAL refers to a buffer within terminal.c, which\r
818  * unconditionally saves the last data selected in the terminal. In\r
819  * configurations where a system clipboard is not written\r
820  * automatically on selection but instead by an explicit UI action,\r
821  * this is where the code responding to that action can find the data\r
822  * to write to the clipboard in question.\r
823  */\r
824 #define CROSS_PLATFORM_CLIPBOARDS(X)                    \\r
825     X(CLIP_NULL, "null clipboard")                      \\r
826     X(CLIP_LOCAL, "last text selected in terminal")     \\r
827     /* end of list */\r
829 #define ALL_CLIPBOARDS(X)                       \\r
830     CROSS_PLATFORM_CLIPBOARDS(X)                \\r
831     PLATFORM_CLIPBOARDS(X)                      \\r
832     /* end of list */\r
834 #define CLIP_ID(id,name) id,\r
835 enum { ALL_CLIPBOARDS(CLIP_ID) N_CLIPBOARDS };\r
836 #undef CLIP_ID\r
838 /* Hint from backend to frontend about time-consuming operations, used\r
839  * by seat_set_busy_status. Initial state is assumed to be\r
840  * BUSY_NOT. */\r
841 typedef enum BusyStatus {\r
842     BUSY_NOT,       /* Not busy, all user interaction OK */\r
843     BUSY_WAITING,   /* Waiting for something; local event loops still\r
844                        running so some local interaction (e.g. menus)\r
845                        OK, but network stuff is suspended */\r
846     BUSY_CPU        /* Locally busy (e.g. crypto); user interaction\r
847                      * suspended */\r
848 } BusyStatus;\r
850 typedef enum SeatInteractionContext {\r
851     SIC_BANNER, SIC_KI_PROMPTS\r
852 } SeatInteractionContext;\r
854 /*\r
855  * Data type 'Seat', which is an API intended to contain essentially\r
856  * everything that a back end might need to talk to its client for:\r
857  * session output, password prompts, SSH warnings about host keys and\r
858  * weak cryptography, notifications of events like the remote process\r
859  * exiting or the GUI specials menu needing an update.\r
860  */\r
861 struct Seat {\r
862     const struct SeatVtable *vt;\r
863 };\r
864 struct SeatVtable {\r
865     /*\r
866      * Provide output from the remote session. 'is_stderr' indicates\r
867      * that the output should be sent to a separate error message\r
868      * channel, if the seat has one. But combining both channels into\r
869      * one is OK too; that's what terminal-window based seats do.\r
870      *\r
871      * The return value is the current size of the output backlog.\r
872      */\r
873     size_t (*output)(Seat *seat, bool is_stderr, const void *data, size_t len);\r
875     /*\r
876      * Called when the back end wants to indicate that EOF has arrived\r
877      * on the server-to-client stream. Returns false to indicate that\r
878      * we intend to keep the session open in the other direction, or\r
879      * true to indicate that if they're closing so are we.\r
880      */\r
881     bool (*eof)(Seat *seat);\r
883     /*\r
884      * Try to get answers from a set of interactive login prompts. The\r
885      * prompts are provided in 'p'; the bufchain 'input' holds the\r
886      * data currently outstanding in the session's normal standard-\r
887      * input channel. Seats may implement this function by consuming\r
888      * data from 'input' (e.g. password prompts in GUI PuTTY,\r
889      * displayed in the same terminal as the subsequent session), or\r
890      * by doing something entirely different (e.g. directly\r
891      * interacting with standard I/O, or putting up a dialog box).\r
892      *\r
893      * A positive return value means that all prompts have had answers\r
894      * filled in. A zero return means that the user performed a\r
895      * deliberate 'cancel' UI action. A negative return means that no\r
896      * answer can be given yet but please try again later.\r
897      *\r
898      * (FIXME: it would be nice to distinguish two classes of cancel\r
899      * action, so the user could specify 'I want to abandon this\r
900      * entire attempt to start a session' or the milder 'I want to\r
901      * abandon this particular form of authentication and fall back to\r
902      * a different one' - e.g. if you turn out not to be able to\r
903      * remember your private key passphrase then perhaps you'd rather\r
904      * fall back to password auth rather than aborting the whole\r
905      * session.)\r
906      *\r
907      * (Also FIXME: currently, backends' only response to the 'try\r
908      * again later' is to try again when more input data becomes\r
909      * available, because they assume that a seat is returning that\r
910      * value because it's consuming keyboard input. But a seat that\r
911      * handled this function by putting up a dialog box might want to\r
912      * put it up non-modally, and therefore would want to proactively\r
913      * notify the backend to retry once the dialog went away. So if I\r
914      * ever do want to move password prompts into a dialog box, I'll\r
915      * want a backend method for sending that notification.)\r
916      */\r
917     int (*get_userpass_input)(Seat *seat, prompts_t *p, bufchain *input);\r
919     /*\r
920      * Notify the seat that the process running at the other end of\r
921      * the connection has finished.\r
922      */\r
923     void (*notify_remote_exit)(Seat *seat);\r
925     /*\r
926      * Notify the seat that the connection has suffered a fatal error.\r
927      */\r
928     void (*connection_fatal)(Seat *seat, const char *message);\r
930     /*\r
931      * Notify the seat that the list of special commands available\r
932      * from backend_get_specials() has changed, so that it might want\r
933      * to call that function to repopulate its menu.\r
934      *\r
935      * Seats are not expected to call backend_get_specials()\r
936      * proactively; they may start by assuming that the backend\r
937      * provides no special commands at all, so if the backend does\r
938      * provide any, then it should use this notification at startup\r
939      * time. Of course it can also invoke it later if the set of\r
940      * special commands changes.\r
941      *\r
942      * It does not need to invoke it at session shutdown.\r
943      */\r
944     void (*update_specials_menu)(Seat *seat);\r
946     /*\r
947      * Get the seat's preferred value for an SSH terminal mode\r
948      * setting. Returning NULL indicates no preference (i.e. the SSH\r
949      * connection will not attempt to set the mode at all).\r
950      *\r
951      * The returned value is dynamically allocated, and the caller\r
952      * should free it.\r
953      */\r
954     char *(*get_ttymode)(Seat *seat, const char *mode);\r
956     /*\r
957      * Tell the seat whether the backend is currently doing anything\r
958      * CPU-intensive (typically a cryptographic key exchange). See\r
959      * BusyStatus enumeration above.\r
960      */\r
961     void (*set_busy_status)(Seat *seat, BusyStatus status);\r
963     /*\r
964      * Ask the seat whether a given SSH host key should be accepted.\r
965      * This may return immediately after checking saved configuration\r
966      * or command-line options, or it may have to present a prompt to\r
967      * the user and return asynchronously later.\r
968      *\r
969      * Return values:\r
970      *\r
971      *  - +1 means `key was OK' (either already known or the user just\r
972      *    approved it) `so continue with the connection'\r
973      *\r
974      *  - 0 means `key was not OK, abandon the connection'\r
975      *\r
976      *  - -1 means `I've initiated enquiries, please wait to be called\r
977      *    back via the provided function with a result that's either 0\r
978      *    or +1'.\r
979      */\r
980     int (*verify_ssh_host_key)(\r
981         Seat *seat, const char *host, int port, const char *keytype,\r
982         char *keystr, const char *keydisp, char **key_fingerprints,\r
983         void (*callback)(void *ctx, int result), void *ctx);\r
985     /*\r
986      * Check with the seat whether it's OK to use a cryptographic\r
987      * primitive from below the 'warn below this line' threshold in\r
988      * the input Conf. Return values are the same as\r
989      * verify_ssh_host_key above.\r
990      */\r
991     int (*confirm_weak_crypto_primitive)(\r
992         Seat *seat, const char *algtype, const char *algname,\r
993         void (*callback)(void *ctx, int result), void *ctx);\r
995     /*\r
996      * Variant form of confirm_weak_crypto_primitive, which prints a\r
997      * slightly different message but otherwise has the same\r
998      * semantics.\r
999      *\r
1000      * This form is used in the case where we're using a host key\r
1001      * below the warning threshold because that's the best one we have\r
1002      * cached, but at least one host key algorithm *above* the\r
1003      * threshold is available that we don't have cached. 'betteralgs'\r
1004      * lists the better algorithm(s).\r
1005      */\r
1006     int (*confirm_weak_cached_hostkey)(\r
1007         Seat *seat, const char *algname, const char *betteralgs,\r
1008         void (*callback)(void *ctx, int result), void *ctx);\r
1010     /*\r
1011      * Indicates whether the seat is expecting to interact with the\r
1012      * user in the UTF-8 character set. (Affects e.g. visual erase\r
1013      * handling in local line editing.)\r
1014      */\r
1015     bool (*is_utf8)(Seat *seat);\r
1017     /*\r
1018      * Notify the seat that the back end, and/or the ldisc between\r
1019      * them, have changed their idea of whether they currently want\r
1020      * local echo and/or local line editing enabled.\r
1021      */\r
1022     void (*echoedit_update)(Seat *seat, bool echoing, bool editing);\r
1024     /*\r
1025      * Return the local X display string relevant to a seat, or NULL\r
1026      * if there isn't one or if the concept is meaningless.\r
1027      */\r
1028     const char *(*get_x_display)(Seat *seat);\r
1030     /*\r
1031      * Return the X11 id of the X terminal window relevant to a seat,\r
1032      * by returning true and filling in the output pointer. Return\r
1033      * false if there isn't one or if the concept is meaningless.\r
1034      */\r
1035     bool (*get_windowid)(Seat *seat, long *id_out);\r
1037     /*\r
1038      * Return the size of the terminal window in pixels. If the\r
1039      * concept is meaningless or the information is unavailable,\r
1040      * return false; otherwise fill in the output pointers and return\r
1041      * true.\r
1042      */\r
1043     bool (*get_window_pixel_size)(Seat *seat, int *width, int *height);\r
1045     /*\r
1046      * Return a StripCtrlChars appropriate for sanitising untrusted\r
1047      * terminal data (e.g. SSH banners, prompts) being sent to the\r
1048      * user of this seat. May return NULL if no sanitisation is\r
1049      * needed.\r
1050      */\r
1051     StripCtrlChars *(*stripctrl_new)(\r
1052         Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1054     /*\r
1055      * Set the seat's current idea of where output is coming from.\r
1056      * True means that output is being generated by our own code base\r
1057      * (and hence, can be trusted if it's asking you for secrets such\r
1058      * as your passphrase); false means output is coming from the\r
1059      * server.\r
1060      *\r
1061      * Returns true if the seat has a way to indicate this\r
1062      * distinction. Returns false if not, in which case the backend\r
1063      * should use a fallback defence against spoofing of PuTTY's local\r
1064      * prompts by malicious servers.\r
1065      */\r
1066     bool (*set_trust_status)(Seat *seat, bool trusted);\r
1068     /*\r
1069      * Ask the seat whether it would like verbose messages.\r
1070      */\r
1071     bool (*verbose)(Seat *seat);\r
1073     /*\r
1074      * Ask the seat whether it's an interactive program.\r
1075      */\r
1076     bool (*interactive)(Seat *seat);\r
1078     /*\r
1079      * Return the seat's current idea of where the output cursor is.\r
1080      *\r
1081      * Returns true if the seat has a cursor. Returns false if not.\r
1082      */\r
1083     bool (*get_cursor_position)(Seat *seat, int *x, int *y);\r
1084 };\r
1086 static inline size_t seat_output(\r
1087     Seat *seat, bool err, const void *data, size_t len)\r
1088 { return seat->vt->output(seat, err, data, len); }\r
1089 static inline bool seat_eof(Seat *seat)\r
1090 { return seat->vt->eof(seat); }\r
1091 static inline int seat_get_userpass_input(\r
1092     Seat *seat, prompts_t *p, bufchain *input)\r
1093 { return seat->vt->get_userpass_input(seat, p, input); }\r
1094 static inline void seat_notify_remote_exit(Seat *seat)\r
1095 { seat->vt->notify_remote_exit(seat); }\r
1096 static inline void seat_update_specials_menu(Seat *seat)\r
1097 { seat->vt->update_specials_menu(seat); }\r
1098 static inline char *seat_get_ttymode(Seat *seat, const char *mode)\r
1099 { return seat->vt->get_ttymode(seat, mode); }\r
1100 static inline void seat_set_busy_status(Seat *seat, BusyStatus status)\r
1101 { seat->vt->set_busy_status(seat, status); }\r
1102 static inline int seat_verify_ssh_host_key(\r
1103     Seat *seat, const char *h, int p, const char *ktyp, char *kstr,\r
1104     const char *kdsp, char **fps, void (*cb)(void *ctx, int result), void *ctx)\r
1105 { return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, kdsp, fps,\r
1106                                        cb, ctx); }\r
1107 static inline int seat_confirm_weak_crypto_primitive(\r
1108     Seat *seat, const char *atyp, const char *aname,\r
1109     void (*cb)(void *ctx, int result), void *ctx)\r
1110 { return seat->vt->confirm_weak_crypto_primitive(seat, atyp, aname, cb, ctx); }\r
1111 static inline int seat_confirm_weak_cached_hostkey(\r
1112     Seat *seat, const char *aname, const char *better,\r
1113     void (*cb)(void *ctx, int result), void *ctx)\r
1114 { return seat->vt->confirm_weak_cached_hostkey(seat, aname, better, cb, ctx); }\r
1115 static inline bool seat_is_utf8(Seat *seat)\r
1116 { return seat->vt->is_utf8(seat); }\r
1117 static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)\r
1118 { seat->vt->echoedit_update(seat, ec, ed); }\r
1119 static inline const char *seat_get_x_display(Seat *seat)\r
1120 { return seat->vt->get_x_display(seat); }\r
1121 static inline bool seat_get_windowid(Seat *seat, long *id_out)\r
1122 { return seat->vt->get_windowid(seat, id_out); }\r
1123 static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)\r
1124 { return seat->vt->get_window_pixel_size(seat, w, h); }\r
1125 static inline StripCtrlChars *seat_stripctrl_new(\r
1126     Seat *seat, BinarySink *bs, SeatInteractionContext sic)\r
1127 { return seat->vt->stripctrl_new(seat, bs, sic); }\r
1128 static inline bool seat_set_trust_status(Seat *seat, bool trusted)\r
1129 { return  seat->vt->set_trust_status(seat, trusted); }\r
1130 static inline bool seat_verbose(Seat *seat)\r
1131 { return seat->vt->verbose(seat); }\r
1132 static inline bool seat_interactive(Seat *seat)\r
1133 { return seat->vt->interactive(seat); }\r
1134 static inline bool seat_get_cursor_position(Seat *seat, int *x, int *y)\r
1135 { return  seat->vt->get_cursor_position(seat, x, y); }\r
1137 /* Unlike the seat's actual method, the public entry point\r
1138  * seat_connection_fatal is a wrapper function with a printf-like API,\r
1139  * defined in misc.c. */\r
1140 void seat_connection_fatal(Seat *seat, const char *fmt, ...) PRINTF_LIKE(2, 3);\r
1142 /* Handy aliases for seat_output which set is_stderr to a fixed value. */\r
1143 static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)\r
1144 { return seat_output(seat, false, data, len); }\r
1145 static inline size_t seat_stdout_pl(Seat *seat, ptrlen data)\r
1146 { return seat_output(seat, false, data.ptr, data.len); }\r
1147 static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)\r
1148 { return seat_output(seat, true, data, len); }\r
1149 static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)\r
1150 { return seat_output(seat, true, data.ptr, data.len); }\r
1152 /*\r
1153  * Stub methods for seat implementations that want to use the obvious\r
1154  * null handling for a given method.\r
1155  *\r
1156  * These are generally obvious, except for is_utf8, where you might\r
1157  * plausibly want to return either fixed answer 'no' or 'yes'.\r
1158  */\r
1159 size_t nullseat_output(\r
1160     Seat *seat, bool is_stderr, const void *data, size_t len);\r
1161 bool nullseat_eof(Seat *seat);\r
1162 int nullseat_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);\r
1163 void nullseat_notify_remote_exit(Seat *seat);\r
1164 void nullseat_connection_fatal(Seat *seat, const char *message);\r
1165 void nullseat_update_specials_menu(Seat *seat);\r
1166 char *nullseat_get_ttymode(Seat *seat, const char *mode);\r
1167 void nullseat_set_busy_status(Seat *seat, BusyStatus status);\r
1168 int nullseat_verify_ssh_host_key(\r
1169     Seat *seat, const char *host, int port, const char *keytype,\r
1170     char *keystr, const char *keydisp, char **key_fingerprints,\r
1171     void (*callback)(void *ctx, int result), void *ctx);\r
1172 int nullseat_confirm_weak_crypto_primitive(\r
1173     Seat *seat, const char *algtype, const char *algname,\r
1174     void (*callback)(void *ctx, int result), void *ctx);\r
1175 int nullseat_confirm_weak_cached_hostkey(\r
1176     Seat *seat, const char *algname, const char *betteralgs,\r
1177     void (*callback)(void *ctx, int result), void *ctx);\r
1178 bool nullseat_is_never_utf8(Seat *seat);\r
1179 bool nullseat_is_always_utf8(Seat *seat);\r
1180 void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing);\r
1181 const char *nullseat_get_x_display(Seat *seat);\r
1182 bool nullseat_get_windowid(Seat *seat, long *id_out);\r
1183 bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height);\r
1184 StripCtrlChars *nullseat_stripctrl_new(\r
1185         Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1186 bool nullseat_set_trust_status(Seat *seat, bool trusted);\r
1187 bool nullseat_set_trust_status_vacuously(Seat *seat, bool trusted);\r
1188 bool nullseat_verbose_no(Seat *seat);\r
1189 bool nullseat_verbose_yes(Seat *seat);\r
1190 bool nullseat_interactive_no(Seat *seat);\r
1191 bool nullseat_interactive_yes(Seat *seat);\r
1192 bool nullseat_get_cursor_position(Seat *seat, int *x, int *y);\r
1194 /*\r
1195  * Seat functions provided by the platform's console-application\r
1196  * support module (wincons.c, uxcons.c).\r
1197  */\r
1199 void console_connection_fatal(Seat *seat, const char *message);\r
1200 int console_verify_ssh_host_key(\r
1201     Seat *seat, const char *host, int port, const char *keytype,\r
1202     char *keystr, const char *keydisp, char **key_fingerprints,\r
1203     void (*callback)(void *ctx, int result), void *ctx);\r
1204 int console_confirm_weak_crypto_primitive(\r
1205     Seat *seat, const char *algtype, const char *algname,\r
1206     void (*callback)(void *ctx, int result), void *ctx);\r
1207 int console_confirm_weak_cached_hostkey(\r
1208     Seat *seat, const char *algname, const char *betteralgs,\r
1209     void (*callback)(void *ctx, int result), void *ctx);\r
1210 StripCtrlChars *console_stripctrl_new(\r
1211         Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1212 bool console_set_trust_status(Seat *seat, bool trusted);\r
1214 /*\r
1215  * Other centralised seat functions.\r
1216  */\r
1217 int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);\r
1218 bool cmdline_seat_verbose(Seat *seat);\r
1220 typedef struct rgb {\r
1221     uint8_t r, g, b;\r
1222 } rgb;\r
1224 /*\r
1225  * Data type 'TermWin', which is a vtable encapsulating all the\r
1226  * functionality that Terminal expects from its containing terminal\r
1227  * window.\r
1228  */\r
1229 struct TermWin {\r
1230     const struct TermWinVtable *vt;\r
1231 };\r
1232 struct TermWinVtable {\r
1233     /*\r
1234      * All functions listed here between setup_draw_ctx and\r
1235      * free_draw_ctx expect to be _called_ between them too, so that\r
1236      * the TermWin has a drawing context currently available.\r
1237      *\r
1238      * (Yes, even char_width, because e.g. the Windows implementation\r
1239      * of TermWin handles it by loading the currently configured font\r
1240      * into the HDC and doing a GDI query.)\r
1241      */\r
1242     bool (*setup_draw_ctx)(TermWin *);\r
1243     /* Draw text in the window, during a painting operation */\r
1244     void (*draw_text)(TermWin *, int x, int y, wchar_t *text, int len,\r
1245                       unsigned long attrs, int line_attrs, truecolour tc);\r
1246     /* Draw the visible cursor. Expects you to have called do_text\r
1247      * first (because it might just draw an underline over a character\r
1248      * presumed to exist already), but also expects you to pass in all\r
1249      * the details of the character under the cursor (because it might\r
1250      * redraw it in different colours). */\r
1251     void (*draw_cursor)(TermWin *, int x, int y, wchar_t *text, int len,\r
1252                         unsigned long attrs, int line_attrs, truecolour tc);\r
1253     /* Draw the sigil indicating that a line of text has come from\r
1254      * PuTTY itself rather than the far end (defence against end-of-\r
1255      * authentication spoofing) */\r
1256     void (*draw_trust_sigil)(TermWin *, int x, int y);\r
1257     int (*char_width)(TermWin *, int uc);\r
1258     void (*free_draw_ctx)(TermWin *);\r
1260     void (*set_cursor_pos)(TermWin *, int x, int y);\r
1262     /* set_raw_mouse_mode instructs the front end to start sending mouse events\r
1263      * in raw mode suitable for translating into mouse-tracking terminal data\r
1264      * (e.g. include scroll-wheel events and don't bother to identify double-\r
1265      * and triple-clicks). set_raw_mouse_mode_pointer instructs the front end\r
1266      * to change the mouse pointer shape to *indicate* raw mouse mode. */\r
1267     void (*set_raw_mouse_mode)(TermWin *, bool enable);\r
1268     void (*set_raw_mouse_mode_pointer)(TermWin *, bool enable);\r
1270     void (*set_scrollbar)(TermWin *, int total, int start, int page);\r
1272     void (*bell)(TermWin *, int mode);\r
1274     void (*clip_write)(TermWin *, int clipboard, wchar_t *text, int *attrs,\r
1275                        truecolour *colours, int len, bool must_deselect);\r
1276     void (*clip_request_paste)(TermWin *, int clipboard);\r
1278     void (*refresh)(TermWin *);\r
1280     void (*request_resize)(TermWin *, int w, int h);\r
1282     void (*set_title)(TermWin *, const char *title);\r
1283     void (*set_icon_title)(TermWin *, const char *icontitle);\r
1284     /* set_minimised and set_maximised are assumed to set two\r
1285      * independent settings, rather than a single three-way\r
1286      * {min,normal,max} switch. The idea is that when you un-minimise\r
1287      * the window it remembers whether to go back to normal or\r
1288      * maximised. */\r
1289     void (*set_minimised)(TermWin *, bool minimised);\r
1290     void (*set_maximised)(TermWin *, bool maximised);\r
1291     void (*move)(TermWin *, int x, int y);\r
1292     void (*set_zorder)(TermWin *, bool top);\r
1294     /* Set the colour palette that the TermWin will use to display\r
1295      * text. One call to this function sets 'ncolours' consecutive\r
1296      * colours in the OSC 4 sequence, starting at 'start'. */\r
1297     void (*palette_set)(TermWin *, unsigned start, unsigned ncolours,\r
1298                         const rgb *colours);\r
1300     /* Query the front end for any OS-local overrides to the default\r
1301      * colours stored in Conf. The front end should set any it cares\r
1302      * about by calling term_palette_override.\r
1303      *\r
1304      * The Terminal object is passed in as a parameter, because this\r
1305      * can be called as a callback from term_init(). So the TermWin\r
1306      * itself won't yet have been told where to find its Terminal\r
1307      * object, because that doesn't happen until term_init\r
1308      * returns. */\r
1309     void (*palette_get_overrides)(TermWin *, Terminal *);\r
1310 };\r
1312 static inline bool win_setup_draw_ctx(TermWin *win)\r
1313 { return win->vt->setup_draw_ctx(win); }\r
1314 static inline void win_draw_text(\r
1315     TermWin *win, int x, int y, wchar_t *text, int len,\r
1316     unsigned long attrs, int line_attrs, truecolour tc)\r
1317 { win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc); }\r
1318 static inline void win_draw_cursor(\r
1319     TermWin *win, int x, int y, wchar_t *text, int len,\r
1320     unsigned long attrs, int line_attrs, truecolour tc)\r
1321 { win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc); }\r
1322 static inline void win_draw_trust_sigil(TermWin *win, int x, int y)\r
1323 { win->vt->draw_trust_sigil(win, x, y); }\r
1324 static inline int win_char_width(TermWin *win, int uc)\r
1325 { return win->vt->char_width(win, uc); }\r
1326 static inline void win_free_draw_ctx(TermWin *win)\r
1327 { win->vt->free_draw_ctx(win); }\r
1328 static inline void win_set_cursor_pos(TermWin *win, int x, int y)\r
1329 { win->vt->set_cursor_pos(win, x, y); }\r
1330 static inline void win_set_raw_mouse_mode(TermWin *win, bool enable)\r
1331 { win->vt->set_raw_mouse_mode(win, enable); }\r
1332 static inline void win_set_raw_mouse_mode_pointer(TermWin *win, bool enable)\r
1333 { win->vt->set_raw_mouse_mode_pointer(win, enable); }\r
1334 static inline void win_set_scrollbar(TermWin *win, int t, int s, int p)\r
1335 { win->vt->set_scrollbar(win, t, s, p); }\r
1336 static inline void win_bell(TermWin *win, int mode)\r
1337 { win->vt->bell(win, mode); }\r
1338 static inline void win_clip_write(\r
1339     TermWin *win, int clipboard, wchar_t *text, int *attrs,\r
1340     truecolour *colours, int len, bool deselect)\r
1341 { win->vt->clip_write(win, clipboard, text, attrs, colours, len, deselect); }\r
1342 static inline void win_clip_request_paste(TermWin *win, int clipboard)\r
1343 { win->vt->clip_request_paste(win, clipboard); }\r
1344 static inline void win_refresh(TermWin *win)\r
1345 { win->vt->refresh(win); }\r
1346 static inline void win_request_resize(TermWin *win, int w, int h)\r
1347 { win->vt->request_resize(win, w, h); }\r
1348 static inline void win_set_title(TermWin *win, const char *title)\r
1349 { win->vt->set_title(win, title); }\r
1350 static inline void win_set_icon_title(TermWin *win, const char *icontitle)\r
1351 { win->vt->set_icon_title(win, icontitle); }\r
1352 static inline void win_set_minimised(TermWin *win, bool minimised)\r
1353 { win->vt->set_minimised(win, minimised); }\r
1354 static inline void win_set_maximised(TermWin *win, bool maximised)\r
1355 { win->vt->set_maximised(win, maximised); }\r
1356 static inline void win_move(TermWin *win, int x, int y)\r
1357 { win->vt->move(win, x, y); }\r
1358 static inline void win_set_zorder(TermWin *win, bool top)\r
1359 { win->vt->set_zorder(win, top); }\r
1360 static inline void win_palette_set(\r
1361     TermWin *win, unsigned start, unsigned ncolours, const rgb *colours)\r
1362 { win->vt->palette_set(win, start, ncolours, colours); }\r
1363 static inline void win_palette_get_overrides(TermWin *win, Terminal *term)\r
1364 { win->vt->palette_get_overrides(win, term); }\r
1366 /*\r
1367  * Global functions not specific to a connection instance.\r
1368  */\r
1369 void nonfatal(const char *, ...) PRINTF_LIKE(1, 2);\r
1370 NORETURN void modalfatalbox(const char *, ...) PRINTF_LIKE(1, 2);\r
1371 NORETURN void cleanup_exit(int);\r
1373 /*\r
1374  * Exports from conf.c, and a big enum (via parametric macro) of\r
1375  * configuration option keys.\r
1376  */\r
1377 #define CONFIG_OPTIONS(X) \\r
1378     /* X(value-type, subkey-type, keyword) */ \\r
1379     X(STR, NONE, host) \\r
1380     X(INT, NONE, port) \\r
1381     X(INT, NONE, protocol) /* PROT_SSH, PROT_TELNET etc */ \\r
1382     X(INT, NONE, addressfamily) /* ADDRTYPE_IPV[46] or ADDRTYPE_UNSPEC */ \\r
1383     X(INT, NONE, close_on_exit) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1384     X(BOOL, NONE, warn_on_close) \\r
1385     X(INT, NONE, ping_interval) /* in seconds */ \\r
1386     X(BOOL, NONE, tcp_nodelay) \\r
1387     X(BOOL, NONE, tcp_keepalives) \\r
1388     X(STR, NONE, loghost) /* logical host being contacted, for host key check */ \\r
1389     /* Proxy options */ \\r
1390     X(STR, NONE, proxy_exclude_list) \\r
1391     X(INT, NONE, proxy_dns) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1392     X(BOOL, NONE, even_proxy_localhost) \\r
1393     X(INT, NONE, proxy_type) /* PROXY_NONE, PROXY_SOCKS4, ... */ \\r
1394     X(STR, NONE, proxy_host) \\r
1395     X(INT, NONE, proxy_port) \\r
1396     X(STR, NONE, proxy_username) \\r
1397     X(STR, NONE, proxy_password) \\r
1398     X(STR, NONE, proxy_telnet_command) \\r
1399     X(INT, NONE, proxy_log_to_term) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1400     /* SSH options */ \\r
1401     X(STR, NONE, remote_cmd) \\r
1402     X(STR, NONE, remote_cmd2) /* fallback if remote_cmd fails; never loaded or saved */ \\r
1403     X(BOOL, NONE, nopty) \\r
1404     X(BOOL, NONE, compression) \\r
1405     X(INT, INT, ssh_kexlist) \\r
1406     X(INT, INT, ssh_hklist) \\r
1407     X(BOOL, NONE, ssh_prefer_known_hostkeys) \\r
1408     X(INT, NONE, ssh_rekey_time) /* in minutes */ \\r
1409     X(STR, NONE, ssh_rekey_data) /* string encoding e.g. "100K", "2M", "1G" */ \\r
1410     X(BOOL, NONE, tryagent) \\r
1411     X(BOOL, NONE, agentfwd) \\r
1412     X(BOOL, NONE, change_username) /* allow username switching in SSH-2 */ \\r
1413     X(INT, INT, ssh_cipherlist) \\r
1414     X(FILENAME, NONE, keyfile) \\r
1415     /* \\r
1416      * Which SSH protocol to use. \\r
1417      * For historical reasons, the current legal values for CONF_sshprot \\r
1418      * are: \\r
1419      *  0 = SSH-1 only \\r
1420      *  3 = SSH-2 only \\r
1421      * We used to also support \\r
1422      *  1 = SSH-1 with fallback to SSH-2 \\r
1423      *  2 = SSH-2 with fallback to SSH-1 \\r
1424      * and we continue to use 0/3 in storage formats rather than the more \\r
1425      * obvious 1/2 to avoid surprises if someone saves a session and later \\r
1426      * downgrades PuTTY. So it's easier to use these numbers internally too. \\r
1427      */ \\r
1428     X(INT, NONE, sshprot) \\r
1429     X(BOOL, NONE, ssh2_des_cbc) /* "des-cbc" unrecommended SSH-2 cipher */ \\r
1430     X(BOOL, NONE, ssh_no_userauth) /* bypass "ssh-userauth" (SSH-2 only) */ \\r
1431     X(BOOL, NONE, ssh_no_trivial_userauth) /* disable trivial types of auth */ \\r
1432     X(BOOL, NONE, ssh_show_banner) /* show USERAUTH_BANNERs (SSH-2 only) */ \\r
1433     X(BOOL, NONE, try_tis_auth) \\r
1434     X(BOOL, NONE, try_ki_auth) \\r
1435     X(BOOL, NONE, try_gssapi_auth) /* attempt gssapi auth via ssh userauth */ \\r
1436     X(BOOL, NONE, try_gssapi_kex) /* attempt gssapi auth via ssh kex */ \\r
1437     X(BOOL, NONE, gssapifwd) /* forward tgt via gss */ \\r
1438     X(INT, NONE, gssapirekey) /* KEXGSS refresh interval (mins) */ \\r
1439     X(INT, INT, ssh_gsslist) /* preference order for local GSS libs */ \\r
1440     X(FILENAME, NONE, ssh_gss_custom) \\r
1441     X(BOOL, NONE, ssh_subsys) /* run a subsystem rather than a command */ \\r
1442     X(BOOL, NONE, ssh_subsys2) /* fallback to go with remote_cmd_ptr2 */ \\r
1443     X(BOOL, NONE, ssh_no_shell) /* avoid running a shell */ \\r
1444     X(STR, NONE, ssh_nc_host) /* host to connect to in `nc' mode */ \\r
1445     X(INT, NONE, ssh_nc_port) /* port to connect to in `nc' mode */ \\r
1446     /* Telnet options */ \\r
1447     X(STR, NONE, termtype) \\r
1448     X(STR, NONE, termspeed) \\r
1449     X(STR, STR, ttymodes) /* values are "Vvalue" or "A" */ \\r
1450     X(STR, STR, environmt) \\r
1451     X(STR, NONE, username) \\r
1452     X(BOOL, NONE, username_from_env) \\r
1453     X(STR, NONE, localusername) \\r
1454     X(BOOL, NONE, rfc_environ) \\r
1455     X(BOOL, NONE, passive_telnet) \\r
1456     /* Serial port options */ \\r
1457     X(STR, NONE, serline) \\r
1458     X(INT, NONE, serspeed) \\r
1459     X(INT, NONE, serdatabits) \\r
1460     X(INT, NONE, serstopbits) \\r
1461     X(INT, NONE, serparity) /* SER_PAR_NONE, SER_PAR_ODD, ... */ \\r
1462     X(INT, NONE, serflow) /* SER_FLOW_NONE, SER_FLOW_XONXOFF, ... */ \\r
1463     /* Supdup options */ \\r
1464     X(STR, NONE, supdup_location) \\r
1465     X(INT, NONE, supdup_ascii_set) \\r
1466     X(BOOL, NONE, supdup_more) \\r
1467     X(BOOL, NONE, supdup_scroll) \\r
1468     /* Keyboard options */ \\r
1469     X(BOOL, NONE, bksp_is_delete) \\r
1470     X(BOOL, NONE, rxvt_homeend) \\r
1471     X(INT, NONE, funky_type) /* FUNKY_XTERM, FUNKY_LINUX, ... */ \\r
1472     X(BOOL, NONE, no_applic_c) /* totally disable app cursor keys */ \\r
1473     X(BOOL, NONE, no_applic_k) /* totally disable app keypad */ \\r
1474     X(BOOL, NONE, no_mouse_rep) /* totally disable mouse reporting */ \\r
1475     X(BOOL, NONE, no_remote_resize) /* disable remote resizing */ \\r
1476     X(BOOL, NONE, no_alt_screen) /* disable alternate screen */ \\r
1477     X(BOOL, NONE, no_remote_wintitle) /* disable remote retitling */ \\r
1478     X(BOOL, NONE, no_remote_clearscroll) /* disable ESC[3J */ \\r
1479     X(BOOL, NONE, no_dbackspace) /* disable destructive backspace */ \\r
1480     X(BOOL, NONE, no_remote_charset) /* disable remote charset config */ \\r
1481     X(INT, NONE, remote_qtitle_action) /* remote win title query action\r
1482                                        * (TITLE_NONE, TITLE_EMPTY, ...) */ \\r
1483     X(BOOL, NONE, app_cursor) \\r
1484     X(BOOL, NONE, app_keypad) \\r
1485     X(BOOL, NONE, nethack_keypad) \\r
1486     X(BOOL, NONE, telnet_keyboard) \\r
1487     X(BOOL, NONE, telnet_newline) \\r
1488     X(BOOL, NONE, alt_f4) /* is it special? */ \\r
1489     X(BOOL, NONE, alt_space) /* is it special? */ \\r
1490     X(BOOL, NONE, alt_only) /* is it special? */ \\r
1491     X(INT, NONE, localecho) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1492     X(INT, NONE, localedit) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1493     X(BOOL, NONE, alwaysontop) \\r
1494     X(BOOL, NONE, fullscreenonaltenter) \\r
1495     X(BOOL, NONE, scroll_on_key) \\r
1496     X(BOOL, NONE, scroll_on_disp) \\r
1497     X(BOOL, NONE, erase_to_scrollback) \\r
1498     X(BOOL, NONE, compose_key) \\r
1499     X(BOOL, NONE, ctrlaltkeys) \\r
1500     X(BOOL, NONE, osx_option_meta) \\r
1501     X(BOOL, NONE, osx_command_meta) \\r
1502     X(STR, NONE, wintitle) /* initial window title */ \\r
1503     /* Terminal options */ \\r
1504     X(INT, NONE, savelines) \\r
1505     X(BOOL, NONE, dec_om) \\r
1506     X(BOOL, NONE, wrap_mode) \\r
1507     X(BOOL, NONE, lfhascr) \\r
1508     X(INT, NONE, cursor_type) /* 0=block 1=underline 2=vertical */ \\r
1509     X(BOOL, NONE, blink_cur) \\r
1510     X(INT, NONE, beep) /* BELL_DISABLED, BELL_DEFAULT, ... */ \\r
1511     X(INT, NONE, beep_ind) /* B_IND_DISABLED, B_IND_FLASH, ... */ \\r
1512     X(BOOL, NONE, bellovl) /* bell overload protection active? */ \\r
1513     X(INT, NONE, bellovl_n) /* number of bells to cause overload */ \\r
1514     X(INT, NONE, bellovl_t) /* time interval for overload (seconds) */ \\r
1515     X(INT, NONE, bellovl_s) /* period of silence to re-enable bell (s) */ \\r
1516     X(FILENAME, NONE, bell_wavefile) \\r
1517     X(BOOL, NONE, scrollbar) \\r
1518     X(BOOL, NONE, scrollbar_in_fullscreen) \\r
1519     X(INT, NONE, resize_action) /* RESIZE_TERM, RESIZE_DISABLED, ... */ \\r
1520     X(BOOL, NONE, bce) \\r
1521     X(BOOL, NONE, blinktext) \\r
1522     X(BOOL, NONE, win_name_always) \\r
1523     X(INT, NONE, width) \\r
1524     X(INT, NONE, height) \\r
1525     X(FONT, NONE, font) \\r
1526     X(INT, NONE, font_quality) /* FQ_DEFAULT, FQ_ANTIALIASED, ... */ \\r
1527     X(FILENAME, NONE, logfilename) \\r
1528     X(INT, NONE, logtype) /* LGTYP_NONE, LGTYPE_ASCII, ... */ \\r
1529     X(INT, NONE, logxfovr) /* LGXF_OVR, LGXF_APN, LGXF_ASK */ \\r
1530     X(BOOL, NONE, logflush) \\r
1531     X(BOOL, NONE, logheader) \\r
1532     X(BOOL, NONE, logomitpass) \\r
1533     X(BOOL, NONE, logomitdata) \\r
1534     X(BOOL, NONE, hide_mouseptr) \\r
1535     X(BOOL, NONE, sunken_edge) \\r
1536     X(INT, NONE, window_border) /* in pixels */ \\r
1537     X(STR, NONE, answerback) \\r
1538     X(STR, NONE, printer) \\r
1539     X(BOOL, NONE, no_arabicshaping) \\r
1540     X(BOOL, NONE, no_bidi) \\r
1541     /* Colour options */ \\r
1542     X(BOOL, NONE, ansi_colour) \\r
1543     X(BOOL, NONE, xterm_256_colour) \\r
1544     X(BOOL, NONE, true_colour) \\r
1545     X(BOOL, NONE, system_colour) \\r
1546     X(BOOL, NONE, try_palette) \\r
1547     X(INT, NONE, bold_style) /* 1=font 2=colour (3=both) */ \\r
1548     X(INT, INT, colours) /* indexed by the CONF_COLOUR_* enum encoding */ \\r
1549     /* Selection options */ \\r
1550     X(INT, NONE, mouse_is_xterm) /* 0=compromise 1=xterm 2=Windows */ \\r
1551     X(BOOL, NONE, rect_select) \\r
1552     X(BOOL, NONE, paste_controls) \\r
1553     X(BOOL, NONE, rawcnp) \\r
1554     X(BOOL, NONE, utf8linedraw) \\r
1555     X(BOOL, NONE, rtf_paste) \\r
1556     X(BOOL, NONE, mouse_override) \\r
1557     X(INT, INT, wordness) \\r
1558     X(BOOL, NONE, mouseautocopy) \\r
1559     X(INT, NONE, mousepaste) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1560     X(INT, NONE, ctrlshiftins) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1561     X(INT, NONE, ctrlshiftcv) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1562     X(STR, NONE, mousepaste_custom) \\r
1563     X(STR, NONE, ctrlshiftins_custom) \\r
1564     X(STR, NONE, ctrlshiftcv_custom) \\r
1565     /* translations */ \\r
1566     X(INT, NONE, vtmode) /* VT_XWINDOWS, VT_OEMANSI, ... */ \\r
1567     X(STR, NONE, line_codepage) \\r
1568     X(BOOL, NONE, cjk_ambig_wide) \\r
1569     X(BOOL, NONE, utf8_override) \\r
1570     X(BOOL, NONE, xlat_capslockcyr) \\r
1571     /* X11 forwarding */ \\r
1572     X(BOOL, NONE, x11_forward) \\r
1573     X(STR, NONE, x11_display) \\r
1574     X(INT, NONE, x11_auth) /* X11_NO_AUTH, X11_MIT, X11_XDM */ \\r
1575     X(FILENAME, NONE, xauthfile) \\r
1576     /* port forwarding */ \\r
1577     X(BOOL, NONE, lport_acceptall) /* accept conns from hosts other than localhost */ \\r
1578     X(BOOL, NONE, rport_acceptall) /* same for remote forwarded ports (SSH-2 only) */ \\r
1579     /*                                                                \\r
1580      * Subkeys for 'portfwd' can have the following forms:            \\r
1581      *                                                                \\r
1582      *   [LR]localport                                                \\r
1583      *   [LR]localaddr:localport                                      \\r
1584      *                                                                \\r
1585      * Dynamic forwardings are indicated by an 'L' key, and the       \\r
1586      * special value "D". For all other forwardings, the value        \\r
1587      * should be of the form 'host:port'.                             \\r
1588      */ \\r
1589     X(STR, STR, portfwd) \\r
1590     /* SSH bug compatibility modes. All FORCE_ON/FORCE_OFF/AUTO */ \\r
1591     X(INT, NONE, sshbug_ignore1) \\r
1592     X(INT, NONE, sshbug_plainpw1) \\r
1593     X(INT, NONE, sshbug_rsa1) \\r
1594     X(INT, NONE, sshbug_hmac2) \\r
1595     X(INT, NONE, sshbug_derivekey2) \\r
1596     X(INT, NONE, sshbug_rsapad2) \\r
1597     X(INT, NONE, sshbug_pksessid2) \\r
1598     X(INT, NONE, sshbug_rekey2) \\r
1599     X(INT, NONE, sshbug_maxpkt2) \\r
1600     X(INT, NONE, sshbug_ignore2) \\r
1601     X(INT, NONE, sshbug_oldgex2) \\r
1602     X(INT, NONE, sshbug_winadj) \\r
1603     X(INT, NONE, sshbug_chanreq) \\r
1604     /*                                                                \\r
1605      * ssh_simple means that we promise never to open any channel     \\r
1606      * other than the main one, which means it can safely use a very  \\r
1607      * large window in SSH-2.                                         \\r
1608      */ \\r
1609     X(BOOL, NONE, ssh_simple) \\r
1610     X(BOOL, NONE, ssh_connection_sharing) \\r
1611     X(BOOL, NONE, ssh_connection_sharing_upstream) \\r
1612     X(BOOL, NONE, ssh_connection_sharing_downstream) \\r
1613     /*\r
1614      * ssh_manual_hostkeys is conceptually a set rather than a\r
1615      * dictionary: the string subkeys are the important thing, and the\r
1616      * actual values to which those subkeys map are all "".\r
1617      */ \\r
1618     X(STR, STR, ssh_manual_hostkeys) \\r
1619     /* Options for pterm. Should split out into platform-dependent part. */ \\r
1620     X(BOOL, NONE, stamp_utmp) \\r
1621     X(BOOL, NONE, login_shell) \\r
1622     X(BOOL, NONE, scrollbar_on_left) \\r
1623     X(BOOL, NONE, shadowbold) \\r
1624     X(FONT, NONE, boldfont) \\r
1625     X(FONT, NONE, widefont) \\r
1626     X(FONT, NONE, wideboldfont) \\r
1627     X(INT, NONE, shadowboldoffset) /* in pixels */ \\r
1628     X(BOOL, NONE, crhaslf) \\r
1629     X(STR, NONE, winclass) \\r
1630     /* end of list */\r
1632 /* Now define the actual enum of option keywords using that macro. */\r
1633 #define CONF_ENUM_DEF(valtype, keytype, keyword) CONF_ ## keyword,\r
1634 enum config_primary_key { CONFIG_OPTIONS(CONF_ENUM_DEF) N_CONFIG_OPTIONS };\r
1635 #undef CONF_ENUM_DEF\r
1637 /* Functions handling configuration structures. */\r
1638 Conf *conf_new(void);                  /* create an empty configuration */\r
1639 void conf_free(Conf *conf);\r
1640 Conf *conf_copy(Conf *oldconf);\r
1641 void conf_copy_into(Conf *dest, Conf *src);\r
1642 /* Mandatory accessor functions: enforce by assertion that keys exist. */\r
1643 bool conf_get_bool(Conf *conf, int key);\r
1644 int conf_get_int(Conf *conf, int key);\r
1645 int conf_get_int_int(Conf *conf, int key, int subkey);\r
1646 char *conf_get_str(Conf *conf, int key);   /* result still owned by conf */\r
1647 char *conf_get_str_str(Conf *conf, int key, const char *subkey);\r
1648 Filename *conf_get_filename(Conf *conf, int key);\r
1649 FontSpec *conf_get_fontspec(Conf *conf, int key); /* still owned by conf */\r
1650 /* Optional accessor function: return NULL if key does not exist. */\r
1651 char *conf_get_str_str_opt(Conf *conf, int key, const char *subkey);\r
1652 /* Accessor function to step through a string-subkeyed list.\r
1653  * Returns the next subkey after the provided one, or the first if NULL.\r
1654  * Returns NULL if there are none left.\r
1655  * Both the return value and *subkeyout are still owned by conf. */\r
1656 char *conf_get_str_strs(Conf *conf, int key, char *subkeyin, char **subkeyout);\r
1657 /* Return the nth string subkey in a list. Owned by conf. NULL if beyond end */\r
1658 char *conf_get_str_nthstrkey(Conf *conf, int key, int n);\r
1659 /* Functions to set entries in configuration. Always copy their inputs. */\r
1660 void conf_set_bool(Conf *conf, int key, bool value);\r
1661 void conf_set_int(Conf *conf, int key, int value);\r
1662 void conf_set_int_int(Conf *conf, int key, int subkey, int value);\r
1663 void conf_set_str(Conf *conf, int key, const char *value);\r
1664 void conf_set_str_str(Conf *conf, int key,\r
1665                       const char *subkey, const char *val);\r
1666 void conf_del_str_str(Conf *conf, int key, const char *subkey);\r
1667 void conf_set_filename(Conf *conf, int key, const Filename *val);\r
1668 void conf_set_fontspec(Conf *conf, int key, const FontSpec *val);\r
1669 /* Serialisation functions for Duplicate Session */\r
1670 void conf_serialise(BinarySink *bs, Conf *conf);\r
1671 bool conf_deserialise(Conf *conf, BinarySource *src);/*returns true on success*/\r
1673 /*\r
1674  * Functions to copy, free, serialise and deserialise FontSpecs.\r
1675  * Provided per-platform, to go with the platform's idea of a\r
1676  * FontSpec's contents.\r
1677  */\r
1678 FontSpec *fontspec_copy(const FontSpec *f);\r
1679 void fontspec_free(FontSpec *f);\r
1680 void fontspec_serialise(BinarySink *bs, FontSpec *f);\r
1681 FontSpec *fontspec_deserialise(BinarySource *src);\r
1683 /*\r
1684  * Exports from noise.c.\r
1685  */\r
1686 typedef enum NoiseSourceId {\r
1687     NOISE_SOURCE_TIME,\r
1688     NOISE_SOURCE_IOID,\r
1689     NOISE_SOURCE_IOLEN,\r
1690     NOISE_SOURCE_KEY,\r
1691     NOISE_SOURCE_MOUSEBUTTON,\r
1692     NOISE_SOURCE_MOUSEPOS,\r
1693     NOISE_SOURCE_MEMINFO,\r
1694     NOISE_SOURCE_STAT,\r
1695     NOISE_SOURCE_RUSAGE,\r
1696     NOISE_SOURCE_FGWINDOW,\r
1697     NOISE_SOURCE_CAPTURE,\r
1698     NOISE_SOURCE_CLIPBOARD,\r
1699     NOISE_SOURCE_QUEUE,\r
1700     NOISE_SOURCE_CURSORPOS,\r
1701     NOISE_SOURCE_THREADTIME,\r
1702     NOISE_SOURCE_PROCTIME,\r
1703     NOISE_SOURCE_PERFCOUNT,\r
1704     NOISE_MAX_SOURCES\r
1705 } NoiseSourceId;\r
1706 void noise_get_heavy(void (*func) (void *, int));\r
1707 void noise_get_light(void (*func) (void *, int));\r
1708 void noise_regular(void);\r
1709 void noise_ultralight(NoiseSourceId id, unsigned long data);\r
1710 void random_save_seed(void);\r
1711 void random_destroy_seed(void);\r
1713 /*\r
1714  * Exports from settings.c.\r
1715  *\r
1716  * load_settings() and do_defaults() return false if the provided\r
1717  * session name didn't actually exist. But they still fill in the\r
1718  * provided Conf with _something_.\r
1719  */\r
1720 const struct BackendVtable *backend_vt_from_name(const char *name);\r
1721 const struct BackendVtable *backend_vt_from_proto(int proto);\r
1722 char *get_remote_username(Conf *conf); /* dynamically allocated */\r
1723 char *save_settings(const char *section, Conf *conf);\r
1724 void save_open_settings(settings_w *sesskey, Conf *conf);\r
1725 bool load_settings(const char *section, Conf *conf);\r
1726 void load_open_settings(settings_r *sesskey, Conf *conf);\r
1727 void get_sesslist(struct sesslist *, bool allocate);\r
1728 bool do_defaults(const char *, Conf *);\r
1729 void registry_cleanup(void);\r
1730 void settings_set_default_protocol(int);\r
1731 void settings_set_default_port(int);\r
1733 /*\r
1734  * Functions used by settings.c to provide platform-specific\r
1735  * default settings.\r
1736  *\r
1737  * (The integer one is expected to return `def' if it has no clear\r
1738  * opinion of its own. This is because there's no integer value\r
1739  * which I can reliably set aside to indicate `nil'. The string\r
1740  * function is perfectly all right returning NULL, of course. The\r
1741  * Filename and FontSpec functions are _not allowed_ to fail to\r
1742  * return, since these defaults _must_ be per-platform.)\r
1743  *\r
1744  * The 'Filename *' returned by platform_default_filename, and the\r
1745  * 'FontSpec *' returned by platform_default_fontspec, have ownership\r
1746  * transferred to the caller, and must be freed.\r
1747  */\r
1748 char *platform_default_s(const char *name);\r
1749 bool platform_default_b(const char *name, bool def);\r
1750 int platform_default_i(const char *name, int def);\r
1751 Filename *platform_default_filename(const char *name);\r
1752 FontSpec *platform_default_fontspec(const char *name);\r
1754 /*\r
1755  * Exports from terminal.c.\r
1756  */\r
1758 Terminal *term_init(Conf *, struct unicode_data *, TermWin *);\r
1759 void term_free(Terminal *);\r
1760 void term_size(Terminal *, int, int, int);\r
1761 void term_paint(Terminal *, int, int, int, int, bool);\r
1762 void term_scroll(Terminal *, int, int);\r
1763 void term_scroll_to_selection(Terminal *, int);\r
1764 void term_pwron(Terminal *, bool);\r
1765 void term_clrsb(Terminal *);\r
1766 void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action,\r
1767                 int, int, bool, bool, bool);\r
1768 void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int,\r
1769               unsigned int);\r
1770 void term_lost_clipboard_ownership(Terminal *, int clipboard);\r
1771 void term_update(Terminal *);\r
1772 void term_invalidate(Terminal *);\r
1773 void term_blink(Terminal *, bool set_cursor);\r
1774 void term_do_paste(Terminal *, const wchar_t *, int);\r
1775 void term_nopaste(Terminal *);\r
1776 void term_copyall(Terminal *, const int *, int);\r
1777 void term_pre_reconfig(Terminal *, Conf *);\r
1778 void term_reconfig(Terminal *, Conf *);\r
1779 void term_request_copy(Terminal *, const int *clipboards, int n_clipboards);\r
1780 void term_request_paste(Terminal *, int clipboard);\r
1781 void term_seen_key_event(Terminal *);\r
1782 size_t term_data(Terminal *, bool is_stderr, const void *data, size_t len);\r
1783 void term_provide_backend(Terminal *term, Backend *backend);\r
1784 void term_provide_logctx(Terminal *term, LogContext *logctx);\r
1785 void term_set_focus(Terminal *term, bool has_focus);\r
1786 char *term_get_ttymode(Terminal *term, const char *mode);\r
1787 int term_get_userpass_input(Terminal *term, prompts_t *p, bufchain *input);\r
1788 void term_set_trust_status(Terminal *term, bool trusted);\r
1789 void term_keyinput(Terminal *, int codepage, const void *buf, int len);\r
1790 void term_keyinputw(Terminal *, const wchar_t * widebuf, int len);\r
1791 void term_get_cursor_position(Terminal *term, int *x, int *y);\r
1792 void term_setup_window_titles(Terminal *term, const char *title_hostname);\r
1793 void term_notify_minimised(Terminal *term, bool minimised);\r
1794 void term_notify_palette_changed(Terminal *term);\r
1795 void term_notify_window_pos(Terminal *term, int x, int y);\r
1796 void term_notify_window_size_pixels(Terminal *term, int x, int y);\r
1797 void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb);\r
1799 typedef enum SmallKeypadKey {\r
1800     SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN,\r
1801 } SmallKeypadKey;\r
1802 int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl);\r
1803 int format_function_key(char *buf, Terminal *term, int key_number,\r
1804                         bool shift, bool ctrl);\r
1805 int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key);\r
1806 int format_numeric_keypad_key(char *buf, Terminal *term, char key,\r
1807                               bool shift, bool ctrl);\r
1809 /*\r
1810  * Exports from logging.c.\r
1811  */\r
1812 struct LogPolicyVtable {\r
1813     /*\r
1814      * Pass Event Log entries on from LogContext to the front end,\r
1815      * which might write them to standard error or save them for a GUI\r
1816      * list box or other things.\r
1817      */\r
1818     void (*eventlog)(LogPolicy *lp, const char *event);\r
1820     /*\r
1821      * Ask what to do about the specified output log file already\r
1822      * existing. Can return four values:\r
1823      *\r
1824      *  - 2 means overwrite the log file\r
1825      *  - 1 means append to the log file\r
1826      *  - 0 means cancel logging for this session\r
1827      *  - -1 means please wait, and callback() will be called with one\r
1828      *    of those options.\r
1829      */\r
1830     int (*askappend)(LogPolicy *lp, Filename *filename,\r
1831                      void (*callback)(void *ctx, int result), void *ctx);\r
1833     /*\r
1834      * Emergency logging when the log file itself can't be opened,\r
1835      * which typically means we want to shout about it more loudly\r
1836      * than a mere Event Log entry.\r
1837      *\r
1838      * One reasonable option is to send it to the same place that\r
1839      * stderr output from the main session goes (so, either a console\r
1840      * tool's actual stderr, or a terminal window). In many cases this\r
1841      * is unlikely to cause this error message to turn up\r
1842      * embarrassingly in a log file of real server output, because the\r
1843      * whole point is that we haven't managed to open any such log\r
1844      * file :-)\r
1845      */\r
1846     void (*logging_error)(LogPolicy *lp, const char *event);\r
1848     /*\r
1849      * Ask whether extra verbose log messages are required.\r
1850      */\r
1851     bool (*verbose)(LogPolicy *lp);\r
1852 };\r
1853 struct LogPolicy {\r
1854     const LogPolicyVtable *vt;\r
1855 };\r
1857 static inline void lp_eventlog(LogPolicy *lp, const char *event)\r
1858 { lp->vt->eventlog(lp, event); }\r
1859 static inline int lp_askappend(\r
1860     LogPolicy *lp, Filename *filename,\r
1861     void (*callback)(void *ctx, int result), void *ctx)\r
1862 { return lp->vt->askappend(lp, filename, callback, ctx); }\r
1863 static inline void lp_logging_error(LogPolicy *lp, const char *event)\r
1864 { lp->vt->logging_error(lp, event); }\r
1865 static inline bool lp_verbose(LogPolicy *lp)\r
1866 { return lp->vt->verbose(lp); }\r
1868 /* Defined in conscli.c, used in several console command-line tools */\r
1869 extern LogPolicy console_cli_logpolicy[];\r
1871 int console_askappend(LogPolicy *lp, Filename *filename,\r
1872                       void (*callback)(void *ctx, int result), void *ctx);\r
1873 void console_logging_error(LogPolicy *lp, const char *string);\r
1874 void console_eventlog(LogPolicy *lp, const char *string);\r
1875 bool null_lp_verbose_yes(LogPolicy *lp);\r
1876 bool null_lp_verbose_no(LogPolicy *lp);\r
1877 bool cmdline_lp_verbose(LogPolicy *lp);\r
1879 LogContext *log_init(LogPolicy *lp, Conf *conf);\r
1880 void log_free(LogContext *logctx);\r
1881 void log_reconfig(LogContext *logctx, Conf *conf);\r
1882 void logfopen(LogContext *logctx);\r
1883 void logfclose(LogContext *logctx);\r
1884 void logtraffic(LogContext *logctx, unsigned char c, int logmode);\r
1885 void logflush(LogContext *logctx);\r
1886 void logevent(LogContext *logctx, const char *event);\r
1887 void logeventf(LogContext *logctx, const char *fmt, ...) PRINTF_LIKE(2, 3);\r
1888 void logeventvf(LogContext *logctx, const char *fmt, va_list ap);\r
1890 /*\r
1891  * Pass a dynamically allocated string to logevent and immediately\r
1892  * free it. Intended for use by wrapper macros which pass the return\r
1893  * value of dupprintf straight to this.\r
1894  */\r
1895 void logevent_and_free(LogContext *logctx, char *event);\r
1896 enum { PKT_INCOMING, PKT_OUTGOING };\r
1897 enum { PKTLOG_EMIT, PKTLOG_BLANK, PKTLOG_OMIT };\r
1898 struct logblank_t {\r
1899     int offset;\r
1900     int len;\r
1901     int type;\r
1902 };\r
1903 void log_packet(LogContext *logctx, int direction, int type,\r
1904                 const char *texttype, const void *data, size_t len,\r
1905                 int n_blanks, const struct logblank_t *blanks,\r
1906                 const unsigned long *sequence,\r
1907                 unsigned downstream_id, const char *additional_log_text);\r
1909 /*\r
1910  * Exports from testback.c\r
1911  */\r
1913 extern const struct BackendVtable null_backend;\r
1914 extern const struct BackendVtable loop_backend;\r
1916 /*\r
1917  * Exports from raw.c.\r
1918  */\r
1920 extern const struct BackendVtable raw_backend;\r
1922 /*\r
1923  * Exports from rlogin.c.\r
1924  */\r
1926 extern const struct BackendVtable rlogin_backend;\r
1928 /*\r
1929  * Exports from telnet.c.\r
1930  */\r
1932 extern const struct BackendVtable telnet_backend;\r
1934 /*\r
1935  * Exports from ssh.c.\r
1936  */\r
1937 extern const struct BackendVtable ssh_backend;\r
1938 extern const struct BackendVtable sshconn_backend;\r
1940 /*\r
1941  * Exports from supdup.c.\r
1942  */\r
1943 extern const struct BackendVtable supdup_backend;\r
1945 /*\r
1946  * Exports from ldisc.c.\r
1947  */\r
1948 Ldisc *ldisc_create(Conf *, Terminal *, Backend *, Seat *);\r
1949 void ldisc_configure(Ldisc *, Conf *);\r
1950 void ldisc_free(Ldisc *);\r
1951 void ldisc_send(Ldisc *, const void *buf, int len, bool interactive);\r
1952 void ldisc_echoedit_update(Ldisc *);\r
1954 /*\r
1955  * Exports from sshrand.c.\r
1956  */\r
1958 void random_add_noise(NoiseSourceId source, const void *noise, int length);\r
1959 void random_read(void *buf, size_t size);\r
1960 void random_get_savedata(void **data, int *len);\r
1961 extern int random_active;\r
1962 /* The random number subsystem is activated if at least one other entity\r
1963  * within the program expresses an interest in it. So each SSH session\r
1964  * calls random_ref on startup and random_unref on shutdown. */\r
1965 void random_ref(void);\r
1966 void random_unref(void);\r
1967 /* random_clear is equivalent to calling random_unref as many times as\r
1968  * necessary to shut down the global PRNG instance completely. It's\r
1969  * not needed in normal applications, but the command-line PuTTYgen\r
1970  * test finds it useful to clean up after each invocation of the\r
1971  * logical main() no matter whether it needed random numbers or\r
1972  * not. */\r
1973 void random_clear(void);\r
1974 /* random_setup_custom sets up the process-global random number\r
1975  * generator specially, with a hash function of your choice. */\r
1976 void random_setup_custom(const ssh_hashalg *hash);\r
1977 /* random_setup_special() is a macro wrapper on that, which makes an\r
1978  * extra-big one based on the largest hash function we have. It's\r
1979  * defined this way to avoid what would otherwise be an unnecessary\r
1980  * module dependency from sshrand.c to a hash function implementation. */\r
1981 #define random_setup_special() random_setup_custom(&ssh_shake256_114bytes)\r
1982 /* Manually drop a random seed into the random number generator, e.g.\r
1983  * just before generating a key. */\r
1984 void random_reseed(ptrlen seed);\r
1985 /* Limit on how much entropy is worth putting into the generator (bits). */\r
1986 size_t random_seed_bits(void);\r
1988 /*\r
1989  * Exports from pinger.c.\r
1990  */\r
1991 typedef struct Pinger Pinger;\r
1992 Pinger *pinger_new(Conf *conf, Backend *backend);\r
1993 void pinger_reconfig(Pinger *, Conf *oldconf, Conf *newconf);\r
1994 void pinger_free(Pinger *);\r
1996 /*\r
1997  * Exports from misc.c.\r
1998  */\r
2000 #include "misc.h"\r
2001 bool conf_launchable(Conf *conf);\r
2002 char const *conf_dest(Conf *conf);\r
2004 /*\r
2005  * Exports from sessprep.c.\r
2006  */\r
2007 void prepare_session(Conf *conf);\r
2009 /*\r
2010  * Exports from sercfg.c.\r
2011  */\r
2012 void ser_setup_config_box(struct controlbox *b, bool midsession,\r
2013                           int parity_mask, int flow_mask);\r
2015 /*\r
2016  * Exports from version.c.\r
2017  */\r
2018 extern const char ver[];\r
2019 extern const char commitid[];\r
2021 /*\r
2022  * Exports from unicode.c.\r
2023  */\r
2024 #ifndef CP_UTF8\r
2025 #define CP_UTF8 65001\r
2026 #endif\r
2027 /* void init_ucs(void); -- this is now in platform-specific headers */\r
2028 bool is_dbcs_leadbyte(int codepage, char byte);\r
2029 int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,\r
2030              wchar_t *wcstr, int wclen);\r
2031 int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,\r
2032              char *mbstr, int mblen, const char *defchr,\r
2033              struct unicode_data *ucsdata);\r
2034 wchar_t xlat_uskbd2cyrllic(int ch);\r
2035 int check_compose(int first, int second);\r
2036 int decode_codepage(char *cp_name);\r
2037 const char *cp_enumerate (int index);\r
2038 const char *cp_name(int codepage);\r
2039 void get_unitab(int codepage, wchar_t * unitab, int ftype);\r
2041 /*\r
2042  * Exports from wcwidth.c\r
2043  */\r
2044 int mk_wcwidth(unsigned int ucs);\r
2045 int mk_wcswidth(const unsigned int *pwcs, size_t n);\r
2046 int mk_wcwidth_cjk(unsigned int ucs);\r
2047 int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n);\r
2049 /*\r
2050  * Exports from pageantc.c.\r
2051  *\r
2052  * agent_query returns NULL for here's-a-response, and non-NULL for\r
2053  * query-in- progress. In the latter case there will be a call to\r
2054  * `callback' at some future point, passing callback_ctx as the first\r
2055  * parameter and the actual reply data as the second and third.\r
2056  *\r
2057  * The response may be a NULL pointer (in either of the synchronous\r
2058  * or asynchronous cases), which indicates failure to receive a\r
2059  * response.\r
2060  *\r
2061  * When the return from agent_query is not NULL, it identifies the\r
2062  * in-progress query in case it needs to be cancelled. If\r
2063  * agent_cancel_query is called, then the pending query is destroyed\r
2064  * and the callback will not be called. (E.g. if you're going to throw\r
2065  * away the thing you were using as callback_ctx.)\r
2066  *\r
2067  * Passing a null pointer as callback forces agent_query to behave\r
2068  * synchronously, i.e. it will block if necessary, and guarantee to\r
2069  * return NULL. The wrapper function agent_query_synchronous() makes\r
2070  * this easier.\r
2071  */\r
2072 typedef struct agent_pending_query agent_pending_query;\r
2073 agent_pending_query *agent_query(\r
2074     strbuf *in, void **out, int *outlen,\r
2075     void (*callback)(void *, void *, int), void *callback_ctx);\r
2076 void agent_cancel_query(agent_pending_query *);\r
2077 void agent_query_synchronous(strbuf *in, void **out, int *outlen);\r
2078 bool agent_exists(void);\r
2080 /* For stream-oriented agent connections, if available. */\r
2081 Socket *agent_connect(Plug *plug);\r
2083 /*\r
2084  * Exports from wildcard.c\r
2085  */\r
2086 const char *wc_error(int value);\r
2087 int wc_match_pl(const char *wildcard, ptrlen target);\r
2088 int wc_match(const char *wildcard, const char *target);\r
2089 bool wc_unescape(char *output, const char *wildcard);\r
2091 /*\r
2092  * Exports from frontend (windlg.c etc)\r
2093  */\r
2094 void pgp_fingerprints(void);\r
2095 /*\r
2096  * have_ssh_host_key() just returns true if a key of that type is\r
2097  * already cached and false otherwise.\r
2098  */\r
2099 bool have_ssh_host_key(const char *host, int port, const char *keytype);\r
2101 /*\r
2102  * Exports from console frontends (wincons.c, uxcons.c)\r
2103  * that aren't equivalents to things in windlg.c et al.\r
2104  */\r
2105 extern bool console_batch_mode, console_antispoof_prompt;\r
2106 int console_get_userpass_input(prompts_t *p);\r
2107 bool is_interactive(void);\r
2108 void console_print_error_msg(const char *prefix, const char *msg);\r
2109 void console_print_error_msg_fmt_v(\r
2110     const char *prefix, const char *fmt, va_list ap);\r
2111 void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...)\r
2112     PRINTF_LIKE(2, 3);\r
2114 /*\r
2115  * Exports from printing.c.\r
2116  */\r
2117 typedef struct printer_enum_tag printer_enum;\r
2118 typedef struct printer_job_tag printer_job;\r
2119 printer_enum *printer_start_enum(int *nprinters);\r
2120 char *printer_get_name(printer_enum *, int);\r
2121 void printer_finish_enum(printer_enum *);\r
2122 printer_job *printer_start_job(char *printer);\r
2123 void printer_job_data(printer_job *, const void *, size_t);\r
2124 void printer_finish_job(printer_job *);\r
2126 /*\r
2127  * Exports from cmdline.c (and also cmdline_error(), which is\r
2128  * defined differently in various places and required _by_\r
2129  * cmdline.c).\r
2130  *\r
2131  * Note that cmdline_process_param takes a const option string, but a\r
2132  * writable argument string. That's not a mistake - that's so it can\r
2133  * zero out password arguments in the hope of not having them show up\r
2134  * avoidably in Unix 'ps'.\r
2135  */\r
2136 int cmdline_process_param(const char *, char *, int, Conf *, bool ignoreFurtherParameters);\r
2137 void cmdline_run_saved(Conf *);\r
2138 void cmdline_cleanup(void);\r
2139 int cmdline_get_passwd_input(prompts_t *p);\r
2140 bool cmdline_host_ok(Conf *);\r
2141 bool cmdline_verbose(void);\r
2142 bool cmdline_loaded_session(void);\r
2144 /*\r
2145  * Here we have a flags word provided by each tool, which describes\r
2146  * the capabilities of that tool that cmdline.c needs to know about.\r
2147  * It will refuse certain command-line options if a particular tool\r
2148  * inherently can't do anything sensible. For example, the file\r
2149  * transfer tools (psftp, pscp) can't do a great deal with protocol\r
2150  * selections (ever tried running scp over telnet?) or with port\r
2151  * forwarding (even if it wasn't a hideously bad idea, they don't have\r
2152  * the select/poll infrastructure to make them work).\r
2153  */\r
2154 extern const unsigned cmdline_tooltype;\r
2156 /* Bit flags for the above */\r
2157 #define TOOLTYPE_LIST(X)                        \\r
2158     X(TOOLTYPE_FILETRANSFER)                    \\r
2159     X(TOOLTYPE_NONNETWORK)                      \\r
2160     X(TOOLTYPE_HOST_ARG)                        \\r
2161     X(TOOLTYPE_HOST_ARG_CAN_BE_SESSION)         \\r
2162     X(TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX)        \\r
2163     X(TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD)   \\r
2164     X(TOOLTYPE_PORT_ARG)                        \\r
2165     X(TOOLTYPE_NO_VERBOSE_OPTION)               \\r
2166     /* end of list */\r
2167 #define BITFLAG_INDEX(val) val ## _bitflag_index,\r
2168 enum { TOOLTYPE_LIST(BITFLAG_INDEX) };\r
2169 #define BITFLAG_DEF(val) val = 1U << (val ## _bitflag_index),\r
2170 enum { TOOLTYPE_LIST(BITFLAG_DEF) };\r
2172 void cmdline_error(const char *, ...) PRINTF_LIKE(1, 2);\r
2174 /*\r
2175  * Exports from config.c.\r
2176  */\r
2177 struct controlbox;\r
2178 union control;\r
2179 void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg,\r
2180                               void *data, int event);\r
2181 #define CHECKBOX_INVERT (1<<30)\r
2182 void conf_checkbox_handler(union control *ctrl, dlgparam *dlg,\r
2183                            void *data, int event);\r
2184 void conf_editbox_handler(union control *ctrl, dlgparam *dlg,\r
2185                           void *data, int event);\r
2186 void conf_filesel_handler(union control *ctrl, dlgparam *dlg,\r
2187                           void *data, int event);\r
2188 void conf_fontsel_handler(union control *ctrl, dlgparam *dlg,\r
2189                           void *data, int event);\r
2191 void setup_config_box(struct controlbox *b, bool midsession,\r
2192                       int protocol, int protcfginfo);\r
2194 /*\r
2195  * Exports from minibidi.c.\r
2196  */\r
2197 #define BIDI_CHAR_INDEX_NONE ((unsigned short)-1)\r
2198 typedef struct bidi_char {\r
2199     unsigned int origwc, wc;\r
2200     unsigned short index, nchars;\r
2201 } bidi_char;\r
2202 int do_bidi(bidi_char *line, int count);\r
2203 int do_shape(bidi_char *line, bidi_char *to, int count);\r
2204 bool is_rtl(int c);\r
2206 /*\r
2207  * X11 auth mechanisms we know about.\r
2208  */\r
2209 enum {\r
2210     X11_NO_AUTH,\r
2211     X11_MIT,                           /* MIT-MAGIC-COOKIE-1 */\r
2212     X11_XDM,                           /* XDM-AUTHORIZATION-1 */\r
2213     X11_NAUTHS\r
2214 };\r
2215 extern const char *const x11_authnames[];  /* declared in x11fwd.c */\r
2217 /*\r
2218  * An enum for the copy-paste UI action configuration.\r
2219  */\r
2220 enum {\r
2221     CLIPUI_NONE,     /* UI action has no copy/paste effect */\r
2222     CLIPUI_IMPLICIT, /* use the default clipboard implicit in mouse actions  */\r
2223     CLIPUI_EXPLICIT, /* use the default clipboard for explicit Copy/Paste */\r
2224     CLIPUI_CUSTOM,   /* use a named clipboard (on systems that support it) */\r
2225 };\r
2227 /*\r
2228  * Miscellaneous exports from the platform-specific code.\r
2229  *\r
2230  * filename_serialise and filename_deserialise have the same semantics\r
2231  * as fontspec_serialise and fontspec_deserialise above.\r
2232  */\r
2233 Filename *filename_from_str(const char *string);\r
2234 const char *filename_to_str(const Filename *fn);\r
2235 bool filename_equal(const Filename *f1, const Filename *f2);\r
2236 bool filename_is_null(const Filename *fn);\r
2237 Filename *filename_copy(const Filename *fn);\r
2238 void filename_free(Filename *fn);\r
2239 void filename_serialise(BinarySink *bs, const Filename *f);\r
2240 Filename *filename_deserialise(BinarySource *src);\r
2241 char *get_username(void);              /* return value needs freeing */\r
2242 char *get_random_data(int bytes, const char *device); /* used in cmdgen.c */\r
2243 char filename_char_sanitise(char c);   /* rewrite special pathname chars */\r
2244 bool open_for_write_would_lose_data(const Filename *fn);\r
2246 /*\r
2247  * Exports and imports from timing.c.\r
2248  *\r
2249  * schedule_timer() asks the front end to schedule a callback to a\r
2250  * timer function in a given number of ticks. The returned value is\r
2251  * the time (in ticks since an arbitrary offset) at which the\r
2252  * callback can be expected. This value will also be passed as the\r
2253  * `now' parameter to the callback function. Hence, you can (for\r
2254  * example) schedule an event at a particular time by calling\r
2255  * schedule_timer() and storing the return value in your context\r
2256  * structure as the time when that event is due. The first time a\r
2257  * callback function gives you that value or more as `now', you do\r
2258  * the thing.\r
2259  *\r
2260  * expire_timer_context() drops all current timers associated with\r
2261  * a given value of ctx (for when you're about to free ctx).\r
2262  *\r
2263  * run_timers() is called from the front end when it has reason to\r
2264  * think some timers have reached their moment, or when it simply\r
2265  * needs to know how long to wait next. We pass it the time we\r
2266  * think it is. It returns true and places the time when the next\r
2267  * timer needs to go off in `next', or alternatively it returns\r
2268  * false if there are no timers at all pending.\r
2269  *\r
2270  * timer_change_notify() must be supplied by the front end; it\r
2271  * notifies the front end that a new timer has been added to the\r
2272  * list which is sooner than any existing ones. It provides the\r
2273  * time when that timer needs to go off.\r
2274  *\r
2275  * *** FRONT END IMPLEMENTORS NOTE:\r
2276  *\r
2277  * There's an important subtlety in the front-end implementation of\r
2278  * the timer interface. When a front end is given a `next' value,\r
2279  * either returned from run_timers() or via timer_change_notify(),\r
2280  * it should ensure that it really passes _that value_ as the `now'\r
2281  * parameter to its next run_timers call. It should _not_ simply\r
2282  * call GETTICKCOUNT() to get the `now' parameter when invoking\r
2283  * run_timers().\r
2284  *\r
2285  * The reason for this is that an OS's system clock might not agree\r
2286  * exactly with the timing mechanisms it supplies to wait for a\r
2287  * given interval. I'll illustrate this by the simple example of\r
2288  * Unix Plink, which uses timeouts to poll() in a way which for\r
2289  * these purposes can simply be considered to be a wait() function.\r
2290  * Suppose, for the sake of argument, that this wait() function\r
2291  * tends to return early by 1%. Then a possible sequence of actions\r
2292  * is:\r
2293  *\r
2294  *  - run_timers() tells the front end that the next timer firing\r
2295  *    is 10000ms from now.\r
2296  *  - Front end calls wait(10000ms), but according to\r
2297  *    GETTICKCOUNT() it has only waited for 9900ms.\r
2298  *  - Front end calls run_timers() again, passing time T-100ms as\r
2299  *    `now'.\r
2300  *  - run_timers() does nothing, and says the next timer firing is\r
2301  *    still 100ms from now.\r
2302  *  - Front end calls wait(100ms), which only waits for 99ms.\r
2303  *  - Front end calls run_timers() yet again, passing time T-1ms.\r
2304  *  - run_timers() says there's still 1ms to wait.\r
2305  *  - Front end calls wait(1ms).\r
2306  *\r
2307  * If you're _lucky_ at this point, wait(1ms) will actually wait\r
2308  * for 1ms and you'll only have woken the program up three times.\r
2309  * If you're unlucky, wait(1ms) might do nothing at all due to\r
2310  * being below some minimum threshold, and you might find your\r
2311  * program spends the whole of the last millisecond tight-looping\r
2312  * between wait() and run_timers().\r
2313  *\r
2314  * Instead, what you should do is to _save_ the precise `next'\r
2315  * value provided by run_timers() or via timer_change_notify(), and\r
2316  * use that precise value as the input to the next run_timers()\r
2317  * call. So:\r
2318  *\r
2319  *  - run_timers() tells the front end that the next timer firing\r
2320  *    is at time T, 10000ms from now.\r
2321  *  - Front end calls wait(10000ms).\r
2322  *  - Front end then immediately calls run_timers() and passes it\r
2323  *    time T, without stopping to check GETTICKCOUNT() at all.\r
2324  *\r
2325  * This guarantees that the program wakes up only as many times as\r
2326  * there are actual timer actions to be taken, and that the timing\r
2327  * mechanism will never send it into a tight loop.\r
2328  *\r
2329  * (It does also mean that the timer action in the above example\r
2330  * will occur 100ms early, but this is not generally critical. And\r
2331  * the hypothetical 1% error in wait() will be partially corrected\r
2332  * for anyway when, _after_ run_timers() returns, you call\r
2333  * GETTICKCOUNT() and compare the result with the returned `next'\r
2334  * value to find out how long you have to make your next wait().)\r
2335  */\r
2336 typedef void (*timer_fn_t)(void *ctx, unsigned long now);\r
2337 unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx);\r
2338 void expire_timer_context(void *ctx);\r
2339 bool run_timers(unsigned long now, unsigned long *next);\r
2340 void timer_change_notify(unsigned long next);\r
2341 unsigned long timing_last_clock(void);\r
2343 /*\r
2344  * Exports from callback.c.\r
2345  *\r
2346  * This provides a method of queuing function calls to be run at the\r
2347  * earliest convenience from the top-level event loop. Use it if\r
2348  * you're deep in a nested chain of calls and want to trigger an\r
2349  * action which will probably lead to your function being re-entered\r
2350  * recursively if you just call the initiating function the normal\r
2351  * way.\r
2352  *\r
2353  * Most front ends run the queued callbacks by simply calling\r
2354  * run_toplevel_callbacks() after handling each event in their\r
2355  * top-level event loop. However, if a front end doesn't have control\r
2356  * over its own event loop (e.g. because it's using GTK) then it can\r
2357  * instead request notifications when a callback is available, so that\r
2358  * it knows to ask its delegate event loop to do the same thing. Also,\r
2359  * if a front end needs to know whether a callback is pending without\r
2360  * actually running it (e.g. so as to put a zero timeout on a poll()\r
2361  * call) then it can call toplevel_callback_pending(), which will\r
2362  * return true if at least one callback is in the queue.\r
2363  *\r
2364  * run_toplevel_callbacks() returns true if it ran any actual code.\r
2365  * This can be used as a means of speculatively terminating a poll\r
2366  * loop, as in PSFTP, for example - if a callback has run then perhaps\r
2367  * it might have done whatever the loop's caller was waiting for.\r
2368  */\r
2369 typedef void (*toplevel_callback_fn_t)(void *ctx);\r
2370 void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx);\r
2371 bool run_toplevel_callbacks(void);\r
2372 bool toplevel_callback_pending(void);\r
2373 void delete_callbacks_for_context(void *ctx);\r
2375 /*\r
2376  * Another facility in callback.c deals with 'idempotent' callbacks,\r
2377  * defined as those which never need to be scheduled again if they are\r
2378  * already scheduled and have not yet run. (An example would be one\r
2379  * which, when called, empties a queue of data completely: when data\r
2380  * is added to the queue, you must ensure a run of the queue-consuming\r
2381  * function has been scheduled, but if one is already pending, you\r
2382  * don't need to schedule a second one.)\r
2383  */\r
2384 struct IdempotentCallback {\r
2385     toplevel_callback_fn_t fn;\r
2386     void *ctx;\r
2387     bool queued;\r
2388 };\r
2389 void queue_idempotent_callback(struct IdempotentCallback *ic);\r
2391 typedef void (*toplevel_callback_notify_fn_t)(void *ctx);\r
2392 void request_callback_notifications(toplevel_callback_notify_fn_t notify,\r
2393                                     void *ctx);\r
2395 /*\r
2396  * Define no-op macros for the jump list functions, on platforms that\r
2397  * don't support them. (This is a bit of a hack, and it'd be nicer to\r
2398  * localise even the calls to those functions into the Windows front\r
2399  * end, but it'll do for the moment.)\r
2400  */\r
2401 #ifndef JUMPLIST_SUPPORTED\r
2402 #define add_session_to_jumplist(x) ((void)0)\r
2403 #define remove_session_from_jumplist(x) ((void)0)\r
2404 #endif\r
2406 /* SURROGATE PAIR */\r
2407 #ifndef HIGH_SURROGATE_START /* in some toolchains <winnls.h> defines these */\r
2408 #define HIGH_SURROGATE_START 0xd800\r
2409 #define HIGH_SURROGATE_END 0xdbff\r
2410 #define LOW_SURROGATE_START 0xdc00\r
2411 #define LOW_SURROGATE_END 0xdfff\r
2412 #endif\r
2414 /* These macros exist in the Windows API, so the environment may\r
2415  * provide them. If not, define them in terms of the above. */\r
2416 #ifndef IS_HIGH_SURROGATE\r
2417 #define IS_HIGH_SURROGATE(wch) (((wch) >= HIGH_SURROGATE_START) && \\r
2418                                 ((wch) <= HIGH_SURROGATE_END))\r
2419 #define IS_LOW_SURROGATE(wch) (((wch) >= LOW_SURROGATE_START) && \\r
2420                                ((wch) <= LOW_SURROGATE_END))\r
2421 #define IS_SURROGATE_PAIR(hs, ls) (IS_HIGH_SURROGATE(hs) && \\r
2422                                    IS_LOW_SURROGATE(ls))\r
2423 #endif\r
2426 #define IS_SURROGATE(wch) (((wch) >= HIGH_SURROGATE_START) &&   \\r
2427                            ((wch) <= LOW_SURROGATE_END))\r
2428 #define HIGH_SURROGATE_OF(codept) \\r
2429     (HIGH_SURROGATE_START + (((codept) - 0x10000) >> 10))\r
2430 #define LOW_SURROGATE_OF(codept) \\r
2431     (LOW_SURROGATE_START + (((codept) - 0x10000) & 0x3FF))\r
2432 #define FROM_SURROGATES(wch1, wch2) \\r
2433     (0x10000 + (((wch1) & 0x3FF) << 10) + ((wch2) & 0x3FF))\r
2435 #endif\r