Upgrade libgit2
[TortoiseGit.git] / src / TortoisePlink / PUTTY.H
blob1542af57cb0c562c11cb10d0ff48bfd6afdeaec4
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 "platform.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 "2023"\r
25 #define PGP_MASTER_KEY_DETAILS "RSA, 4096-bit"\r
26 #define PGP_MASTER_KEY_FP                                  \\r
27     "28D4 7C46 55E7 65A6 D827  AC66 B15D 9EFC 216B 06A1"\r
28 #define PGP_PREV_MASTER_KEY_YEAR "2021"\r
29 #define PGP_PREV_MASTER_KEY_DETAILS "RSA, 3072-bit"\r
30 #define PGP_PREV_MASTER_KEY_FP                                  \\r
31     "A872 D42F 1660 890F 0E05  223E DD43 55EA AC11 19DE"\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     bool dbcs_screenfont;\r
270     int font_codepage;\r
271     int line_codepage;\r
272     wchar_t unitab_scoacs[256];\r
273     wchar_t unitab_line[256];\r
274     wchar_t unitab_font[256];\r
275     wchar_t unitab_xterm[256];\r
276     wchar_t unitab_oemcp[256];\r
277     unsigned char unitab_ctrl[256];\r
278 };\r
280 #define LGXF_OVR  1                    /* existing logfile overwrite */\r
281 #define LGXF_APN  0                    /* existing logfile append */\r
282 #define LGXF_ASK -1                    /* existing logfile ask */\r
283 #define LGTYP_NONE  0                  /* logmode: no logging */\r
284 #define LGTYP_ASCII 1                  /* logmode: pure ascii */\r
285 #define LGTYP_DEBUG 2                  /* logmode: all chars of traffic */\r
286 #define LGTYP_PACKETS 3                /* logmode: SSH data packets */\r
287 #define LGTYP_SSHRAW 4                 /* logmode: SSH raw data */\r
289 /*\r
290  * Enumeration of 'special commands' that can be sent during a\r
291  * session, separately from the byte stream of ordinary session data.\r
292  */\r
293 typedef enum {\r
294     /*\r
295      * Commands that are generally useful in multiple backends.\r
296      */\r
297     SS_BRK,    /* serial-line break */\r
298     SS_EOF,    /* end-of-file on session input */\r
299     SS_NOP,    /* transmit data with no effect */\r
300     SS_PING,   /* try to keep the session alive (probably, but not\r
301                 * necessarily, implemented as SS_NOP) */\r
303     /*\r
304      * Commands specific to Telnet.\r
305      */\r
306     SS_AYT,    /* Are You There */\r
307     SS_SYNCH,  /* Synch */\r
308     SS_EC,     /* Erase Character */\r
309     SS_EL,     /* Erase Line */\r
310     SS_GA,     /* Go Ahead */\r
311     SS_ABORT,  /* Abort Process */\r
312     SS_AO,     /* Abort Output */\r
313     SS_IP,     /* Interrupt Process */\r
314     SS_SUSP,   /* Suspend Process */\r
315     SS_EOR,    /* End Of Record */\r
316     SS_EOL,    /* Telnet end-of-line sequence (CRLF, as opposed to CR\r
317                 * NUL that escapes a literal CR) */\r
319     /*\r
320      * Commands specific to SSH.\r
321      */\r
322     SS_REKEY,  /* trigger an immediate repeat key exchange */\r
323     SS_XCERT,  /* cross-certify another host key ('arg' indicates which) */\r
325     /*\r
326      * Send a POSIX-style signal. (Useful in SSH and also pterm.)\r
327      *\r
328      * We use the master list in ssh/signal-list.h to define these enum\r
329      * values, which will come out looking like names of the form\r
330      * SS_SIGABRT, SS_SIGINT etc.\r
331      */\r
332     #define SIGNAL_MAIN(name, text) SS_SIG ## name,\r
333     #define SIGNAL_SUB(name) SS_SIG ## name,\r
334     #include "ssh/signal-list.h"\r
335     #undef SIGNAL_MAIN\r
336     #undef SIGNAL_SUB\r
338     /*\r
339      * These aren't really special commands, but they appear in the\r
340      * enumeration because the list returned from\r
341      * backend_get_specials() will use them to specify the structure\r
342      * of the GUI specials menu.\r
343      */\r
344     SS_SEP,         /* Separator */\r
345     SS_SUBMENU,     /* Start a new submenu with specified name */\r
346     SS_EXITMENU,    /* Exit current submenu, or end of entire specials list */\r
347 } SessionSpecialCode;\r
349 /*\r
350  * The structure type returned from backend_get_specials.\r
351  */\r
352 struct SessionSpecial {\r
353     const char *name;\r
354     SessionSpecialCode code;\r
355     int arg;\r
356 };\r
358 /* Needed by both ssh/channel.h and ssh/ppl.h */\r
359 typedef void (*add_special_fn_t)(\r
360     void *ctx, const char *text, SessionSpecialCode code, int arg);\r
362 typedef enum {\r
363     MBT_NOTHING,\r
364     MBT_LEFT, MBT_MIDDLE, MBT_RIGHT,   /* `raw' button designations */\r
365     MBT_SELECT, MBT_EXTEND, MBT_PASTE, /* `cooked' button designations */\r
366     MBT_WHEEL_UP, MBT_WHEEL_DOWN,      /* vertical mouse wheel */\r
367     MBT_WHEEL_LEFT, MBT_WHEEL_RIGHT    /* horizontal mouse wheel */\r
368 } Mouse_Button;\r
370 typedef enum {\r
371     MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE, MA_MOVE\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_DHGROUP15,\r
427     KEX_DHGROUP16,\r
428     KEX_DHGROUP17,\r
429     KEX_DHGROUP18,\r
430     KEX_DHGEX,\r
431     KEX_RSA,\r
432     KEX_ECDH,\r
433     KEX_NTRU_HYBRID,\r
434     KEX_MAX\r
435 };\r
437 enum {\r
438     /*\r
439      * SSH-2 host key algorithms\r
440      */\r
441     HK_WARN,\r
442     HK_RSA,\r
443     HK_DSA,\r
444     HK_ECDSA,\r
445     HK_ED25519,\r
446     HK_ED448,\r
447     HK_MAX\r
448 };\r
450 enum {\r
451     /*\r
452      * SSH ciphers (both SSH-1 and SSH-2)\r
453      */\r
454     CIPHER_WARN,                       /* pseudo 'cipher' */\r
455     CIPHER_3DES,\r
456     CIPHER_BLOWFISH,\r
457     CIPHER_AES,                        /* (SSH-2 only) */\r
458     CIPHER_DES,\r
459     CIPHER_ARCFOUR,\r
460     CIPHER_CHACHA20,\r
461     CIPHER_AESGCM,\r
462     CIPHER_MAX                         /* no. ciphers (inc warn) */\r
463 };\r
465 enum TriState {\r
466     /*\r
467      * Several different bits of the PuTTY configuration seem to be\r
468      * three-way settings whose values are `always yes', `always\r
469      * no', and `decide by some more complex automated means'. This\r
470      * is true of line discipline options (local echo and line\r
471      * editing), proxy DNS, proxy terminal logging, Close On Exit, and\r
472      * SSH server bug workarounds. Accordingly I supply a single enum\r
473      * here to deal with them all.\r
474      */\r
475     FORCE_ON, FORCE_OFF, AUTO\r
476 };\r
478 enum {\r
479     /*\r
480      * Proxy types.\r
481      */\r
482     PROXY_NONE, PROXY_SOCKS4, PROXY_SOCKS5,\r
483     PROXY_HTTP, PROXY_TELNET, PROXY_CMD, PROXY_SSH_TCPIP,\r
484     PROXY_SSH_EXEC, PROXY_SSH_SUBSYSTEM,\r
485     PROXY_FUZZ\r
486 };\r
488 enum {\r
489     /*\r
490      * Line discipline options which the backend might try to control.\r
491      */\r
492     LD_EDIT,                           /* local line editing */\r
493     LD_ECHO,                           /* local echo */\r
494     LD_N_OPTIONS\r
495 };\r
497 enum {\r
498     /* Actions on remote window title query */\r
499     TITLE_NONE, TITLE_EMPTY, TITLE_REAL\r
500 };\r
502 enum {\r
503     /* SUPDUP character set options */\r
504     SUPDUP_CHARSET_ASCII, SUPDUP_CHARSET_ITS, SUPDUP_CHARSET_WAITS\r
505 };\r
507 enum {\r
508     /* Protocol back ends. (CONF_protocol) */\r
509     PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH, PROT_SSHCONN,\r
510     /* PROT_SERIAL is supported on a subset of platforms, but it doesn't\r
511      * hurt to define it globally. */\r
512     PROT_SERIAL,\r
513     /* PROT_SUPDUP is the historical RFC 734 protocol. */\r
514     PROT_SUPDUP,\r
515     PROTOCOL_LIMIT, /* upper bound on number of protocols */\r
516 };\r
518 enum {\r
519     /* Bell settings (CONF_beep) */\r
520     BELL_DISABLED, BELL_DEFAULT, BELL_VISUAL, BELL_WAVEFILE, BELL_PCSPEAKER\r
521 };\r
523 enum {\r
524     /* Taskbar flashing indication on bell (CONF_beep_ind) */\r
525     B_IND_DISABLED, B_IND_FLASH, B_IND_STEADY\r
526 };\r
528 enum {\r
529     /* Resize actions (CONF_resize_action) */\r
530     RESIZE_TERM, RESIZE_DISABLED, RESIZE_FONT, RESIZE_EITHER\r
531 };\r
533 enum {\r
534     /* Function key types (CONF_funky_type) */\r
535     FUNKY_TILDE,\r
536     FUNKY_LINUX,\r
537     FUNKY_XTERM,\r
538     FUNKY_VT400,\r
539     FUNKY_VT100P,\r
540     FUNKY_SCO,\r
541     FUNKY_XTERM_216\r
542 };\r
544 enum {\r
545     /* Shifted arrow key types (CONF_sharrow_type) */\r
546     SHARROW_APPLICATION,  /* Ctrl flips between ESC O A and ESC [ A */\r
547     SHARROW_BITMAP        /* ESC [ 1 ; n A, where n = 1 + bitmap of CAS */\r
548 };\r
550 enum {\r
551     FQ_DEFAULT, FQ_ANTIALIASED, FQ_NONANTIALIASED, FQ_CLEARTYPE\r
552 };\r
554 enum {\r
555     SER_PAR_NONE, SER_PAR_ODD, SER_PAR_EVEN, SER_PAR_MARK, SER_PAR_SPACE\r
556 };\r
558 enum {\r
559     SER_FLOW_NONE, SER_FLOW_XONXOFF, SER_FLOW_RTSCTS, SER_FLOW_DSRDTR\r
560 };\r
562 /*\r
563  * Tables of string <-> enum value mappings used in settings.c.\r
564  * Defined here so that backends can export their GSS library tables\r
565  * to the cross-platform settings code.\r
566  */\r
567 struct keyvalwhere {\r
568     /*\r
569      * Two fields which define a string and enum value to be\r
570      * equivalent to each other.\r
571      */\r
572     const char *s;\r
573     int v;\r
575     /*\r
576      * The next pair of fields are used by gprefs() in settings.c to\r
577      * arrange that when it reads a list of strings representing a\r
578      * preference list and translates it into the corresponding list\r
579      * of integers, strings not appearing in the list are entered in a\r
580      * configurable position rather than uniformly at the end.\r
581      */\r
583     /*\r
584      * 'vrel' indicates which other value in the list to place this\r
585      * element relative to. It should be a value that has occurred in\r
586      * a 'v' field of some other element of the array, or -1 to\r
587      * indicate that we simply place relative to one or other end of\r
588      * the list.\r
589      *\r
590      * gprefs will try to process the elements in an order which makes\r
591      * this field work (i.e. so that the element referenced has been\r
592      * added before processing this one).\r
593      */\r
594     int vrel;\r
596     /*\r
597      * 'where' indicates whether to place the new value before or\r
598      * after the one referred to by vrel. -1 means before; +1 means\r
599      * after.\r
600      *\r
601      * When vrel is -1, this also implicitly indicates which end of\r
602      * the array to use. So vrel=-1, where=-1 means to place _before_\r
603      * some end of the list (hence, at the last element); vrel=-1,\r
604      * where=+1 means to place _after_ an end (hence, at the first).\r
605      */\r
606     int where;\r
607 };\r
609 #ifndef NO_GSSAPI\r
610 extern const int ngsslibs;\r
611 extern const char *const gsslibnames[]; /* for displaying in configuration */\r
612 extern const struct keyvalwhere gsslibkeywords[]; /* for settings.c */\r
613 #endif\r
615 extern const char *const ttymodes[];\r
617 enum {\r
618     /*\r
619      * Network address types. Used for specifying choice of IPv4/v6\r
620      * in config; also used in proxy.c to indicate whether a given\r
621      * host name has already been resolved or will be resolved at\r
622      * the proxy end.\r
623      */\r
624     ADDRTYPE_UNSPEC,\r
625     ADDRTYPE_IPV4,\r
626     ADDRTYPE_IPV6,\r
627     ADDRTYPE_LOCAL,    /* e.g. Unix domain socket, or Windows named pipe */\r
628     ADDRTYPE_NAME      /* SockAddr storing an unresolved host name */\r
629 };\r
631 /* Backend flags */\r
632 #define BACKEND_RESIZE_FORBIDDEN    0x01   /* Backend does not allow\r
633                                               resizing terminal */\r
634 #define BACKEND_NEEDS_TERMINAL      0x02   /* Backend must have terminal */\r
635 #define BACKEND_SUPPORTS_NC_HOST    0x04   /* Backend can honour\r
636                                               CONF_ssh_nc_host */\r
637 #define BACKEND_NOTIFIES_SESSION_START 0x08 /* Backend will call\r
638                                                seat_notify_session_started */\r
640 /* In (no)sshproxy.c */\r
641 extern const bool ssh_proxy_supported;\r
643 /*\r
644  * This structure type wraps a Seat pointer, in a way that has no\r
645  * purpose except to be a different type.\r
646  *\r
647  * The Seat wrapper functions that present interactive prompts all\r
648  * expect one of these in place of their ordinary Seat pointer. You\r
649  * get one by calling interactor_announce (defined below), which will\r
650  * print a message (if not already done) identifying the Interactor\r
651  * that originated the prompt.\r
652  *\r
653  * This arranges that the C type system itself will check that no call\r
654  * to any of those Seat methods has omitted the mandatory call to\r
655  * interactor_announce beforehand.\r
656  */\r
657 struct InteractionReadySeat {\r
658     Seat *seat;\r
659 };\r
661 /*\r
662  * The Interactor trait is implemented by anything that is capable of\r
663  * presenting interactive prompts or questions to the user during\r
664  * network connection setup. Every Backend that ever needs to do this\r
665  * is an Interactor, but also, while a Backend is making its initial\r
666  * network connection, it may go via network proxy code which is also\r
667  * an Interactor and can ask questions of its own.\r
668  */\r
669 struct Interactor {\r
670     const InteractorVtable *vt;\r
672     /* The parent Interactor that we are a proxy for, if any. */\r
673     Interactor *parent;\r
675     /*\r
676      * If we're the top-level Interactor (parent==NULL), then this\r
677      * field records the last Interactor that actually did anything\r
678      * interactive, so that we know when to announce a changeover\r
679      * between levels of proxying.\r
680      *\r
681      * If parent != NULL, this field is not used.\r
682      */\r
683     Interactor *last_to_talk;\r
684 };\r
686 struct InteractorVtable {\r
687     /*\r
688      * Returns a user-facing description of the nature of the network\r
689      * connection being made. Used in interactive proxy authentication\r
690      * to announce which connection attempt is now in control of the\r
691      * Seat.\r
692      *\r
693      * The idea is not just to be written in natural language, but to\r
694      * connect with the user's idea of _why_ they think some\r
695      * connection is being made. For example, instead of saying 'TCP\r
696      * connection to 123.45.67.89 port 22', you might say 'SSH\r
697      * connection to [logical host name for SSH host key purposes]'.\r
698      *\r
699      * The returned string must be freed by the caller.\r
700      */\r
701     char *(*description)(Interactor *itr);\r
703     /*\r
704      * Returns the LogPolicy associated with this Interactor. (A\r
705      * Backend can derive this from its logging context; a proxy\r
706      * Interactor inherits it from the Interactor for the parent\r
707      * network connection.)\r
708      */\r
709     LogPolicy *(*logpolicy)(Interactor *itr);\r
711     /*\r
712      * Gets and sets the Seat that this Interactor talks to. When a\r
713      * Seat is borrowed and replaced with a TempSeat, this will be the\r
714      * mechanism by which that replacement happens.\r
715      */\r
716     Seat *(*get_seat)(Interactor *itr);\r
717     void (*set_seat)(Interactor *itr, Seat *seat);\r
718 };\r
720 static inline char *interactor_description(Interactor *itr)\r
721 { return itr->vt->description(itr); }\r
722 static inline LogPolicy *interactor_logpolicy(Interactor *itr)\r
723 { return itr->vt->logpolicy(itr); }\r
724 static inline Seat *interactor_get_seat(Interactor *itr)\r
725 { return itr->vt->get_seat(itr); }\r
726 static inline void interactor_set_seat(Interactor *itr, Seat *seat)\r
727 { itr->vt->set_seat(itr, seat); }\r
729 static inline void interactor_set_child(Interactor *parent, Interactor *child)\r
730 { child->parent = parent; }\r
731 Seat *interactor_borrow_seat(Interactor *itr);\r
732 void interactor_return_seat(Interactor *itr);\r
733 InteractionReadySeat interactor_announce(Interactor *itr);\r
735 /* Interactors that are Backends will find this helper function useful\r
736  * in constructing their description strings */\r
737 char *default_description(const BackendVtable *backvt,\r
738                           const char *host, int port);\r
740 /*\r
741  * The Backend trait is the top-level one that governs each of the\r
742  * user-facing main modes that PuTTY can use to talk to some\r
743  * destination: SSH, Telnet, serial port, pty, etc.\r
744  */\r
746 struct Backend {\r
747     const BackendVtable *vt;\r
749     /* Many Backends are also Interactors. If this one is, a pointer\r
750      * to its Interactor trait lives here. */\r
751     Interactor *interactor;\r
752 };\r
753 struct BackendVtable {\r
754     char *(*init) (const BackendVtable *vt, Seat *seat,\r
755                    Backend **backend_out, LogContext *logctx, Conf *conf,\r
756                    const char *host, int port, char **realhost,\r
757                    bool nodelay, bool keepalive);\r
759     void (*free) (Backend *be);\r
760     /* Pass in a replacement configuration. */\r
761     void (*reconfig) (Backend *be, Conf *conf);\r
762     void (*send) (Backend *be, const char *buf, size_t len);\r
763     /* sendbuffer() returns the current amount of buffered data */\r
764     size_t (*sendbuffer) (Backend *be);\r
765     void (*size) (Backend *be, int width, int height);\r
766     void (*special) (Backend *be, SessionSpecialCode code, int arg);\r
767     const SessionSpecial *(*get_specials) (Backend *be);\r
768     bool (*connected) (Backend *be);\r
769     int (*exitcode) (Backend *be);\r
770     /* If back->sendok() returns false, the backend doesn't currently\r
771      * want input data, so the frontend should avoid acquiring any if\r
772      * possible (passing back-pressure on to its sender).\r
773      *\r
774      * Policy rule: no backend shall return true from sendok() while\r
775      * its network connection attempt is still ongoing. This ensures\r
776      * that if making the network connection involves a proxy type\r
777      * which wants to interact with the user via the terminal, the\r
778      * proxy implementation and the backend itself won't fight over\r
779      * who gets the terminal input. */\r
780     bool (*sendok) (Backend *be);\r
781     bool (*ldisc_option_state) (Backend *be, int);\r
782     void (*provide_ldisc) (Backend *be, Ldisc *ldisc);\r
783     /* Tells the back end that the front end  buffer is clearing. */\r
784     void (*unthrottle) (Backend *be, size_t bufsize);\r
785     int (*cfg_info) (Backend *be);\r
787     /* Only implemented in the SSH protocol: check whether a\r
788      * connection-sharing upstream exists for a given configuration. */\r
789     bool (*test_for_upstream)(const char *host, int port, Conf *conf);\r
790     /* Special-purpose function to return additional information to put\r
791      * in a "are you sure you want to close this session" dialog;\r
792      * return NULL if no such info, otherwise caller must free.\r
793      * Only implemented in the SSH protocol, to warn about downstream\r
794      * connections that would be lost if this one were terminated. */\r
795     char *(*close_warn_text)(Backend *be);\r
797     /* 'id' is a machine-readable name for the backend, used in\r
798      * saved-session storage. 'displayname_tc' and 'displayname_lc'\r
799      * are human-readable names, one in title-case for config boxes,\r
800      * and one in lower-case for use in mid-sentence. */\r
801     const char *id, *displayname_tc, *displayname_lc;\r
803     int protocol;\r
804     int default_port;\r
805     unsigned flags;\r
807     /* Only relevant for the serial protocol: bit masks of which\r
808      * parity and flow control settings are supported. */\r
809     unsigned serial_parity_mask, serial_flow_mask;\r
810 };\r
812 static inline char *backend_init(\r
813     const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,\r
814     Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)\r
815 { return vt->init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka); }\r
816 static inline void backend_free(Backend *be)\r
817 { be->vt->free(be); }\r
818 static inline void backend_reconfig(Backend *be, Conf *conf)\r
819 { be->vt->reconfig(be, conf); }\r
820 static inline void backend_send(Backend *be, const char *buf, size_t len)\r
821 { be->vt->send(be, buf, len); }\r
822 static inline size_t backend_sendbuffer(Backend *be)\r
823 { return be->vt->sendbuffer(be); }\r
824 static inline void backend_size(Backend *be, int width, int height)\r
825 { be->vt->size(be, width, height); }\r
826 static inline void backend_special(\r
827     Backend *be, SessionSpecialCode code, int arg)\r
828 { be->vt->special(be, code, arg); }\r
829 static inline const SessionSpecial *backend_get_specials(Backend *be)\r
830 { return be->vt->get_specials(be); }\r
831 static inline bool backend_connected(Backend *be)\r
832 { return be->vt->connected(be); }\r
833 static inline int backend_exitcode(Backend *be)\r
834 { return be->vt->exitcode(be); }\r
835 static inline bool backend_sendok(Backend *be)\r
836 { return be->vt->sendok(be); }\r
837 static inline bool backend_ldisc_option_state(Backend *be, int state)\r
838 { return be->vt->ldisc_option_state(be, state); }\r
839 static inline void backend_provide_ldisc(Backend *be, Ldisc *ldisc)\r
840 { be->vt->provide_ldisc(be, ldisc); }\r
841 static inline void backend_unthrottle(Backend *be, size_t bufsize)\r
842 { be->vt->unthrottle(be, bufsize); }\r
843 static inline int backend_cfg_info(Backend *be)\r
844 { return be->vt->cfg_info(be); }\r
846 extern const struct BackendVtable *const backends[];\r
847 /*\r
848  * In programs with a config UI, only the first few members of\r
849  * backends[] will be displayed at the top-level; the others will be\r
850  * relegated to a drop-down.\r
851  */\r
852 extern const size_t n_ui_backends;\r
854 /*\r
855  * Suggested default protocol provided by the backend link module.\r
856  * The application is free to ignore this.\r
857  */\r
858 extern const int be_default_protocol;\r
860 /*\r
861  * Name of this particular application, for use in the config box\r
862  * and other pieces of text.\r
863  */\r
864 extern const char *const appname;\r
866 /*\r
867  * Used by callback.c; declared up here so that prompts_t can use it\r
868  */\r
869 typedef void (*toplevel_callback_fn_t)(void *ctx);\r
871 /* Enum of result types in SeatPromptResult below */\r
872 typedef enum SeatPromptResultKind {\r
873     /* Answer not yet available at all; either try again later or wait\r
874      * for a callback (depending on the request's API) */\r
875     SPRK_INCOMPLETE,\r
877     /* We're abandoning the connection because the user interactively\r
878      * told us to. (Hence, no need to present an error message\r
879      * telling the user we're doing that: they already know.) */\r
880     SPRK_USER_ABORT,\r
882     /* We're abandoning the connection for some other reason (e.g. we\r
883      * were unable to present the prompt at all, or a batch-mode\r
884      * configuration told us to give the answer no). This may\r
885      * ultimately have stemmed from some user configuration, but they\r
886      * didn't _tell us right now_ to abandon this connection, so we\r
887      * still need to inform them that we've done so. */\r
888     SPRK_SW_ABORT,\r
890     /* We're proceeding with the connection and have all requested\r
891      * information (if any) */\r
892     SPRK_OK\r
893 } SeatPromptResultKind;\r
895 /* Small struct to present the results of interactive requests from\r
896  * backend to Seat (see below) */\r
897 struct SeatPromptResult {\r
898     SeatPromptResultKind kind;\r
900     /*\r
901      * In the case of SPRK_SW_ABORT, the frontend provides an error\r
902      * message to present to the user. But dynamically allocating it\r
903      * up front would mean having to make sure it got freed at any\r
904      * call site where one of these structs is received (and freed\r
905      * _once_ no matter how many times the struct is copied). So\r
906      * instead we provide a function that will generate the error\r
907      * message into a BinarySink.\r
908      */\r
909     void (*errfn)(SeatPromptResult, BinarySink *);\r
911     /*\r
912      * And some fields the error function can use to construct the\r
913      * message (holding, e.g. an OS error code).\r
914      */\r
915     const char *errdata_lit; /* statically allocated, e.g. a string literal */\r
916     unsigned errdata_u;\r
917 };\r
919 /* Helper function to construct the simple versions of these\r
920  * structures inline */\r
921 static inline SeatPromptResult make_spr_simple(SeatPromptResultKind kind)\r
923     SeatPromptResult spr;\r
924     spr.kind = kind;\r
925     spr.errdata_lit = NULL;\r
926     return spr;\r
929 /* Most common constructor function for SPRK_SW_ABORT errors */\r
930 SeatPromptResult make_spr_sw_abort_static(const char *);\r
932 /* Convenience macros wrapping those constructors in turn */\r
933 #define SPR_INCOMPLETE make_spr_simple(SPRK_INCOMPLETE)\r
934 #define SPR_USER_ABORT make_spr_simple(SPRK_USER_ABORT)\r
935 #define SPR_SW_ABORT(lit) make_spr_sw_abort_static(lit)\r
936 #define SPR_OK make_spr_simple(SPRK_OK)\r
938 /* Query function that folds both kinds of abort together */\r
939 static inline bool spr_is_abort(SeatPromptResult spr)\r
941     return spr.kind == SPRK_USER_ABORT || spr.kind == SPRK_SW_ABORT;\r
944 /* Function to return a dynamically allocated copy of the error message */\r
945 char *spr_get_error_message(SeatPromptResult spr);\r
947 /*\r
948  * Mechanism for getting text strings such as usernames and passwords\r
949  * from the front-end.\r
950  * The fields are mostly modelled after SSH's keyboard-interactive auth.\r
951  * FIXME We should probably mandate a character set/encoding (probably UTF-8).\r
952  *\r
953  * Since many of the pieces of text involved may be chosen by the server,\r
954  * the caller must take care to ensure that the server can't spoof locally-\r
955  * generated prompts such as key passphrase prompts. Some ground rules:\r
956  *  - If the front-end needs to truncate a string, it should lop off the\r
957  *    end.\r
958  *  - The front-end should filter out any dangerous characters and\r
959  *    generally not trust the strings. (But \n is required to behave\r
960  *    vaguely sensibly, at least in `instruction', and ideally in\r
961  *    `prompt[]' too.)\r
962  */\r
963 typedef struct {\r
964     char *prompt;\r
965     bool echo;\r
966     strbuf *result;\r
967 } prompt_t;\r
968 typedef struct prompts_t prompts_t;\r
969 struct prompts_t {\r
970     /*\r
971      * Indicates whether the information entered is to be used locally\r
972      * (for instance a key passphrase prompt), or is destined for the wire.\r
973      * This is a hint only; the front-end is at liberty not to use this\r
974      * information (so the caller should ensure that the supplied text is\r
975      * sufficient).\r
976      */\r
977     bool to_server;\r
979     /*\r
980      * Indicates whether the prompts originated _at_ the server, so\r
981      * that the front end can display some kind of trust sigil that\r
982      * distinguishes (say) a legit private-key passphrase prompt from\r
983      * a fake one sent by a malicious server.\r
984      */\r
985     bool from_server;\r
987     char *name;         /* Short description, perhaps for dialog box title */\r
988     bool name_reqd;     /* Display of `name' required or optional? */\r
989     char *instruction;  /* Long description, maybe with embedded newlines */\r
990     bool instr_reqd;    /* Display of `instruction' required or optional? */\r
991     size_t n_prompts;   /* May be zero (in which case display the foregoing,\r
992                          * if any, and return success) */\r
993     size_t prompts_size; /* allocated storage capacity for prompts[] */\r
994     prompt_t **prompts;\r
995     void *data;         /* slot for housekeeping data, managed by\r
996                          * seat_get_userpass_input(); initially NULL */\r
997     SeatPromptResult spr; /* some implementations need to cache one of these */\r
999     /*\r
1000      * Callback you can fill in to be notified when all the prompts'\r
1001      * responses are available. After you receive this notification, a\r
1002      * further call to the get_userpass_input function will return the\r
1003      * final state of the prompts system, which is guaranteed not to\r
1004      * be negative for 'still ongoing'.\r
1005      */\r
1006     toplevel_callback_fn_t callback;\r
1007     void *callback_ctx;\r
1009     /*\r
1010      * When this prompts_t is known to an Ldisc, we might need to\r
1011      * break the connection if things get freed in an emergency. So\r
1012      * this is a pointer to the Ldisc's pointer to us.\r
1013      */\r
1014     prompts_t **ldisc_ptr_to_us;\r
1015 };\r
1016 prompts_t *new_prompts(void);\r
1017 void add_prompt(prompts_t *p, char *promptstr, bool echo);\r
1018 void prompt_set_result(prompt_t *pr, const char *newstr);\r
1019 char *prompt_get_result(prompt_t *pr);\r
1020 const char *prompt_get_result_ref(prompt_t *pr);\r
1021 void free_prompts(prompts_t *p);\r
1023 /*\r
1024  * Data type definitions for true-colour terminal display.\r
1025  * 'optionalrgb' describes a single RGB colour, which overrides the\r
1026  * other colour settings if 'enabled' is nonzero, and is ignored\r
1027  * otherwise. 'truecolour' contains a pair of those for foreground and\r
1028  * background.\r
1029  */\r
1030 typedef struct optionalrgb {\r
1031     bool enabled;\r
1032     unsigned char r, g, b;\r
1033 } optionalrgb;\r
1034 extern const optionalrgb optionalrgb_none;\r
1035 typedef struct truecolour {\r
1036     optionalrgb fg, bg;\r
1037 } truecolour;\r
1038 #define optionalrgb_equal(r1,r2) (                              \\r
1039         (r1).enabled==(r2).enabled &&                           \\r
1040         (r1).r==(r2).r && (r1).g==(r2).g && (r1).b==(r2).b)\r
1041 #define truecolour_equal(c1,c2) (               \\r
1042         optionalrgb_equal((c1).fg, (c2).fg) &&  \\r
1043         optionalrgb_equal((c1).bg, (c2).bg))\r
1045 /*\r
1046  * Enumeration of clipboards. We provide some standard ones cross-\r
1047  * platform, and then permit each platform to extend this enumeration\r
1048  * further by defining PLATFORM_CLIPBOARDS in its own header file.\r
1049  *\r
1050  * CLIP_NULL is a non-clipboard, writes to which are ignored and reads\r
1051  * from which return no data.\r
1052  *\r
1053  * CLIP_LOCAL refers to a buffer within terminal.c, which\r
1054  * unconditionally saves the last data selected in the terminal. In\r
1055  * configurations where a system clipboard is not written\r
1056  * automatically on selection but instead by an explicit UI action,\r
1057  * this is where the code responding to that action can find the data\r
1058  * to write to the clipboard in question.\r
1059  */\r
1060 #define CROSS_PLATFORM_CLIPBOARDS(X)                    \\r
1061     X(CLIP_NULL, "null clipboard")                      \\r
1062     X(CLIP_LOCAL, "last text selected in terminal")     \\r
1063     /* end of list */\r
1065 #define ALL_CLIPBOARDS(X)                       \\r
1066     CROSS_PLATFORM_CLIPBOARDS(X)                \\r
1067     PLATFORM_CLIPBOARDS(X)                      \\r
1068     /* end of list */\r
1070 #define CLIP_ID(id,name) id,\r
1071 enum { ALL_CLIPBOARDS(CLIP_ID) N_CLIPBOARDS };\r
1072 #undef CLIP_ID\r
1074 /* Hint from backend to frontend about time-consuming operations, used\r
1075  * by seat_set_busy_status. Initial state is assumed to be\r
1076  * BUSY_NOT. */\r
1077 typedef enum BusyStatus {\r
1078     BUSY_NOT,       /* Not busy, all user interaction OK */\r
1079     BUSY_WAITING,   /* Waiting for something; local event loops still\r
1080                        running so some local interaction (e.g. menus)\r
1081                        OK, but network stuff is suspended */\r
1082     BUSY_CPU        /* Locally busy (e.g. crypto); user interaction\r
1083                      * suspended */\r
1084 } BusyStatus;\r
1086 typedef enum SeatInteractionContext {\r
1087     SIC_BANNER, SIC_KI_PROMPTS\r
1088 } SeatInteractionContext;\r
1090 typedef enum SeatOutputType {\r
1091     SEAT_OUTPUT_STDOUT, SEAT_OUTPUT_STDERR\r
1092 } SeatOutputType;\r
1094 typedef enum SeatDialogTextType {\r
1095     SDT_PARA, SDT_DISPLAY, SDT_SCARY_HEADING,\r
1096     SDT_TITLE, SDT_PROMPT, SDT_BATCH_ABORT,\r
1097     SDT_MORE_INFO_KEY, SDT_MORE_INFO_VALUE_SHORT, SDT_MORE_INFO_VALUE_BLOB\r
1098 } SeatDialogTextType;\r
1099 struct SeatDialogTextItem {\r
1100     SeatDialogTextType type;\r
1101     char *text;\r
1102 };\r
1103 struct SeatDialogText {\r
1104     size_t nitems, itemsize;\r
1105     SeatDialogTextItem *items;\r
1106 };\r
1107 SeatDialogText *seat_dialog_text_new(void);\r
1108 void seat_dialog_text_free(SeatDialogText *sdt);\r
1109 PRINTF_LIKE(3, 4) void seat_dialog_text_append(\r
1110     SeatDialogText *sdt, SeatDialogTextType type, const char *fmt, ...);\r
1112 /*\r
1113  * Data type 'Seat', which is an API intended to contain essentially\r
1114  * everything that a back end might need to talk to its client for:\r
1115  * session output, password prompts, SSH warnings about host keys and\r
1116  * weak cryptography, notifications of events like the remote process\r
1117  * exiting or the GUI specials menu needing an update.\r
1118  */\r
1119 struct Seat {\r
1120     const struct SeatVtable *vt;\r
1121 };\r
1122 struct SeatVtable {\r
1123     /*\r
1124      * Provide output from the remote session. 'type' indicates the\r
1125      * type of the output (stdout or stderr), which can be used to\r
1126      * split the output into separate message channels, if the seat\r
1127      * wants to handle them differently. But combining the channels\r
1128      * into one is OK too; that's what terminal-window based seats do.\r
1129      *\r
1130      * The return value is the current size of the output backlog.\r
1131      */\r
1132     size_t (*output)(Seat *seat, SeatOutputType type,\r
1133                      const void *data, size_t len);\r
1135     /*\r
1136      * Called when the back end wants to indicate that EOF has arrived\r
1137      * on the server-to-client stream. Returns false to indicate that\r
1138      * we intend to keep the session open in the other direction, or\r
1139      * true to indicate that if they're closing so are we.\r
1140      */\r
1141     bool (*eof)(Seat *seat);\r
1143     /*\r
1144      * Called by the back end to notify that the output backlog has\r
1145      * changed size. A front end in control of the event loop won't\r
1146      * necessarily need this (they can just keep checking it via\r
1147      * backend_sendbuffer at every opportunity), but one buried in the\r
1148      * depths of something else (like an SSH proxy) will need to be\r
1149      * proactively notified that the amount of buffered data has\r
1150      * become smaller.\r
1151      */\r
1152     void (*sent)(Seat *seat, size_t new_sendbuffer);\r
1154     /*\r
1155      * Provide authentication-banner output from the session setup.\r
1156      * End-user Seats can treat this as very similar to 'output', but\r
1157      * intermediate Seats in complex proxying situations will want to\r
1158      * implement this and 'output' differently.\r
1159      */\r
1160     size_t (*banner)(Seat *seat, const void *data, size_t len);\r
1162     /*\r
1163      * Try to get answers from a set of interactive login prompts. The\r
1164      * prompts are provided in 'p'.\r
1165      *\r
1166      * (FIXME: it would be nice to distinguish two classes of user-\r
1167      * abort action, so the user could specify 'I want to abandon this\r
1168      * entire attempt to start a session' or the milder 'I want to\r
1169      * abandon this particular form of authentication and fall back to\r
1170      * a different one' - e.g. if you turn out not to be able to\r
1171      * remember your private key passphrase then perhaps you'd rather\r
1172      * fall back to password auth rather than aborting the whole\r
1173      * session.)\r
1174      */\r
1175     SeatPromptResult (*get_userpass_input)(Seat *seat, prompts_t *p);\r
1177     /*\r
1178      * Notify the seat that the main session channel has been\r
1179      * successfully set up.\r
1180      *\r
1181      * This is only used as part of the SSH proxying system, so it's\r
1182      * not necessary to implement it in all backends. A backend must\r
1183      * call this if it advertises the BACKEND_NOTIFIES_SESSION_START\r
1184      * flag, and otherwise, doesn't have to.\r
1185      */\r
1186     void (*notify_session_started)(Seat *seat);\r
1188     /*\r
1189      * Notify the seat that the process running at the other end of\r
1190      * the connection has finished.\r
1191      */\r
1192     void (*notify_remote_exit)(Seat *seat);\r
1194     /*\r
1195      * Notify the seat that the whole connection has finished.\r
1196      * (Distinct from notify_remote_exit, e.g. in the case where you\r
1197      * have port forwardings still active when the main foreground\r
1198      * session goes away: then you'd get notify_remote_exit when the\r
1199      * foreground session dies, but notify_remote_disconnect when the\r
1200      * last forwarding vanishes and the network connection actually\r
1201      * closes.)\r
1202      *\r
1203      * This function might be called multiple times by accident; seats\r
1204      * should be prepared to cope.\r
1205      *\r
1206      * More precisely: this function notifies the seat that\r
1207      * backend_connected() might now return false where previously it\r
1208      * returned true. (Note the 'might': an accidental duplicate call\r
1209      * might happen when backend_connected() was already returning\r
1210      * false. Or even, in weird situations, when it hadn't stopped\r
1211      * returning true yet. The point is, when you get this\r
1212      * notification, all it's really telling you is that it's worth\r
1213      * _checking_ backend_connected, if you weren't already.)\r
1214      */\r
1215     void (*notify_remote_disconnect)(Seat *seat);\r
1217     /*\r
1218      * Notify the seat that the connection has suffered a fatal error.\r
1219      */\r
1220     void (*connection_fatal)(Seat *seat, const char *message);\r
1222     /*\r
1223      * Notify the seat that the list of special commands available\r
1224      * from backend_get_specials() has changed, so that it might want\r
1225      * to call that function to repopulate its menu.\r
1226      *\r
1227      * Seats are not expected to call backend_get_specials()\r
1228      * proactively; they may start by assuming that the backend\r
1229      * provides no special commands at all, so if the backend does\r
1230      * provide any, then it should use this notification at startup\r
1231      * time. Of course it can also invoke it later if the set of\r
1232      * special commands changes.\r
1233      *\r
1234      * It does not need to invoke it at session shutdown.\r
1235      */\r
1236     void (*update_specials_menu)(Seat *seat);\r
1238     /*\r
1239      * Get the seat's preferred value for an SSH terminal mode\r
1240      * setting. Returning NULL indicates no preference (i.e. the SSH\r
1241      * connection will not attempt to set the mode at all).\r
1242      *\r
1243      * The returned value is dynamically allocated, and the caller\r
1244      * should free it.\r
1245      */\r
1246     char *(*get_ttymode)(Seat *seat, const char *mode);\r
1248     /*\r
1249      * Tell the seat whether the backend is currently doing anything\r
1250      * CPU-intensive (typically a cryptographic key exchange). See\r
1251      * BusyStatus enumeration above.\r
1252      */\r
1253     void (*set_busy_status)(Seat *seat, BusyStatus status);\r
1255     /*\r
1256      * Ask the seat whether a given SSH host key should be accepted.\r
1257      * This is called after we've already checked it by any means we\r
1258      * can do ourselves, such as checking against host key\r
1259      * fingerprints in the Conf or the host key cache on disk: once we\r
1260      * call this function, we've already decided there's nothing for\r
1261      * it but to prompt the user.\r
1262      *\r
1263      * 'mismatch' reports the result of checking the host key cache:\r
1264      * it is true if the server has presented a host key different\r
1265      * from the one we expected, and false if we had no expectation in\r
1266      * the first place.\r
1267      *\r
1268      * This call may prompt the user synchronously and not return\r
1269      * until the answer is available, or it may present the prompt and\r
1270      * return immediately, giving the answer later via the provided\r
1271      * callback.\r
1272      *\r
1273      * Return values:\r
1274      *\r
1275      *  - +1 means `user approved the key, so continue with the\r
1276      *    connection'\r
1277      *\r
1278      *  - 0 means `user rejected the key, abandon the connection'\r
1279      *\r
1280      *  - -1 means `I've initiated enquiries, please wait to be called\r
1281      *    back via the provided function with a result that's either 0\r
1282      *    or +1'.\r
1283      */\r
1284     SeatPromptResult (*confirm_ssh_host_key)(\r
1285         Seat *seat, const char *host, int port, const char *keytype,\r
1286         char *keystr, SeatDialogText *text, HelpCtx helpctx,\r
1287         void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1289     /*\r
1290      * Check with the seat whether it's OK to use a cryptographic\r
1291      * primitive from below the 'warn below this line' threshold in\r
1292      * the input Conf. Return values are the same as\r
1293      * confirm_ssh_host_key above.\r
1294      */\r
1295     SeatPromptResult (*confirm_weak_crypto_primitive)(\r
1296         Seat *seat, SeatDialogText *text,\r
1297         void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1299     /*\r
1300      * Variant form of confirm_weak_crypto_primitive, which prints a\r
1301      * slightly different message but otherwise has the same\r
1302      * semantics.\r
1303      *\r
1304      * This form is used in the case where we're using a host key\r
1305      * below the warning threshold because that's the best one we have\r
1306      * cached, but at least one host key algorithm *above* the\r
1307      * threshold is available that we don't have cached.\r
1308      */\r
1309     SeatPromptResult (*confirm_weak_cached_hostkey)(\r
1310         Seat *seat, SeatDialogText *text,\r
1311         void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1313     /*\r
1314      * Some snippets of text describing the UI actions in host key\r
1315      * prompts / dialog boxes, to be used in ssh/common.c when it\r
1316      * assembles the full text of those prompts.\r
1317      */\r
1318     const SeatDialogPromptDescriptions *(*prompt_descriptions)(Seat *seat);\r
1320     /*\r
1321      * Indicates whether the seat is expecting to interact with the\r
1322      * user in the UTF-8 character set. (Affects e.g. visual erase\r
1323      * handling in local line editing.)\r
1324      */\r
1325     bool (*is_utf8)(Seat *seat);\r
1327     /*\r
1328      * Notify the seat that the back end, and/or the ldisc between\r
1329      * them, have changed their idea of whether they currently want\r
1330      * local echo and/or local line editing enabled.\r
1331      */\r
1332     void (*echoedit_update)(Seat *seat, bool echoing, bool editing);\r
1334     /*\r
1335      * Return the local X display string relevant to a seat, or NULL\r
1336      * if there isn't one or if the concept is meaningless.\r
1337      */\r
1338     const char *(*get_x_display)(Seat *seat);\r
1340     /*\r
1341      * Return the X11 id of the X terminal window relevant to a seat,\r
1342      * by returning true and filling in the output pointer. Return\r
1343      * false if there isn't one or if the concept is meaningless.\r
1344      */\r
1345     bool (*get_windowid)(Seat *seat, long *id_out);\r
1347     /*\r
1348      * Return the size of the terminal window in pixels. If the\r
1349      * concept is meaningless or the information is unavailable,\r
1350      * return false; otherwise fill in the output pointers and return\r
1351      * true.\r
1352      */\r
1353     bool (*get_window_pixel_size)(Seat *seat, int *width, int *height);\r
1355     /*\r
1356      * Return a StripCtrlChars appropriate for sanitising untrusted\r
1357      * terminal data (e.g. SSH banners, prompts) being sent to the\r
1358      * user of this seat. May return NULL if no sanitisation is\r
1359      * needed.\r
1360      */\r
1361     StripCtrlChars *(*stripctrl_new)(\r
1362         Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1364     /*\r
1365      * Set the seat's current idea of where output is coming from.\r
1366      * True means that output is being generated by our own code base\r
1367      * (and hence, can be trusted if it's asking you for secrets such\r
1368      * as your passphrase); false means output is coming from the\r
1369      * server.\r
1370      */\r
1371     void (*set_trust_status)(Seat *seat, bool trusted);\r
1373     /*\r
1374      * Query whether this Seat can do anything user-visible in\r
1375      * response to set_trust_status.\r
1376      *\r
1377      * Returns true if the seat has a way to indicate this\r
1378      * distinction. Returns false if not, in which case the backend\r
1379      * should use a fallback defence against spoofing of PuTTY's local\r
1380      * prompts by malicious servers.\r
1381      */\r
1382     bool (*can_set_trust_status)(Seat *seat);\r
1384     /*\r
1385      * Query whether this Seat's interactive prompt responses and its\r
1386      * session input come from the same place.\r
1387      *\r
1388      * If false, this is used to suppress the final 'Press Return to\r
1389      * begin session' anti-spoofing prompt in Plink. For example,\r
1390      * Plink itself sets this flag if its standard input is redirected\r
1391      * (and therefore not coming from the same place as the console\r
1392      * it's sending its prompts to).\r
1393      */\r
1394     bool (*has_mixed_input_stream)(Seat *seat);\r
1396     /*\r
1397      * Ask the seat whether it would like verbose messages.\r
1398      */\r
1399     bool (*verbose)(Seat *seat);\r
1401     /*\r
1402      * Ask the seat whether it's an interactive program.\r
1403      */\r
1404     bool (*interactive)(Seat *seat);\r
1406     /*\r
1407      * Return the seat's current idea of where the output cursor is.\r
1408      *\r
1409      * Returns true if the seat has a cursor. Returns false if not.\r
1410      */\r
1411     bool (*get_cursor_position)(Seat *seat, int *x, int *y);\r
1412 };\r
1414 static inline size_t seat_output(\r
1415     Seat *seat, SeatOutputType type, const void *data, size_t len)\r
1416 { return seat->vt->output(seat, type, data, len); }\r
1417 static inline bool seat_eof(Seat *seat)\r
1418 { return seat->vt->eof(seat); }\r
1419 static inline void seat_sent(Seat *seat, size_t bufsize)\r
1420 { seat->vt->sent(seat, bufsize); }\r
1421 static inline size_t seat_banner(\r
1422     InteractionReadySeat iseat, const void *data, size_t len)\r
1423 { return iseat.seat->vt->banner(iseat.seat, data, len); }\r
1424 static inline SeatPromptResult seat_get_userpass_input(\r
1425     InteractionReadySeat iseat, prompts_t *p)\r
1426 { return iseat.seat->vt->get_userpass_input(iseat.seat, p); }\r
1427 static inline void seat_notify_session_started(Seat *seat)\r
1428 { seat->vt->notify_session_started(seat); }\r
1429 static inline void seat_notify_remote_exit(Seat *seat)\r
1430 { seat->vt->notify_remote_exit(seat); }\r
1431 static inline void seat_notify_remote_disconnect(Seat *seat)\r
1432 { seat->vt->notify_remote_disconnect(seat); }\r
1433 static inline void seat_update_specials_menu(Seat *seat)\r
1434 { seat->vt->update_specials_menu(seat); }\r
1435 static inline char *seat_get_ttymode(Seat *seat, const char *mode)\r
1436 { return seat->vt->get_ttymode(seat, mode); }\r
1437 static inline void seat_set_busy_status(Seat *seat, BusyStatus status)\r
1438 { seat->vt->set_busy_status(seat, status); }\r
1439 static inline SeatPromptResult seat_confirm_ssh_host_key(\r
1440     InteractionReadySeat iseat, const char *h, int p, const char *ktyp,\r
1441     char *kstr, SeatDialogText *text, HelpCtx helpctx,\r
1442     void (*cb)(void *ctx, SeatPromptResult result), void *ctx)\r
1443 { return iseat.seat->vt->confirm_ssh_host_key(\r
1444         iseat.seat, h, p, ktyp, kstr, text, helpctx, cb, ctx); }\r
1445 static inline SeatPromptResult seat_confirm_weak_crypto_primitive(\r
1446     InteractionReadySeat iseat, SeatDialogText *text,\r
1447     void (*cb)(void *ctx, SeatPromptResult result), void *ctx)\r
1448 { return iseat.seat->vt->confirm_weak_crypto_primitive(\r
1449         iseat.seat, text, cb, ctx); }\r
1450 static inline SeatPromptResult seat_confirm_weak_cached_hostkey(\r
1451     InteractionReadySeat iseat, SeatDialogText *text,\r
1452     void (*cb)(void *ctx, SeatPromptResult result), void *ctx)\r
1453 { return iseat.seat->vt->confirm_weak_cached_hostkey(\r
1454         iseat.seat, text, cb, ctx); }\r
1455 static inline const SeatDialogPromptDescriptions *seat_prompt_descriptions(\r
1456     Seat *seat)\r
1457 { return seat->vt->prompt_descriptions(seat); }\r
1458 static inline bool seat_is_utf8(Seat *seat)\r
1459 { return seat->vt->is_utf8(seat); }\r
1460 static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)\r
1461 { seat->vt->echoedit_update(seat, ec, ed); }\r
1462 static inline const char *seat_get_x_display(Seat *seat)\r
1463 { return seat->vt->get_x_display(seat); }\r
1464 static inline bool seat_get_windowid(Seat *seat, long *id_out)\r
1465 { return seat->vt->get_windowid(seat, id_out); }\r
1466 static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)\r
1467 { return seat->vt->get_window_pixel_size(seat, w, h); }\r
1468 static inline StripCtrlChars *seat_stripctrl_new(\r
1469     Seat *seat, BinarySink *bs, SeatInteractionContext sic)\r
1470 { return seat->vt->stripctrl_new(seat, bs, sic); }\r
1471 static inline void seat_set_trust_status(Seat *seat, bool trusted)\r
1472 { seat->vt->set_trust_status(seat, trusted); }\r
1473 static inline bool seat_can_set_trust_status(Seat *seat)\r
1474 { return seat->vt->can_set_trust_status(seat); }\r
1475 static inline bool seat_has_mixed_input_stream(Seat *seat)\r
1476 { return seat->vt->has_mixed_input_stream(seat); }\r
1477 static inline bool seat_verbose(Seat *seat)\r
1478 { return seat->vt->verbose(seat); }\r
1479 static inline bool seat_interactive(Seat *seat)\r
1480 { return seat->vt->interactive(seat); }\r
1481 static inline bool seat_get_cursor_position(Seat *seat, int *x, int *y)\r
1482 { return  seat->vt->get_cursor_position(seat, x, y); }\r
1484 /* Unlike the seat's actual method, the public entry point\r
1485  * seat_connection_fatal is a wrapper function with a printf-like API,\r
1486  * defined in utils. */\r
1487 void seat_connection_fatal(Seat *seat, const char *fmt, ...) PRINTF_LIKE(2, 3);\r
1489 /* Handy aliases for seat_output which set is_stderr to a fixed value. */\r
1490 static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)\r
1491 { return seat_output(seat, SEAT_OUTPUT_STDOUT, data, len); }\r
1492 static inline size_t seat_stdout_pl(Seat *seat, ptrlen data)\r
1493 { return seat_output(seat, SEAT_OUTPUT_STDOUT, data.ptr, data.len); }\r
1494 static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)\r
1495 { return seat_output(seat, SEAT_OUTPUT_STDERR, data, len); }\r
1496 static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)\r
1497 { return seat_output(seat, SEAT_OUTPUT_STDERR, data.ptr, data.len); }\r
1499 /* Alternative API for seat_banner taking a ptrlen */\r
1500 static inline size_t seat_banner_pl(InteractionReadySeat iseat, ptrlen data)\r
1501 { return iseat.seat->vt->banner(iseat.seat, data.ptr, data.len); }\r
1503 struct SeatDialogPromptDescriptions {\r
1504     const char *hk_accept_action;\r
1505     const char *hk_connect_once_action;\r
1506     const char *hk_cancel_action, *hk_cancel_action_Participle;\r
1507     const char *weak_accept_action, *weak_cancel_action;\r
1508 };\r
1510 /* In the utils subdir: print a message to the Seat which can't be\r
1511  * spoofed by server-supplied auth-time output such as SSH banners */\r
1512 void seat_antispoof_msg(InteractionReadySeat iseat, const char *msg);\r
1514 /*\r
1515  * Stub methods for seat implementations that want to use the obvious\r
1516  * null handling for a given method.\r
1517  *\r
1518  * These are generally obvious, except for is_utf8, where you might\r
1519  * plausibly want to return either fixed answer 'no' or 'yes'.\r
1520  */\r
1521 size_t nullseat_output(\r
1522     Seat *seat, SeatOutputType type, const void *data, size_t len);\r
1523 bool nullseat_eof(Seat *seat);\r
1524 void nullseat_sent(Seat *seat, size_t bufsize);\r
1525 size_t nullseat_banner(Seat *seat, const void *data, size_t len);\r
1526 size_t nullseat_banner_to_stderr(Seat *seat, const void *data, size_t len);\r
1527 SeatPromptResult nullseat_get_userpass_input(Seat *seat, prompts_t *p);\r
1528 void nullseat_notify_session_started(Seat *seat);\r
1529 void nullseat_notify_remote_exit(Seat *seat);\r
1530 void nullseat_notify_remote_disconnect(Seat *seat);\r
1531 void nullseat_connection_fatal(Seat *seat, const char *message);\r
1532 void nullseat_update_specials_menu(Seat *seat);\r
1533 char *nullseat_get_ttymode(Seat *seat, const char *mode);\r
1534 void nullseat_set_busy_status(Seat *seat, BusyStatus status);\r
1535 SeatPromptResult nullseat_confirm_ssh_host_key(\r
1536     Seat *seat, const char *host, int port, const char *keytype,\r
1537     char *keystr, SeatDialogText *text, HelpCtx helpctx,\r
1538     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1539 SeatPromptResult nullseat_confirm_weak_crypto_primitive(\r
1540     Seat *seat, SeatDialogText *text,\r
1541     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1542 SeatPromptResult nullseat_confirm_weak_cached_hostkey(\r
1543     Seat *seat, SeatDialogText *text,\r
1544     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1545 const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat);\r
1546 bool nullseat_is_never_utf8(Seat *seat);\r
1547 bool nullseat_is_always_utf8(Seat *seat);\r
1548 void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing);\r
1549 const char *nullseat_get_x_display(Seat *seat);\r
1550 bool nullseat_get_windowid(Seat *seat, long *id_out);\r
1551 bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height);\r
1552 StripCtrlChars *nullseat_stripctrl_new(\r
1553     Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1554 void nullseat_set_trust_status(Seat *seat, bool trusted);\r
1555 bool nullseat_can_set_trust_status_yes(Seat *seat);\r
1556 bool nullseat_can_set_trust_status_no(Seat *seat);\r
1557 bool nullseat_has_mixed_input_stream_yes(Seat *seat);\r
1558 bool nullseat_has_mixed_input_stream_no(Seat *seat);\r
1559 bool nullseat_verbose_no(Seat *seat);\r
1560 bool nullseat_verbose_yes(Seat *seat);\r
1561 bool nullseat_interactive_no(Seat *seat);\r
1562 bool nullseat_interactive_yes(Seat *seat);\r
1563 bool nullseat_get_cursor_position(Seat *seat, int *x, int *y);\r
1565 /*\r
1566  * Seat functions provided by the platform's console-application\r
1567  * support module (console.c in each platform subdirectory).\r
1568  */\r
1570 void console_connection_fatal(Seat *seat, const char *message);\r
1571 SeatPromptResult console_confirm_ssh_host_key(\r
1572     Seat *seat, const char *host, int port, const char *keytype,\r
1573     char *keystr, SeatDialogText *text, HelpCtx helpctx,\r
1574     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1575 SeatPromptResult console_confirm_weak_crypto_primitive(\r
1576     Seat *seat, SeatDialogText *text,\r
1577     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1578 SeatPromptResult console_confirm_weak_cached_hostkey(\r
1579     Seat *seat, SeatDialogText *text,\r
1580     void (*callback)(void *ctx, SeatPromptResult result), void *ctx);\r
1581 StripCtrlChars *console_stripctrl_new(\r
1582     Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);\r
1583 void console_set_trust_status(Seat *seat, bool trusted);\r
1584 bool console_can_set_trust_status(Seat *seat);\r
1585 bool console_has_mixed_input_stream(Seat *seat);\r
1586 const SeatDialogPromptDescriptions *console_prompt_descriptions(Seat *seat);\r
1588 /*\r
1589  * Other centralised seat functions.\r
1590  */\r
1591 SeatPromptResult filexfer_get_userpass_input(Seat *seat, prompts_t *p);\r
1592 bool cmdline_seat_verbose(Seat *seat);\r
1594 /*\r
1595  * TempSeat: a seat implementation that can be given to a backend\r
1596  * temporarily while network proxy setup is using the real seat.\r
1597  * Buffers output and trust-status changes until the real seat is\r
1598  * available again.\r
1599  */\r
1601 /* Called by the proxy code to make a TempSeat. */\r
1602 Seat *tempseat_new(Seat *real);\r
1604 /* Query functions to tell if a Seat _is_ temporary, and if so, to\r
1605  * return the underlying real Seat. */\r
1606 bool is_tempseat(Seat *seat);\r
1607 Seat *tempseat_get_real(Seat *seat);\r
1609 /* Called by interactor_return_seat once the proxy connection has\r
1610  * finished setting up (or failed), to pass on any buffered stuff to\r
1611  * the real seat. */\r
1612 void tempseat_flush(Seat *ts);\r
1614 /* Frees a TempSeat, without flushing anything it has buffered. (Call\r
1615  * this after tempseat_flush, or alternatively, when you were going to\r
1616  * abandon the whole connection anyway.) */\r
1617 void tempseat_free(Seat *ts);\r
1619 typedef struct rgb {\r
1620     uint8_t r, g, b;\r
1621 } rgb;\r
1623 /*\r
1624  * Data type 'TermWin', which is a vtable encapsulating all the\r
1625  * functionality that Terminal expects from its containing terminal\r
1626  * window.\r
1627  */\r
1628 struct TermWin {\r
1629     const struct TermWinVtable *vt;\r
1630 };\r
1631 struct TermWinVtable {\r
1632     /*\r
1633      * All functions listed here between setup_draw_ctx and\r
1634      * free_draw_ctx expect to be _called_ between them too, so that\r
1635      * the TermWin has a drawing context currently available.\r
1636      *\r
1637      * (Yes, even char_width, because e.g. the Windows implementation\r
1638      * of TermWin handles it by loading the currently configured font\r
1639      * into the HDC and doing a GDI query.)\r
1640      */\r
1641     bool (*setup_draw_ctx)(TermWin *);\r
1642     /* Draw text in the window, during a painting operation */\r
1643     void (*draw_text)(TermWin *, int x, int y, wchar_t *text, int len,\r
1644                       unsigned long attrs, int line_attrs, truecolour tc);\r
1645     /* Draw the visible cursor. Expects you to have called do_text\r
1646      * first (because it might just draw an underline over a character\r
1647      * presumed to exist already), but also expects you to pass in all\r
1648      * the details of the character under the cursor (because it might\r
1649      * redraw it in different colours). */\r
1650     void (*draw_cursor)(TermWin *, int x, int y, wchar_t *text, int len,\r
1651                         unsigned long attrs, int line_attrs, truecolour tc);\r
1652     /* Draw the sigil indicating that a line of text has come from\r
1653      * PuTTY itself rather than the far end (defence against end-of-\r
1654      * authentication spoofing) */\r
1655     void (*draw_trust_sigil)(TermWin *, int x, int y);\r
1656     int (*char_width)(TermWin *, int uc);\r
1657     void (*free_draw_ctx)(TermWin *);\r
1659     void (*set_cursor_pos)(TermWin *, int x, int y);\r
1661     /* set_raw_mouse_mode instructs the front end to start sending mouse events\r
1662      * in raw mode suitable for translating into mouse-tracking terminal data\r
1663      * (e.g. include scroll-wheel events and don't bother to identify double-\r
1664      * and triple-clicks). set_raw_mouse_mode_pointer instructs the front end\r
1665      * to change the mouse pointer shape to *indicate* raw mouse mode. */\r
1666     void (*set_raw_mouse_mode)(TermWin *, bool enable);\r
1667     void (*set_raw_mouse_mode_pointer)(TermWin *, bool enable);\r
1669     void (*set_scrollbar)(TermWin *, int total, int start, int page);\r
1671     void (*bell)(TermWin *, int mode);\r
1673     void (*clip_write)(TermWin *, int clipboard, wchar_t *text, int *attrs,\r
1674                        truecolour *colours, int len, bool must_deselect);\r
1675     void (*clip_request_paste)(TermWin *, int clipboard);\r
1677     void (*refresh)(TermWin *);\r
1679     /* request_resize asks the front end if the terminal can please be\r
1680      * resized to (w,h) in characters. The front end MAY call\r
1681      * term_size() in response to tell the terminal its new size\r
1682      * (which MAY be the requested size, or some other size if the\r
1683      * requested one can't be achieved). The front end MAY also not\r
1684      * call term_size() at all. But the front end MUST reply to this\r
1685      * request by calling term_resize_request_completed(), after the\r
1686      * responding resize event has taken place (if any).\r
1687      *\r
1688      * The calls to term_size and term_resize_request_completed may be\r
1689      * synchronous callbacks from within the call to request_resize(). */\r
1690     void (*request_resize)(TermWin *, int w, int h);\r
1692     void (*set_title)(TermWin *, const char *title, int codepage);\r
1693     void (*set_icon_title)(TermWin *, const char *icontitle, int codepage);\r
1695     /* set_minimised and set_maximised are assumed to set two\r
1696      * independent settings, rather than a single three-way\r
1697      * {min,normal,max} switch. The idea is that when you un-minimise\r
1698      * the window it remembers whether to go back to normal or\r
1699      * maximised. */\r
1700     void (*set_minimised)(TermWin *, bool minimised);\r
1701     void (*set_maximised)(TermWin *, bool maximised);\r
1702     void (*move)(TermWin *, int x, int y);\r
1703     void (*set_zorder)(TermWin *, bool top);\r
1705     /* Set the colour palette that the TermWin will use to display\r
1706      * text. One call to this function sets 'ncolours' consecutive\r
1707      * colours in the OSC 4 sequence, starting at 'start'. */\r
1708     void (*palette_set)(TermWin *, unsigned start, unsigned ncolours,\r
1709                         const rgb *colours);\r
1711     /* Query the front end for any OS-local overrides to the default\r
1712      * colours stored in Conf. The front end should set any it cares\r
1713      * about by calling term_palette_override.\r
1714      *\r
1715      * The Terminal object is passed in as a parameter, because this\r
1716      * can be called as a callback from term_init(). So the TermWin\r
1717      * itself won't yet have been told where to find its Terminal\r
1718      * object, because that doesn't happen until term_init\r
1719      * returns. */\r
1720     void (*palette_get_overrides)(TermWin *, Terminal *);\r
1722     /* Notify the front end that the terminal's buffer of unprocessed\r
1723      * output has reduced. (Front ends will likely pass this straight\r
1724      * on to backend_unthrottle.) */\r
1725     void (*unthrottle)(TermWin *, size_t bufsize);\r
1726 };\r
1728 static inline bool win_setup_draw_ctx(TermWin *win)\r
1729 { return win->vt->setup_draw_ctx(win); }\r
1730 static inline void win_draw_text(\r
1731     TermWin *win, int x, int y, wchar_t *text, int len,\r
1732     unsigned long attrs, int line_attrs, truecolour tc)\r
1733 { win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc); }\r
1734 static inline void win_draw_cursor(\r
1735     TermWin *win, int x, int y, wchar_t *text, int len,\r
1736     unsigned long attrs, int line_attrs, truecolour tc)\r
1737 { win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc); }\r
1738 static inline void win_draw_trust_sigil(TermWin *win, int x, int y)\r
1739 { win->vt->draw_trust_sigil(win, x, y); }\r
1740 static inline int win_char_width(TermWin *win, int uc)\r
1741 { return win->vt->char_width(win, uc); }\r
1742 static inline void win_free_draw_ctx(TermWin *win)\r
1743 { win->vt->free_draw_ctx(win); }\r
1744 static inline void win_set_cursor_pos(TermWin *win, int x, int y)\r
1745 { win->vt->set_cursor_pos(win, x, y); }\r
1746 static inline void win_set_raw_mouse_mode(TermWin *win, bool enable)\r
1747 { win->vt->set_raw_mouse_mode(win, enable); }\r
1748 static inline void win_set_raw_mouse_mode_pointer(TermWin *win, bool enable)\r
1749 { win->vt->set_raw_mouse_mode_pointer(win, enable); }\r
1750 static inline void win_set_scrollbar(TermWin *win, int t, int s, int p)\r
1751 { win->vt->set_scrollbar(win, t, s, p); }\r
1752 static inline void win_bell(TermWin *win, int mode)\r
1753 { win->vt->bell(win, mode); }\r
1754 static inline void win_clip_write(\r
1755     TermWin *win, int clipboard, wchar_t *text, int *attrs,\r
1756     truecolour *colours, int len, bool deselect)\r
1757 { win->vt->clip_write(win, clipboard, text, attrs, colours, len, deselect); }\r
1758 static inline void win_clip_request_paste(TermWin *win, int clipboard)\r
1759 { win->vt->clip_request_paste(win, clipboard); }\r
1760 static inline void win_refresh(TermWin *win)\r
1761 { win->vt->refresh(win); }\r
1762 static inline void win_request_resize(TermWin *win, int w, int h)\r
1763 { win->vt->request_resize(win, w, h); }\r
1764 static inline void win_set_title(TermWin *win, const char *title, int codepage)\r
1765 { win->vt->set_title(win, title, codepage); }\r
1766 static inline void win_set_icon_title(TermWin *win, const char *icontitle,\r
1767                                       int codepage)\r
1768 { win->vt->set_icon_title(win, icontitle, codepage); }\r
1769 static inline void win_set_minimised(TermWin *win, bool minimised)\r
1770 { win->vt->set_minimised(win, minimised); }\r
1771 static inline void win_set_maximised(TermWin *win, bool maximised)\r
1772 { win->vt->set_maximised(win, maximised); }\r
1773 static inline void win_move(TermWin *win, int x, int y)\r
1774 { win->vt->move(win, x, y); }\r
1775 static inline void win_set_zorder(TermWin *win, bool top)\r
1776 { win->vt->set_zorder(win, top); }\r
1777 static inline void win_palette_set(\r
1778     TermWin *win, unsigned start, unsigned ncolours, const rgb *colours)\r
1779 { win->vt->palette_set(win, start, ncolours, colours); }\r
1780 static inline void win_palette_get_overrides(TermWin *win, Terminal *term)\r
1781 { win->vt->palette_get_overrides(win, term); }\r
1782 static inline void win_unthrottle(TermWin *win, size_t size)\r
1783 { win->vt->unthrottle(win, size); }\r
1785 /*\r
1786  * Global functions not specific to a connection instance.\r
1787  */\r
1788 void nonfatal(const char *, ...) PRINTF_LIKE(1, 2);\r
1789 NORETURN void modalfatalbox(const char *, ...) PRINTF_LIKE(1, 2);\r
1790 NORETURN void cleanup_exit(int);\r
1792 /*\r
1793  * Exports from conf.c, and a big enum (via parametric macro) of\r
1794  * configuration option keys.\r
1795  */\r
1796 #define CONFIG_OPTIONS(X) \\r
1797     /* X(value-type, subkey-type, keyword) */ \\r
1798     X(STR, NONE, host) \\r
1799     X(INT, NONE, port) \\r
1800     X(INT, NONE, protocol) /* PROT_SSH, PROT_TELNET etc */ \\r
1801     X(INT, NONE, addressfamily) /* ADDRTYPE_IPV[46] or ADDRTYPE_UNSPEC */ \\r
1802     X(INT, NONE, close_on_exit) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1803     X(BOOL, NONE, warn_on_close) \\r
1804     X(INT, NONE, ping_interval) /* in seconds */ \\r
1805     X(BOOL, NONE, tcp_nodelay) \\r
1806     X(BOOL, NONE, tcp_keepalives) \\r
1807     X(STR, NONE, loghost) /* logical host being contacted, for host key check */ \\r
1808     /* Proxy options */ \\r
1809     X(STR, NONE, proxy_exclude_list) \\r
1810     X(INT, NONE, proxy_dns) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1811     X(BOOL, NONE, even_proxy_localhost) \\r
1812     X(INT, NONE, proxy_type) /* PROXY_NONE, PROXY_SOCKS4, ... */ \\r
1813     X(STR, NONE, proxy_host) \\r
1814     X(INT, NONE, proxy_port) \\r
1815     X(STR, NONE, proxy_username) \\r
1816     X(STR, NONE, proxy_password) \\r
1817     X(STR, NONE, proxy_telnet_command) \\r
1818     X(INT, NONE, proxy_log_to_term) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1819     /* SSH options */ \\r
1820     X(STR, NONE, remote_cmd) \\r
1821     X(STR, NONE, remote_cmd2) /* fallback if remote_cmd fails; never loaded or saved */ \\r
1822     X(BOOL, NONE, nopty) \\r
1823     X(BOOL, NONE, compression) \\r
1824     X(INT, INT, ssh_kexlist) \\r
1825     X(INT, INT, ssh_hklist) \\r
1826     X(BOOL, NONE, ssh_prefer_known_hostkeys) \\r
1827     X(INT, NONE, ssh_rekey_time) /* in minutes */ \\r
1828     X(STR, NONE, ssh_rekey_data) /* string encoding e.g. "100K", "2M", "1G" */ \\r
1829     X(BOOL, NONE, tryagent) \\r
1830     X(BOOL, NONE, agentfwd) \\r
1831     X(BOOL, NONE, change_username) /* allow username switching in SSH-2 */ \\r
1832     X(INT, INT, ssh_cipherlist) \\r
1833     X(FILENAME, NONE, keyfile) \\r
1834     X(FILENAME, NONE, detached_cert) \\r
1835     X(STR, NONE, auth_plugin) \\r
1836     /* \\r
1837      * Which SSH protocol to use. \\r
1838      * For historical reasons, the current legal values for CONF_sshprot \\r
1839      * are: \\r
1840      *  0 = SSH-1 only \\r
1841      *  3 = SSH-2 only \\r
1842      * We used to also support \\r
1843      *  1 = SSH-1 with fallback to SSH-2 \\r
1844      *  2 = SSH-2 with fallback to SSH-1 \\r
1845      * and we continue to use 0/3 in storage formats rather than the more \\r
1846      * obvious 1/2 to avoid surprises if someone saves a session and later \\r
1847      * downgrades PuTTY. So it's easier to use these numbers internally too. \\r
1848      */ \\r
1849     X(INT, NONE, sshprot) \\r
1850     X(BOOL, NONE, ssh2_des_cbc) /* "des-cbc" unrecommended SSH-2 cipher */ \\r
1851     X(BOOL, NONE, ssh_no_userauth) /* bypass "ssh-userauth" (SSH-2 only) */ \\r
1852     X(BOOL, NONE, ssh_no_trivial_userauth) /* disable trivial types of auth */ \\r
1853     X(BOOL, NONE, ssh_show_banner) /* show USERAUTH_BANNERs (SSH-2 only) */ \\r
1854     X(BOOL, NONE, try_tis_auth) \\r
1855     X(BOOL, NONE, try_ki_auth) \\r
1856     X(BOOL, NONE, try_gssapi_auth) /* attempt gssapi auth via ssh userauth */ \\r
1857     X(BOOL, NONE, try_gssapi_kex) /* attempt gssapi auth via ssh kex */ \\r
1858     X(BOOL, NONE, gssapifwd) /* forward tgt via gss */ \\r
1859     X(INT, NONE, gssapirekey) /* KEXGSS refresh interval (mins) */ \\r
1860     X(INT, INT, ssh_gsslist) /* preference order for local GSS libs */ \\r
1861     X(FILENAME, NONE, ssh_gss_custom) \\r
1862     X(BOOL, NONE, ssh_subsys) /* run a subsystem rather than a command */ \\r
1863     X(BOOL, NONE, ssh_subsys2) /* fallback to go with remote_cmd_ptr2 */ \\r
1864     X(BOOL, NONE, ssh_no_shell) /* avoid running a shell */ \\r
1865     X(STR, NONE, ssh_nc_host) /* host to connect to in `nc' mode */ \\r
1866     X(INT, NONE, ssh_nc_port) /* port to connect to in `nc' mode */ \\r
1867     /* Telnet options */ \\r
1868     X(STR, NONE, termtype) \\r
1869     X(STR, NONE, termspeed) \\r
1870     X(STR, STR, ttymodes) /* values are "Vvalue" or "A" */ \\r
1871     X(STR, STR, environmt) \\r
1872     X(STR, NONE, username) \\r
1873     X(BOOL, NONE, username_from_env) \\r
1874     X(STR, NONE, localusername) \\r
1875     X(BOOL, NONE, rfc_environ) \\r
1876     X(BOOL, NONE, passive_telnet) \\r
1877     /* Serial port options */ \\r
1878     X(STR, NONE, serline) \\r
1879     X(INT, NONE, serspeed) \\r
1880     X(INT, NONE, serdatabits) \\r
1881     X(INT, NONE, serstopbits) \\r
1882     X(INT, NONE, serparity) /* SER_PAR_NONE, SER_PAR_ODD, ... */ \\r
1883     X(INT, NONE, serflow) /* SER_FLOW_NONE, SER_FLOW_XONXOFF, ... */ \\r
1884     /* Supdup options */ \\r
1885     X(STR, NONE, supdup_location) \\r
1886     X(INT, NONE, supdup_ascii_set) \\r
1887     X(BOOL, NONE, supdup_more) \\r
1888     X(BOOL, NONE, supdup_scroll) \\r
1889     /* Keyboard options */ \\r
1890     X(BOOL, NONE, bksp_is_delete) \\r
1891     X(BOOL, NONE, rxvt_homeend) \\r
1892     X(INT, NONE, funky_type) /* FUNKY_XTERM, FUNKY_LINUX, ... */ \\r
1893     X(INT, NONE, sharrow_type) /* SHARROW_APPLICATION, SHARROW_BITMAP, ... */ \\r
1894     X(BOOL, NONE, no_applic_c) /* totally disable app cursor keys */ \\r
1895     X(BOOL, NONE, no_applic_k) /* totally disable app keypad */ \\r
1896     X(BOOL, NONE, no_mouse_rep) /* totally disable mouse reporting */ \\r
1897     X(BOOL, NONE, no_remote_resize) /* disable remote resizing */ \\r
1898     X(BOOL, NONE, no_alt_screen) /* disable alternate screen */ \\r
1899     X(BOOL, NONE, no_remote_wintitle) /* disable remote retitling */ \\r
1900     X(BOOL, NONE, no_remote_clearscroll) /* disable ESC[3J */ \\r
1901     X(BOOL, NONE, no_dbackspace) /* disable destructive backspace */ \\r
1902     X(BOOL, NONE, no_remote_charset) /* disable remote charset config */ \\r
1903     X(INT, NONE, remote_qtitle_action) /* remote win title query action\r
1904                                        * (TITLE_NONE, TITLE_EMPTY, ...) */ \\r
1905     X(BOOL, NONE, app_cursor) \\r
1906     X(BOOL, NONE, app_keypad) \\r
1907     X(BOOL, NONE, nethack_keypad) \\r
1908     X(BOOL, NONE, telnet_keyboard) \\r
1909     X(BOOL, NONE, telnet_newline) \\r
1910     X(BOOL, NONE, alt_f4) /* is it special? */ \\r
1911     X(BOOL, NONE, alt_space) /* is it special? */ \\r
1912     X(BOOL, NONE, alt_only) /* is it special? */ \\r
1913     X(INT, NONE, localecho) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1914     X(INT, NONE, localedit) /* FORCE_ON, FORCE_OFF, AUTO */ \\r
1915     X(BOOL, NONE, alwaysontop) \\r
1916     X(BOOL, NONE, fullscreenonaltenter) \\r
1917     X(BOOL, NONE, scroll_on_key) \\r
1918     X(BOOL, NONE, scroll_on_disp) \\r
1919     X(BOOL, NONE, erase_to_scrollback) \\r
1920     X(BOOL, NONE, compose_key) \\r
1921     X(BOOL, NONE, ctrlaltkeys) \\r
1922     X(BOOL, NONE, osx_option_meta) \\r
1923     X(BOOL, NONE, osx_command_meta) \\r
1924     X(STR, NONE, wintitle) /* initial window title */ \\r
1925     /* Terminal options */ \\r
1926     X(INT, NONE, savelines) \\r
1927     X(BOOL, NONE, dec_om) \\r
1928     X(BOOL, NONE, wrap_mode) \\r
1929     X(BOOL, NONE, lfhascr) \\r
1930     X(INT, NONE, cursor_type) /* 0=block 1=underline 2=vertical */ \\r
1931     X(BOOL, NONE, blink_cur) \\r
1932     X(INT, NONE, beep) /* BELL_DISABLED, BELL_DEFAULT, ... */ \\r
1933     X(INT, NONE, beep_ind) /* B_IND_DISABLED, B_IND_FLASH, ... */ \\r
1934     X(BOOL, NONE, bellovl) /* bell overload protection active? */ \\r
1935     X(INT, NONE, bellovl_n) /* number of bells to cause overload */ \\r
1936     X(INT, NONE, bellovl_t) /* time interval for overload (seconds) */ \\r
1937     X(INT, NONE, bellovl_s) /* period of silence to re-enable bell (s) */ \\r
1938     X(FILENAME, NONE, bell_wavefile) \\r
1939     X(BOOL, NONE, scrollbar) \\r
1940     X(BOOL, NONE, scrollbar_in_fullscreen) \\r
1941     X(INT, NONE, resize_action) /* RESIZE_TERM, RESIZE_DISABLED, ... */ \\r
1942     X(BOOL, NONE, bce) \\r
1943     X(BOOL, NONE, blinktext) \\r
1944     X(BOOL, NONE, win_name_always) \\r
1945     X(INT, NONE, width) \\r
1946     X(INT, NONE, height) \\r
1947     X(FONT, NONE, font) \\r
1948     X(INT, NONE, font_quality) /* FQ_DEFAULT, FQ_ANTIALIASED, ... */ \\r
1949     X(FILENAME, NONE, logfilename) \\r
1950     X(INT, NONE, logtype) /* LGTYP_NONE, LGTYPE_ASCII, ... */ \\r
1951     X(INT, NONE, logxfovr) /* LGXF_OVR, LGXF_APN, LGXF_ASK */ \\r
1952     X(BOOL, NONE, logflush) \\r
1953     X(BOOL, NONE, logheader) \\r
1954     X(BOOL, NONE, logomitpass) \\r
1955     X(BOOL, NONE, logomitdata) \\r
1956     X(BOOL, NONE, hide_mouseptr) \\r
1957     X(BOOL, NONE, sunken_edge) \\r
1958     X(INT, NONE, window_border) /* in pixels */ \\r
1959     X(STR, NONE, answerback) \\r
1960     X(STR, NONE, printer) \\r
1961     X(BOOL, NONE, no_arabicshaping) \\r
1962     X(BOOL, NONE, no_bidi) \\r
1963     /* Colour options */ \\r
1964     X(BOOL, NONE, ansi_colour) \\r
1965     X(BOOL, NONE, xterm_256_colour) \\r
1966     X(BOOL, NONE, true_colour) \\r
1967     X(BOOL, NONE, system_colour) \\r
1968     X(BOOL, NONE, try_palette) \\r
1969     X(INT, NONE, bold_style) /* 1=font 2=colour (3=both) */ \\r
1970     X(INT, INT, colours) /* indexed by the CONF_COLOUR_* enum encoding */ \\r
1971     /* Selection options */ \\r
1972     X(INT, NONE, mouse_is_xterm) /* 0=compromise 1=xterm 2=Windows */ \\r
1973     X(BOOL, NONE, rect_select) \\r
1974     X(BOOL, NONE, paste_controls) \\r
1975     X(BOOL, NONE, rawcnp) \\r
1976     X(BOOL, NONE, utf8linedraw) \\r
1977     X(BOOL, NONE, rtf_paste) \\r
1978     X(BOOL, NONE, mouse_override) \\r
1979     X(INT, INT, wordness) \\r
1980     X(BOOL, NONE, mouseautocopy) \\r
1981     X(INT, NONE, mousepaste) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1982     X(INT, NONE, ctrlshiftins) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1983     X(INT, NONE, ctrlshiftcv) /* CLIPUI_IMPLICIT, CLIPUI_EXPLICIT, ... */ \\r
1984     X(STR, NONE, mousepaste_custom) \\r
1985     X(STR, NONE, ctrlshiftins_custom) \\r
1986     X(STR, NONE, ctrlshiftcv_custom) \\r
1987     /* translations */ \\r
1988     X(INT, NONE, vtmode) /* VT_XWINDOWS, VT_OEMANSI, ... */ \\r
1989     X(STR, NONE, line_codepage) \\r
1990     X(BOOL, NONE, cjk_ambig_wide) \\r
1991     X(BOOL, NONE, utf8_override) \\r
1992     X(BOOL, NONE, xlat_capslockcyr) \\r
1993     /* X11 forwarding */ \\r
1994     X(BOOL, NONE, x11_forward) \\r
1995     X(STR, NONE, x11_display) \\r
1996     X(INT, NONE, x11_auth) /* X11_NO_AUTH, X11_MIT, X11_XDM */ \\r
1997     X(FILENAME, NONE, xauthfile) \\r
1998     /* port forwarding */ \\r
1999     X(BOOL, NONE, lport_acceptall) /* accept conns from hosts other than localhost */ \\r
2000     X(BOOL, NONE, rport_acceptall) /* same for remote forwarded ports (SSH-2 only) */ \\r
2001     /*                                                                \\r
2002      * Subkeys for 'portfwd' can have the following forms:            \\r
2003      *                                                                \\r
2004      *   [LR]localport                                                \\r
2005      *   [LR]localaddr:localport                                      \\r
2006      *                                                                \\r
2007      * Dynamic forwardings are indicated by an 'L' key, and the       \\r
2008      * special value "D". For all other forwardings, the value        \\r
2009      * should be of the form 'host:port'.                             \\r
2010      */ \\r
2011     X(STR, STR, portfwd) \\r
2012     /* SSH bug compatibility modes. All FORCE_ON/FORCE_OFF/AUTO */ \\r
2013     X(INT, NONE, sshbug_ignore1) \\r
2014     X(INT, NONE, sshbug_plainpw1) \\r
2015     X(INT, NONE, sshbug_rsa1) \\r
2016     X(INT, NONE, sshbug_hmac2) \\r
2017     X(INT, NONE, sshbug_derivekey2) \\r
2018     X(INT, NONE, sshbug_rsapad2) \\r
2019     X(INT, NONE, sshbug_pksessid2) \\r
2020     X(INT, NONE, sshbug_rekey2) \\r
2021     X(INT, NONE, sshbug_maxpkt2) \\r
2022     X(INT, NONE, sshbug_ignore2) \\r
2023     X(INT, NONE, sshbug_oldgex2) \\r
2024     X(INT, NONE, sshbug_winadj) \\r
2025     X(INT, NONE, sshbug_chanreq) \\r
2026     X(INT, NONE, sshbug_dropstart) \\r
2027     X(INT, NONE, sshbug_filter_kexinit) \\r
2028     X(INT, NONE, sshbug_rsa_sha2_cert_userauth) \\r
2029     /*                                                                \\r
2030      * ssh_simple means that we promise never to open any channel     \\r
2031      * other than the main one, which means it can safely use a very  \\r
2032      * large window in SSH-2.                                         \\r
2033      */ \\r
2034     X(BOOL, NONE, ssh_simple) \\r
2035     X(BOOL, NONE, ssh_connection_sharing) \\r
2036     X(BOOL, NONE, ssh_connection_sharing_upstream) \\r
2037     X(BOOL, NONE, ssh_connection_sharing_downstream) \\r
2038     /*\r
2039      * ssh_manual_hostkeys is conceptually a set rather than a\r
2040      * dictionary: the string subkeys are the important thing, and the\r
2041      * actual values to which those subkeys map are all "".\r
2042      */ \\r
2043     X(STR, STR, ssh_manual_hostkeys) \\r
2044     /* Options for pterm. Should split out into platform-dependent part. */ \\r
2045     X(BOOL, NONE, stamp_utmp) \\r
2046     X(BOOL, NONE, login_shell) \\r
2047     X(BOOL, NONE, scrollbar_on_left) \\r
2048     X(BOOL, NONE, shadowbold) \\r
2049     X(FONT, NONE, boldfont) \\r
2050     X(FONT, NONE, widefont) \\r
2051     X(FONT, NONE, wideboldfont) \\r
2052     X(INT, NONE, shadowboldoffset) /* in pixels */ \\r
2053     X(BOOL, NONE, crhaslf) \\r
2054     X(STR, NONE, winclass) \\r
2055     /* end of list */\r
2057 /* Now define the actual enum of option keywords using that macro. */\r
2058 #define CONF_ENUM_DEF(valtype, keytype, keyword) CONF_ ## keyword,\r
2059 enum config_primary_key { CONFIG_OPTIONS(CONF_ENUM_DEF) N_CONFIG_OPTIONS };\r
2060 #undef CONF_ENUM_DEF\r
2062 /* Functions handling configuration structures. */\r
2063 Conf *conf_new(void);                  /* create an empty configuration */\r
2064 void conf_free(Conf *conf);\r
2065 Conf *conf_copy(Conf *oldconf);\r
2066 void conf_copy_into(Conf *dest, Conf *src);\r
2067 /* Mandatory accessor functions: enforce by assertion that keys exist. */\r
2068 bool conf_get_bool(Conf *conf, int key);\r
2069 int conf_get_int(Conf *conf, int key);\r
2070 int conf_get_int_int(Conf *conf, int key, int subkey);\r
2071 char *conf_get_str(Conf *conf, int key);   /* result still owned by conf */\r
2072 char *conf_get_str_str(Conf *conf, int key, const char *subkey);\r
2073 Filename *conf_get_filename(Conf *conf, int key);\r
2074 FontSpec *conf_get_fontspec(Conf *conf, int key); /* still owned by conf */\r
2075 /* Optional accessor function: return NULL if key does not exist. */\r
2076 char *conf_get_str_str_opt(Conf *conf, int key, const char *subkey);\r
2077 /* Accessor function to step through a string-subkeyed list.\r
2078  * Returns the next subkey after the provided one, or the first if NULL.\r
2079  * Returns NULL if there are none left.\r
2080  * Both the return value and *subkeyout are still owned by conf. */\r
2081 char *conf_get_str_strs(Conf *conf, int key, char *subkeyin, char **subkeyout);\r
2082 /* Return the nth string subkey in a list. Owned by conf. NULL if beyond end */\r
2083 char *conf_get_str_nthstrkey(Conf *conf, int key, int n);\r
2084 /* Functions to set entries in configuration. Always copy their inputs. */\r
2085 void conf_set_bool(Conf *conf, int key, bool value);\r
2086 void conf_set_int(Conf *conf, int key, int value);\r
2087 void conf_set_int_int(Conf *conf, int key, int subkey, int value);\r
2088 void conf_set_str(Conf *conf, int key, const char *value);\r
2089 void conf_set_str_str(Conf *conf, int key,\r
2090                       const char *subkey, const char *val);\r
2091 void conf_del_str_str(Conf *conf, int key, const char *subkey);\r
2092 void conf_set_filename(Conf *conf, int key, const Filename *val);\r
2093 void conf_set_fontspec(Conf *conf, int key, const FontSpec *val);\r
2094 /* Serialisation functions for Duplicate Session */\r
2095 void conf_serialise(BinarySink *bs, Conf *conf);\r
2096 bool conf_deserialise(Conf *conf, BinarySource *src);/*returns true on success*/\r
2098 /*\r
2099  * Functions to copy, free, serialise and deserialise FontSpecs.\r
2100  * Provided per-platform, to go with the platform's idea of a\r
2101  * FontSpec's contents.\r
2102  */\r
2103 FontSpec *fontspec_copy(const FontSpec *f);\r
2104 void fontspec_free(FontSpec *f);\r
2105 void fontspec_serialise(BinarySink *bs, FontSpec *f);\r
2106 FontSpec *fontspec_deserialise(BinarySource *src);\r
2108 /*\r
2109  * Exports from each platform's noise.c.\r
2110  */\r
2111 typedef enum NoiseSourceId {\r
2112     NOISE_SOURCE_TIME,\r
2113     NOISE_SOURCE_IOID,\r
2114     NOISE_SOURCE_IOLEN,\r
2115     NOISE_SOURCE_KEY,\r
2116     NOISE_SOURCE_MOUSEBUTTON,\r
2117     NOISE_SOURCE_MOUSEPOS,\r
2118     NOISE_SOURCE_MEMINFO,\r
2119     NOISE_SOURCE_STAT,\r
2120     NOISE_SOURCE_RUSAGE,\r
2121     NOISE_SOURCE_FGWINDOW,\r
2122     NOISE_SOURCE_CAPTURE,\r
2123     NOISE_SOURCE_CLIPBOARD,\r
2124     NOISE_SOURCE_QUEUE,\r
2125     NOISE_SOURCE_CURSORPOS,\r
2126     NOISE_SOURCE_THREADTIME,\r
2127     NOISE_SOURCE_PROCTIME,\r
2128     NOISE_SOURCE_PERFCOUNT,\r
2129     NOISE_MAX_SOURCES\r
2130 } NoiseSourceId;\r
2131 void noise_get_heavy(void (*func) (void *, int));\r
2132 void noise_get_light(void (*func) (void *, int));\r
2133 void noise_regular(void);\r
2134 void noise_ultralight(NoiseSourceId id, unsigned long data);\r
2136 /*\r
2137  * Exports from sshrand.c.\r
2138  */\r
2139 void random_save_seed(void);\r
2140 void random_destroy_seed(void);\r
2142 /*\r
2143  * Exports from settings.c.\r
2144  *\r
2145  * load_settings() and do_defaults() return false if the provided\r
2146  * session name didn't actually exist. But they still fill in the\r
2147  * provided Conf with _something_.\r
2148  */\r
2149 const struct BackendVtable *backend_vt_from_name(const char *name);\r
2150 const struct BackendVtable *backend_vt_from_proto(int proto);\r
2151 char *get_remote_username(Conf *conf); /* dynamically allocated */\r
2152 char *save_settings(const char *section, Conf *conf);\r
2153 void save_open_settings(settings_w *sesskey, Conf *conf);\r
2154 bool load_settings(const char *section, Conf *conf);\r
2155 void load_open_settings(settings_r *sesskey, Conf *conf);\r
2156 void get_sesslist(struct sesslist *, bool allocate);\r
2157 bool do_defaults(const char *, Conf *);\r
2158 void registry_cleanup(void);\r
2159 void settings_set_default_protocol(int);\r
2160 void settings_set_default_port(int);\r
2162 /*\r
2163  * Functions used by settings.c to provide platform-specific\r
2164  * default settings.\r
2165  *\r
2166  * (The integer one is expected to return `def' if it has no clear\r
2167  * opinion of its own. This is because there's no integer value\r
2168  * which I can reliably set aside to indicate `nil'. The string\r
2169  * function is perfectly all right returning NULL, of course. The\r
2170  * Filename and FontSpec functions are _not allowed_ to fail to\r
2171  * return, since these defaults _must_ be per-platform.)\r
2172  *\r
2173  * The 'Filename *' returned by platform_default_filename, and the\r
2174  * 'FontSpec *' returned by platform_default_fontspec, have ownership\r
2175  * transferred to the caller, and must be freed.\r
2176  */\r
2177 char *platform_default_s(const char *name);\r
2178 bool platform_default_b(const char *name, bool def);\r
2179 int platform_default_i(const char *name, int def);\r
2180 Filename *platform_default_filename(const char *name);\r
2181 FontSpec *platform_default_fontspec(const char *name);\r
2183 /*\r
2184  * Exports from terminal.c.\r
2185  */\r
2187 Terminal *term_init(Conf *, struct unicode_data *, TermWin *);\r
2188 void term_free(Terminal *);\r
2189 void term_size(Terminal *, int, int, int);\r
2190 void term_resize_request_completed(Terminal *);\r
2191 void term_paint(Terminal *, int, int, int, int, bool);\r
2192 void term_scroll(Terminal *, int, int);\r
2193 void term_scroll_to_selection(Terminal *, int);\r
2194 void term_pwron(Terminal *, bool);\r
2195 void term_clrsb(Terminal *);\r
2196 void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action,\r
2197                 int, int, bool, bool, bool);\r
2198 void term_cancel_selection_drag(Terminal *);\r
2199 void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int,\r
2200               unsigned int);\r
2201 void term_lost_clipboard_ownership(Terminal *, int clipboard);\r
2202 void term_update(Terminal *);\r
2203 void term_invalidate(Terminal *);\r
2204 void term_blink(Terminal *, bool set_cursor);\r
2205 void term_do_paste(Terminal *, const wchar_t *, int);\r
2206 void term_nopaste(Terminal *);\r
2207 void term_copyall(Terminal *, const int *, int);\r
2208 void term_pre_reconfig(Terminal *, Conf *);\r
2209 void term_reconfig(Terminal *, Conf *);\r
2210 void term_request_copy(Terminal *, const int *clipboards, int n_clipboards);\r
2211 void term_request_paste(Terminal *, int clipboard);\r
2212 void term_seen_key_event(Terminal *);\r
2213 size_t term_data(Terminal *, const void *data, size_t len);\r
2214 void term_provide_backend(Terminal *term, Backend *backend);\r
2215 void term_provide_logctx(Terminal *term, LogContext *logctx);\r
2216 void term_set_focus(Terminal *term, bool has_focus);\r
2217 char *term_get_ttymode(Terminal *term, const char *mode);\r
2218 SeatPromptResult term_get_userpass_input(Terminal *term, prompts_t *p);\r
2219 void term_set_trust_status(Terminal *term, bool trusted);\r
2220 void term_keyinput(Terminal *, int codepage, const void *buf, int len);\r
2221 void term_keyinputw(Terminal *, const wchar_t *widebuf, int len);\r
2222 void term_get_cursor_position(Terminal *term, int *x, int *y);\r
2223 void term_setup_window_titles(Terminal *term, const char *title_hostname);\r
2224 void term_notify_minimised(Terminal *term, bool minimised);\r
2225 void term_notify_palette_changed(Terminal *term);\r
2226 void term_notify_window_pos(Terminal *term, int x, int y);\r
2227 void term_notify_window_size_pixels(Terminal *term, int x, int y);\r
2228 void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb);\r
2230 typedef enum SmallKeypadKey {\r
2231     SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN,\r
2232 } SmallKeypadKey;\r
2233 int format_arrow_key(char *buf, Terminal *term, int xkey,\r
2234                      bool shift, bool ctrl, bool alt, bool *consumed_alt);\r
2235 int format_function_key(char *buf, Terminal *term, int key_number,\r
2236                         bool shift, bool ctrl, bool alt, bool *consumed_alt);\r
2237 int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key,\r
2238                             bool shift, bool ctrl, bool alt,\r
2239                             bool *consumed_alt);\r
2240 int format_numeric_keypad_key(char *buf, Terminal *term, char key,\r
2241                               bool shift, bool ctrl);\r
2243 /*\r
2244  * Exports from logging.c.\r
2245  */\r
2246 struct LogPolicyVtable {\r
2247     /*\r
2248      * Pass Event Log entries on from LogContext to the front end,\r
2249      * which might write them to standard error or save them for a GUI\r
2250      * list box or other things.\r
2251      */\r
2252     void (*eventlog)(LogPolicy *lp, const char *event);\r
2254     /*\r
2255      * Ask what to do about the specified output log file already\r
2256      * existing. Can return four values:\r
2257      *\r
2258      *  - 2 means overwrite the log file\r
2259      *  - 1 means append to the log file\r
2260      *  - 0 means cancel logging for this session\r
2261      *  - -1 means please wait, and callback() will be called with one\r
2262      *    of those options.\r
2263      */\r
2264     int (*askappend)(LogPolicy *lp, Filename *filename,\r
2265                      void (*callback)(void *ctx, int result), void *ctx);\r
2267     /*\r
2268      * Emergency logging when the log file itself can't be opened,\r
2269      * which typically means we want to shout about it more loudly\r
2270      * than a mere Event Log entry.\r
2271      *\r
2272      * One reasonable option is to send it to the same place that\r
2273      * stderr output from the main session goes (so, either a console\r
2274      * tool's actual stderr, or a terminal window). In many cases this\r
2275      * is unlikely to cause this error message to turn up\r
2276      * embarrassingly in a log file of real server output, because the\r
2277      * whole point is that we haven't managed to open any such log\r
2278      * file :-)\r
2279      */\r
2280     void (*logging_error)(LogPolicy *lp, const char *event);\r
2282     /*\r
2283      * Ask whether extra verbose log messages are required.\r
2284      */\r
2285     bool (*verbose)(LogPolicy *lp);\r
2286 };\r
2287 struct LogPolicy {\r
2288     const LogPolicyVtable *vt;\r
2289 };\r
2291 static inline void lp_eventlog(LogPolicy *lp, const char *event)\r
2292 { lp->vt->eventlog(lp, event); }\r
2293 static inline int lp_askappend(\r
2294     LogPolicy *lp, Filename *filename,\r
2295     void (*callback)(void *ctx, int result), void *ctx)\r
2296 { return lp->vt->askappend(lp, filename, callback, ctx); }\r
2297 static inline void lp_logging_error(LogPolicy *lp, const char *event)\r
2298 { lp->vt->logging_error(lp, event); }\r
2299 static inline bool lp_verbose(LogPolicy *lp)\r
2300 { return lp->vt->verbose(lp); }\r
2302 /* Defined in clicons.c, used in several console command-line tools */\r
2303 extern LogPolicy console_cli_logpolicy[];\r
2305 int console_askappend(LogPolicy *lp, Filename *filename,\r
2306                       void (*callback)(void *ctx, int result), void *ctx);\r
2307 void console_logging_error(LogPolicy *lp, const char *string);\r
2308 void console_eventlog(LogPolicy *lp, const char *string);\r
2309 bool null_lp_verbose_yes(LogPolicy *lp);\r
2310 bool null_lp_verbose_no(LogPolicy *lp);\r
2311 bool cmdline_lp_verbose(LogPolicy *lp);\r
2313 LogContext *log_init(LogPolicy *lp, Conf *conf);\r
2314 void log_free(LogContext *logctx);\r
2315 void log_reconfig(LogContext *logctx, Conf *conf);\r
2316 void logfopen(LogContext *logctx);\r
2317 void logfclose(LogContext *logctx);\r
2318 void logtraffic(LogContext *logctx, unsigned char c, int logmode);\r
2319 void logflush(LogContext *logctx);\r
2320 LogPolicy *log_get_policy(LogContext *logctx);\r
2321 void logevent(LogContext *logctx, const char *event);\r
2322 void logeventf(LogContext *logctx, const char *fmt, ...) PRINTF_LIKE(2, 3);\r
2323 void logeventvf(LogContext *logctx, const char *fmt, va_list ap);\r
2325 /*\r
2326  * Pass a dynamically allocated string to logevent and immediately\r
2327  * free it. Intended for use by wrapper macros which pass the return\r
2328  * value of dupprintf straight to this.\r
2329  */\r
2330 void logevent_and_free(LogContext *logctx, char *event);\r
2331 enum { PKT_INCOMING, PKT_OUTGOING };\r
2332 enum { PKTLOG_EMIT, PKTLOG_BLANK, PKTLOG_OMIT };\r
2333 struct logblank_t {\r
2334     int offset;\r
2335     int len;\r
2336     int type;\r
2337 };\r
2338 void log_packet(LogContext *logctx, int direction, int type,\r
2339                 const char *texttype, const void *data, size_t len,\r
2340                 int n_blanks, const struct logblank_t *blanks,\r
2341                 const unsigned long *sequence,\r
2342                 unsigned downstream_id, const char *additional_log_text);\r
2344 /*\r
2345  * Exports from testback.c\r
2346  */\r
2348 extern const struct BackendVtable null_backend;\r
2349 extern const struct BackendVtable loop_backend;\r
2351 /*\r
2352  * Exports from raw.c.\r
2353  */\r
2355 extern const struct BackendVtable raw_backend;\r
2357 /*\r
2358  * Exports from rlogin.c.\r
2359  */\r
2361 extern const struct BackendVtable rlogin_backend;\r
2363 /*\r
2364  * Exports from telnet.c.\r
2365  */\r
2367 extern const struct BackendVtable telnet_backend;\r
2369 /*\r
2370  * Exports from ssh/ssh.c.\r
2371  */\r
2372 extern const struct BackendVtable ssh_backend;\r
2373 extern const struct BackendVtable sshconn_backend;\r
2375 /*\r
2376  * Exports from supdup.c.\r
2377  */\r
2378 extern const struct BackendVtable supdup_backend;\r
2380 /*\r
2381  * Exports from ldisc.c.\r
2382  */\r
2383 Ldisc *ldisc_create(Conf *, Terminal *, Backend *, Seat *);\r
2384 void ldisc_configure(Ldisc *, Conf *);\r
2385 void ldisc_free(Ldisc *);\r
2386 void ldisc_send(Ldisc *, const void *buf, int len, bool interactive);\r
2387 void ldisc_echoedit_update(Ldisc *);\r
2388 typedef struct LdiscInputToken {\r
2389     /*\r
2390      * Structure that encodes any single item of data that Ldisc can\r
2391      * buffer: either a single character of raw data, or a session\r
2392      * special.\r
2393      */\r
2394     bool is_special;\r
2395     union {\r
2396         struct {\r
2397             /* if is_special == false */\r
2398             char chr;\r
2399         };\r
2400         struct {\r
2401             /* if is_special == true */\r
2402             SessionSpecialCode code;\r
2403             int arg;\r
2404         };\r
2405     };\r
2406 } LdiscInputToken;\r
2407 bool ldisc_has_input_buffered(Ldisc *);\r
2408 LdiscInputToken ldisc_get_input_token(Ldisc *); /* asserts there is input */\r
2409 void ldisc_enable_prompt_callback(Ldisc *, prompts_t *);\r
2410 void ldisc_check_sendok(Ldisc *);\r
2412 /*\r
2413  * Exports from sshrand.c.\r
2414  */\r
2416 void random_add_noise(NoiseSourceId source, const void *noise, int length);\r
2417 void random_read(void *buf, size_t size);\r
2418 void random_get_savedata(void **data, int *len);\r
2419 extern int random_active;\r
2420 /* The random number subsystem is activated if at least one other entity\r
2421  * within the program expresses an interest in it. So each SSH session\r
2422  * calls random_ref on startup and random_unref on shutdown. */\r
2423 void random_ref(void);\r
2424 void random_unref(void);\r
2425 /* random_clear is equivalent to calling random_unref as many times as\r
2426  * necessary to shut down the global PRNG instance completely. It's\r
2427  * not needed in normal applications, but the command-line PuTTYgen\r
2428  * test finds it useful to clean up after each invocation of the\r
2429  * logical main() no matter whether it needed random numbers or\r
2430  * not. */\r
2431 void random_clear(void);\r
2432 /* random_setup_custom sets up the process-global random number\r
2433  * generator specially, with a hash function of your choice. */\r
2434 void random_setup_custom(const ssh_hashalg *hash);\r
2435 /* random_setup_special() is a macro wrapper on that, which makes an\r
2436  * extra-big one based on the largest hash function we have. It's\r
2437  * defined this way to avoid what would otherwise be an unnecessary\r
2438  * module dependency from sshrand.c to a hash function implementation. */\r
2439 #define random_setup_special() random_setup_custom(&ssh_shake256_114bytes)\r
2440 /* Manually drop a random seed into the random number generator, e.g.\r
2441  * just before generating a key. */\r
2442 void random_reseed(ptrlen seed);\r
2443 /* Limit on how much entropy is worth putting into the generator (bits). */\r
2444 size_t random_seed_bits(void);\r
2446 /*\r
2447  * Exports from pinger.c.\r
2448  */\r
2449 typedef struct Pinger Pinger;\r
2450 Pinger *pinger_new(Conf *conf, Backend *backend);\r
2451 void pinger_reconfig(Pinger *, Conf *oldconf, Conf *newconf);\r
2452 void pinger_free(Pinger *);\r
2454 /*\r
2455  * Exports from modules in utils.\r
2456  */\r
2458 #include "misc.h"\r
2459 bool conf_launchable(Conf *conf);\r
2460 char const *conf_dest(Conf *conf);\r
2462 /*\r
2463  * Exports from sessprep.c.\r
2464  */\r
2465 void prepare_session(Conf *conf);\r
2467 /*\r
2468  * Exports from version.c and cmake_commit.c.\r
2469  */\r
2470 extern const char ver[];\r
2471 extern const char commitid[];\r
2473 /*\r
2474  * Exports from unicode.c in platform subdirs.\r
2475  */\r
2476 #ifndef CP_UTF8\r
2477 #define CP_UTF8 65001\r
2478 #endif\r
2479 /* void init_ucs(void); -- this is now in platform-specific headers */\r
2480 bool is_dbcs_leadbyte(int codepage, char byte);\r
2481 int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,\r
2482              wchar_t *wcstr, int wclen);\r
2483 int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,\r
2484              char *mbstr, int mblen, const char *defchr);\r
2485 wchar_t xlat_uskbd2cyrllic(int ch);\r
2486 int check_compose(int first, int second);\r
2487 int decode_codepage(const char *cp_name);\r
2488 const char *cp_enumerate (int index);\r
2489 const char *cp_name(int codepage);\r
2490 void get_unitab(int codepage, wchar_t *unitab, int ftype);\r
2492 /*\r
2493  * Exports from wcwidth.c\r
2494  */\r
2495 int mk_wcwidth(unsigned int ucs);\r
2496 int mk_wcswidth(const unsigned int *pwcs, size_t n);\r
2497 int mk_wcwidth_cjk(unsigned int ucs);\r
2498 int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n);\r
2500 /*\r
2501  * Exports from agent-client.c in platform subdirs.\r
2502  *\r
2503  * agent_query returns NULL for here's-a-response, and non-NULL for\r
2504  * query-in- progress. In the latter case there will be a call to\r
2505  * `callback' at some future point, passing callback_ctx as the first\r
2506  * parameter and the actual reply data as the second and third.\r
2507  *\r
2508  * The response may be a NULL pointer (in either of the synchronous\r
2509  * or asynchronous cases), which indicates failure to receive a\r
2510  * response.\r
2511  *\r
2512  * When the return from agent_query is not NULL, it identifies the\r
2513  * in-progress query in case it needs to be cancelled. If\r
2514  * agent_cancel_query is called, then the pending query is destroyed\r
2515  * and the callback will not be called. (E.g. if you're going to throw\r
2516  * away the thing you were using as callback_ctx.)\r
2517  *\r
2518  * Passing a null pointer as callback forces agent_query to behave\r
2519  * synchronously, i.e. it will block if necessary, and guarantee to\r
2520  * return NULL. The wrapper function agent_query_synchronous()\r
2521  * (defined in its own module aqsync.c) makes this easier.\r
2522  */\r
2523 typedef struct agent_pending_query agent_pending_query;\r
2524 agent_pending_query *agent_query(\r
2525     strbuf *in, void **out, int *outlen,\r
2526     void (*callback)(void *, void *, int), void *callback_ctx);\r
2527 void agent_cancel_query(agent_pending_query *);\r
2528 void agent_query_synchronous(strbuf *in, void **out, int *outlen);\r
2529 bool agent_exists(void);\r
2531 /* For stream-oriented agent connections, if available. */\r
2532 Socket *agent_connect(Plug *plug);\r
2534 /*\r
2535  * Exports from wildcard.c\r
2536  */\r
2537 const char *wc_error(int value);\r
2538 int wc_match_pl(const char *wildcard, ptrlen target);\r
2539 int wc_match(const char *wildcard, const char *target);\r
2540 bool wc_unescape(char *output, const char *wildcard);\r
2542 /*\r
2543  * Exports from frontend (dialog.c etc)\r
2544  */\r
2545 void pgp_fingerprints(void);\r
2546 /*\r
2547  * have_ssh_host_key() just returns true if a key of that type is\r
2548  * already cached and false otherwise.\r
2549  */\r
2550 bool have_ssh_host_key(const char *host, int port, const char *keytype);\r
2552 /*\r
2553  * Exports from console frontends (console.c in platform subdirs)\r
2554  * that aren't equivalents to things in windlg.c et al.\r
2555  */\r
2556 extern bool console_batch_mode, console_antispoof_prompt;\r
2557 SeatPromptResult console_get_userpass_input(prompts_t *p);\r
2558 bool is_interactive(void);\r
2559 void console_print_error_msg(const char *prefix, const char *msg);\r
2560 void console_print_error_msg_fmt_v(\r
2561     const char *prefix, const char *fmt, va_list ap);\r
2562 void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...)\r
2563     PRINTF_LIKE(2, 3);\r
2565 /*\r
2566  * Exports from printing.c in platform subdirs.\r
2567  */\r
2568 typedef struct printer_enum_tag printer_enum;\r
2569 typedef struct printer_job_tag printer_job;\r
2570 printer_enum *printer_start_enum(int *nprinters);\r
2571 char *printer_get_name(printer_enum *, int);\r
2572 void printer_finish_enum(printer_enum *);\r
2573 printer_job *printer_start_job(char *printer);\r
2574 void printer_job_data(printer_job *, const void *, size_t);\r
2575 void printer_finish_job(printer_job *);\r
2577 /*\r
2578  * Exports from cmdline.c (and also cmdline_error(), which is\r
2579  * defined differently in various places and required _by_\r
2580  * cmdline.c).\r
2581  *\r
2582  * Note that cmdline_process_param takes a const option string, but a\r
2583  * writable argument string. That's not a mistake - that's so it can\r
2584  * zero out password arguments in the hope of not having them show up\r
2585  * avoidably in Unix 'ps'.\r
2586  */\r
2587 struct cmdline_get_passwd_input_state { bool tried; };\r
2588 #define CMDLINE_GET_PASSWD_INPUT_STATE_INIT { .tried = false }\r
2589 extern const cmdline_get_passwd_input_state cmdline_get_passwd_input_state_new;\r
2591 int cmdline_process_param(const char *, char *, int, Conf *);\r
2592 void cmdline_run_saved(Conf *);\r
2593 void cmdline_cleanup(void);\r
2594 SeatPromptResult cmdline_get_passwd_input(\r
2595     prompts_t *p, cmdline_get_passwd_input_state *state, bool restartable);\r
2596 bool cmdline_host_ok(Conf *);\r
2597 bool cmdline_verbose(void);\r
2598 bool cmdline_loaded_session(void);\r
2600 /*\r
2601  * Here we have a flags word provided by each tool, which describes\r
2602  * the capabilities of that tool that cmdline.c needs to know about.\r
2603  * It will refuse certain command-line options if a particular tool\r
2604  * inherently can't do anything sensible. For example, the file\r
2605  * transfer tools (psftp, pscp) can't do a great deal with protocol\r
2606  * selections (ever tried running scp over telnet?) or with port\r
2607  * forwarding (even if it wasn't a hideously bad idea, they don't have\r
2608  * the select/poll infrastructure to make them work).\r
2609  */\r
2610 extern const unsigned cmdline_tooltype;\r
2612 /* Bit flags for the above */\r
2613 #define TOOLTYPE_LIST(X)                        \\r
2614     X(TOOLTYPE_FILETRANSFER)                    \\r
2615     X(TOOLTYPE_NONNETWORK)                      \\r
2616     X(TOOLTYPE_HOST_ARG)                        \\r
2617     X(TOOLTYPE_HOST_ARG_CAN_BE_SESSION)         \\r
2618     X(TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX)        \\r
2619     X(TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD)   \\r
2620     X(TOOLTYPE_PORT_ARG)                        \\r
2621     X(TOOLTYPE_NO_VERBOSE_OPTION)               \\r
2622     /* end of list */\r
2623 #define BITFLAG_INDEX(val) val ## _bitflag_index,\r
2624 enum { TOOLTYPE_LIST(BITFLAG_INDEX) };\r
2625 #define BITFLAG_DEF(val) val = 1U << (val ## _bitflag_index),\r
2626 enum { TOOLTYPE_LIST(BITFLAG_DEF) };\r
2628 void cmdline_error(const char *, ...) PRINTF_LIKE(1, 2);\r
2630 /*\r
2631  * Exports from config.c.\r
2632  */\r
2633 struct controlbox;\r
2634 void conf_radiobutton_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2635                               void *data, int event);\r
2636 #define CHECKBOX_INVERT (1<<30)\r
2637 void conf_checkbox_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2638                            void *data, int event);\r
2639 void conf_editbox_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2640                           void *data, int event);\r
2641 void conf_filesel_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2642                           void *data, int event);\r
2643 void conf_fontsel_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2644                           void *data, int event);\r
2646 struct conf_editbox_handler_type {\r
2647     /* Structure passed as context2 to conf_editbox_handler */\r
2648     enum { EDIT_STR, EDIT_INT, EDIT_FIXEDPOINT } type;\r
2649     union {\r
2650         /*\r
2651          * EDIT_STR means the edit box is connected to a string\r
2652          * field in Conf. No further parameters needed.\r
2653          */\r
2655         /*\r
2656          * EDIT_INT means the edit box is connected to an int field in\r
2657          * Conf, and the input string is interpreted as decimal. No\r
2658          * further parameters needed. (But we could add one here later\r
2659          * if for some reason we wanted int fields in hex.)\r
2660          */\r
2662         /*\r
2663          * EDIT_FIXEDPOINT means the edit box is connected to an int\r
2664          * field in Conf, but the input string is interpreted as\r
2665          * _floating point_, and converted to/from the output int by\r
2666          * means of a fixed denominator. That is,\r
2667          *\r
2668          *   (floating value in edit box) * denominator = value in Conf\r
2669          */\r
2670         struct {\r
2671             double denominator;\r
2672         };\r
2673     };\r
2674 };\r
2676 extern const struct conf_editbox_handler_type conf_editbox_str;\r
2677 extern const struct conf_editbox_handler_type conf_editbox_int;\r
2678 #define ED_STR CP(&conf_editbox_str)\r
2679 #define ED_INT CP(&conf_editbox_int)\r
2681 void setup_config_box(struct controlbox *b, bool midsession,\r
2682                       int protocol, int protcfginfo);\r
2684 void setup_ca_config_box(struct controlbox *b);\r
2686 /* Platforms provide this to be called from config.c */\r
2687 void show_ca_config_box(dlgparam *dlg);\r
2688 extern const bool has_ca_config_box; /* false if, e.g., we're PuTTYtel */\r
2690 /* Visible outside config.c so that platforms can use it to recognise\r
2691  * the proxy type control */\r
2692 void proxy_type_handler(dlgcontrol *ctrl, dlgparam *dlg,\r
2693                         void *data, int event);\r
2694 /* And then they'll set this flag in its generic.context.i */\r
2695 #define PROXY_UI_FLAG_LOCAL 1 /* has a local proxy */\r
2697 /*\r
2698  * Exports from bidi.c.\r
2699  */\r
2700 #define BIDI_CHAR_INDEX_NONE ((unsigned short)-1)\r
2701 typedef struct bidi_char {\r
2702     unsigned int origwc, wc;\r
2703     unsigned short index, nchars;\r
2704 } bidi_char;\r
2705 BidiContext *bidi_new_context(void);\r
2706 void bidi_free_context(BidiContext *ctx);\r
2707 void do_bidi(BidiContext *ctx, bidi_char *line, size_t count);\r
2708 int do_shape(bidi_char *line, bidi_char *to, int count);\r
2709 bool is_rtl(int c);\r
2711 /*\r
2712  * X11 auth mechanisms we know about.\r
2713  */\r
2714 enum {\r
2715     X11_NO_AUTH,\r
2716     X11_MIT,                           /* MIT-MAGIC-COOKIE-1 */\r
2717     X11_XDM,                           /* XDM-AUTHORIZATION-1 */\r
2718     X11_NAUTHS\r
2719 };\r
2720 extern const char *const x11_authnames[X11_NAUTHS];\r
2722 /*\r
2723  * An enum for the copy-paste UI action configuration.\r
2724  */\r
2725 enum {\r
2726     CLIPUI_NONE,     /* UI action has no copy/paste effect */\r
2727     CLIPUI_IMPLICIT, /* use the default clipboard implicit in mouse actions  */\r
2728     CLIPUI_EXPLICIT, /* use the default clipboard for explicit Copy/Paste */\r
2729     CLIPUI_CUSTOM,   /* use a named clipboard (on systems that support it) */\r
2730 };\r
2732 /*\r
2733  * Miscellaneous exports from the platform-specific code.\r
2734  *\r
2735  * filename_serialise and filename_deserialise have the same semantics\r
2736  * as fontspec_serialise and fontspec_deserialise above.\r
2737  */\r
2738 Filename *filename_from_str(const char *string);\r
2739 const char *filename_to_str(const Filename *fn);\r
2740 bool filename_equal(const Filename *f1, const Filename *f2);\r
2741 bool filename_is_null(const Filename *fn);\r
2742 Filename *filename_copy(const Filename *fn);\r
2743 void filename_free(Filename *fn);\r
2744 void filename_serialise(BinarySink *bs, const Filename *f);\r
2745 Filename *filename_deserialise(BinarySource *src);\r
2746 char *get_username(void);              /* return value needs freeing */\r
2747 char *get_random_data(int bytes, const char *device); /* used in cmdgen.c */\r
2748 char filename_char_sanitise(char c);   /* rewrite special pathname chars */\r
2749 bool open_for_write_would_lose_data(const Filename *fn);\r
2751 /*\r
2752  * Exports and imports from timing.c.\r
2753  *\r
2754  * schedule_timer() asks the front end to schedule a callback to a\r
2755  * timer function in a given number of ticks. The returned value is\r
2756  * the time (in ticks since an arbitrary offset) at which the\r
2757  * callback can be expected. This value will also be passed as the\r
2758  * `now' parameter to the callback function. Hence, you can (for\r
2759  * example) schedule an event at a particular time by calling\r
2760  * schedule_timer() and storing the return value in your context\r
2761  * structure as the time when that event is due. The first time a\r
2762  * callback function gives you that value or more as `now', you do\r
2763  * the thing.\r
2764  *\r
2765  * expire_timer_context() drops all current timers associated with\r
2766  * a given value of ctx (for when you're about to free ctx).\r
2767  *\r
2768  * run_timers() is called from the front end when it has reason to\r
2769  * think some timers have reached their moment, or when it simply\r
2770  * needs to know how long to wait next. We pass it the time we\r
2771  * think it is. It returns true and places the time when the next\r
2772  * timer needs to go off in `next', or alternatively it returns\r
2773  * false if there are no timers at all pending.\r
2774  *\r
2775  * timer_change_notify() must be supplied by the front end; it\r
2776  * notifies the front end that a new timer has been added to the\r
2777  * list which is sooner than any existing ones. It provides the\r
2778  * time when that timer needs to go off.\r
2779  *\r
2780  * *** FRONT END IMPLEMENTORS NOTE:\r
2781  *\r
2782  * There's an important subtlety in the front-end implementation of\r
2783  * the timer interface. When a front end is given a `next' value,\r
2784  * either returned from run_timers() or via timer_change_notify(),\r
2785  * it should ensure that it really passes _that value_ as the `now'\r
2786  * parameter to its next run_timers call. It should _not_ simply\r
2787  * call GETTICKCOUNT() to get the `now' parameter when invoking\r
2788  * run_timers().\r
2789  *\r
2790  * The reason for this is that an OS's system clock might not agree\r
2791  * exactly with the timing mechanisms it supplies to wait for a\r
2792  * given interval. I'll illustrate this by the simple example of\r
2793  * Unix Plink, which uses timeouts to poll() in a way which for\r
2794  * these purposes can simply be considered to be a wait() function.\r
2795  * Suppose, for the sake of argument, that this wait() function\r
2796  * tends to return early by 1%. Then a possible sequence of actions\r
2797  * is:\r
2798  *\r
2799  *  - run_timers() tells the front end that the next timer firing\r
2800  *    is 10000ms from now.\r
2801  *  - Front end calls wait(10000ms), but according to\r
2802  *    GETTICKCOUNT() it has only waited for 9900ms.\r
2803  *  - Front end calls run_timers() again, passing time T-100ms as\r
2804  *    `now'.\r
2805  *  - run_timers() does nothing, and says the next timer firing is\r
2806  *    still 100ms from now.\r
2807  *  - Front end calls wait(100ms), which only waits for 99ms.\r
2808  *  - Front end calls run_timers() yet again, passing time T-1ms.\r
2809  *  - run_timers() says there's still 1ms to wait.\r
2810  *  - Front end calls wait(1ms).\r
2811  *\r
2812  * If you're _lucky_ at this point, wait(1ms) will actually wait\r
2813  * for 1ms and you'll only have woken the program up three times.\r
2814  * If you're unlucky, wait(1ms) might do nothing at all due to\r
2815  * being below some minimum threshold, and you might find your\r
2816  * program spends the whole of the last millisecond tight-looping\r
2817  * between wait() and run_timers().\r
2818  *\r
2819  * Instead, what you should do is to _save_ the precise `next'\r
2820  * value provided by run_timers() or via timer_change_notify(), and\r
2821  * use that precise value as the input to the next run_timers()\r
2822  * call. So:\r
2823  *\r
2824  *  - run_timers() tells the front end that the next timer firing\r
2825  *    is at time T, 10000ms from now.\r
2826  *  - Front end calls wait(10000ms).\r
2827  *  - Front end then immediately calls run_timers() and passes it\r
2828  *    time T, without stopping to check GETTICKCOUNT() at all.\r
2829  *\r
2830  * This guarantees that the program wakes up only as many times as\r
2831  * there are actual timer actions to be taken, and that the timing\r
2832  * mechanism will never send it into a tight loop.\r
2833  *\r
2834  * (It does also mean that the timer action in the above example\r
2835  * will occur 100ms early, but this is not generally critical. And\r
2836  * the hypothetical 1% error in wait() will be partially corrected\r
2837  * for anyway when, _after_ run_timers() returns, you call\r
2838  * GETTICKCOUNT() and compare the result with the returned `next'\r
2839  * value to find out how long you have to make your next wait().)\r
2840  */\r
2841 typedef void (*timer_fn_t)(void *ctx, unsigned long now);\r
2842 unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx);\r
2843 void expire_timer_context(void *ctx);\r
2844 bool run_timers(unsigned long now, unsigned long *next);\r
2845 void timer_change_notify(unsigned long next);\r
2846 unsigned long timing_last_clock(void);\r
2848 /*\r
2849  * Exports from callback.c.\r
2850  *\r
2851  * This provides a method of queuing function calls to be run at the\r
2852  * earliest convenience from the top-level event loop. Use it if\r
2853  * you're deep in a nested chain of calls and want to trigger an\r
2854  * action which will probably lead to your function being re-entered\r
2855  * recursively if you just call the initiating function the normal\r
2856  * way.\r
2857  *\r
2858  * Most front ends run the queued callbacks by simply calling\r
2859  * run_toplevel_callbacks() after handling each event in their\r
2860  * top-level event loop. However, if a front end doesn't have control\r
2861  * over its own event loop (e.g. because it's using GTK) then it can\r
2862  * instead request notifications when a callback is available, so that\r
2863  * it knows to ask its delegate event loop to do the same thing. Also,\r
2864  * if a front end needs to know whether a callback is pending without\r
2865  * actually running it (e.g. so as to put a zero timeout on a poll()\r
2866  * call) then it can call toplevel_callback_pending(), which will\r
2867  * return true if at least one callback is in the queue.\r
2868  *\r
2869  * run_toplevel_callbacks() returns true if it ran any actual code.\r
2870  * This can be used as a means of speculatively terminating a poll\r
2871  * loop, as in PSFTP, for example - if a callback has run then perhaps\r
2872  * it might have done whatever the loop's caller was waiting for.\r
2873  */\r
2874 void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx);\r
2875 bool run_toplevel_callbacks(void);\r
2876 bool toplevel_callback_pending(void);\r
2877 void delete_callbacks_for_context(void *ctx);\r
2879 /*\r
2880  * Another facility in callback.c deals with 'idempotent' callbacks,\r
2881  * defined as those which never need to be scheduled again if they are\r
2882  * already scheduled and have not yet run. (An example would be one\r
2883  * which, when called, empties a queue of data completely: when data\r
2884  * is added to the queue, you must ensure a run of the queue-consuming\r
2885  * function has been scheduled, but if one is already pending, you\r
2886  * don't need to schedule a second one.)\r
2887  */\r
2888 struct IdempotentCallback {\r
2889     toplevel_callback_fn_t fn;\r
2890     void *ctx;\r
2891     bool queued;\r
2892 };\r
2893 void queue_idempotent_callback(struct IdempotentCallback *ic);\r
2895 typedef void (*toplevel_callback_notify_fn_t)(void *ctx);\r
2896 void request_callback_notifications(toplevel_callback_notify_fn_t notify,\r
2897                                     void *ctx);\r
2899 /*\r
2900  * Facility provided by the platform to spawn a parallel subprocess\r
2901  * and present its stdio via a Socket.\r
2902  *\r
2903  * 'prefix' indicates the prefix that should appear on messages passed\r
2904  * to plug_log to provide stderr output from the process.\r
2905  */\r
2906 Socket *platform_start_subprocess(const char *cmd, Plug *plug,\r
2907                                   const char *prefix);\r
2909 /*\r
2910  * Define no-op macros for the jump list functions, on platforms that\r
2911  * don't support them. (This is a bit of a hack, and it'd be nicer to\r
2912  * localise even the calls to those functions into the Windows front\r
2913  * end, but it'll do for the moment.)\r
2914  */\r
2915 #ifndef JUMPLIST_SUPPORTED\r
2916 #define add_session_to_jumplist(x) ((void)0)\r
2917 #define remove_session_from_jumplist(x) ((void)0)\r
2918 #endif\r
2920 /* SURROGATE PAIR */\r
2921 #ifndef HIGH_SURROGATE_START /* in some toolchains <winnls.h> defines these */\r
2922 #define HIGH_SURROGATE_START 0xd800\r
2923 #define HIGH_SURROGATE_END 0xdbff\r
2924 #define LOW_SURROGATE_START 0xdc00\r
2925 #define LOW_SURROGATE_END 0xdfff\r
2926 #endif\r
2928 /* These macros exist in the Windows API, so the environment may\r
2929  * provide them. If not, define them in terms of the above. */\r
2930 #ifndef IS_HIGH_SURROGATE\r
2931 #define IS_HIGH_SURROGATE(wch) (((wch) >= HIGH_SURROGATE_START) && \\r
2932                                 ((wch) <= HIGH_SURROGATE_END))\r
2933 #define IS_LOW_SURROGATE(wch) (((wch) >= LOW_SURROGATE_START) && \\r
2934                                ((wch) <= LOW_SURROGATE_END))\r
2935 #define IS_SURROGATE_PAIR(hs, ls) (IS_HIGH_SURROGATE(hs) && \\r
2936                                    IS_LOW_SURROGATE(ls))\r
2937 #endif\r
2940 #define IS_SURROGATE(wch) (((wch) >= HIGH_SURROGATE_START) &&   \\r
2941                            ((wch) <= LOW_SURROGATE_END))\r
2942 #define HIGH_SURROGATE_OF(codept) \\r
2943     (HIGH_SURROGATE_START + (((codept) - 0x10000) >> 10))\r
2944 #define LOW_SURROGATE_OF(codept) \\r
2945     (LOW_SURROGATE_START + (((codept) - 0x10000) & 0x3FF))\r
2946 #define FROM_SURROGATES(wch1, wch2) \\r
2947     (0x10000 + (((wch1) & 0x3FF) << 10) + ((wch2) & 0x3FF))\r
2949 #endif\r