OSDN Git Service

Enable X64 Build
[tortoisegit/TortoiseGitJp.git] / src / TortoisePlink / RLOGIN.C
1 /*\r
2  * Rlogin backend.\r
3  */\r
4 \r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 #include <ctype.h>\r
8 \r
9 #include "putty.h"\r
10 \r
11 #ifndef FALSE\r
12 #define FALSE 0\r
13 #endif\r
14 #ifndef TRUE\r
15 #define TRUE 1\r
16 #endif\r
17 \r
18 #define RLOGIN_MAX_BACKLOG 4096\r
19 \r
20 typedef struct rlogin_tag {\r
21     const struct plug_function_table *fn;\r
22     /* the above field _must_ be first in the structure */\r
23 \r
24     Socket s;\r
25     int bufsize;\r
26     int firstbyte;\r
27     int cansize;\r
28     int term_width, term_height;\r
29     void *frontend;\r
30 } *Rlogin;\r
31 \r
32 static void rlogin_size(void *handle, int width, int height);\r
33 \r
34 static void c_write(Rlogin rlogin, char *buf, int len)\r
35 {\r
36     int backlog = from_backend(rlogin->frontend, 0, buf, len);\r
37     sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG);\r
38 }\r
39 \r
40 static void rlogin_log(Plug plug, int type, SockAddr addr, int port,\r
41                        const char *error_msg, int error_code)\r
42 {\r
43     Rlogin rlogin = (Rlogin) plug;\r
44     char addrbuf[256], *msg;\r
45 \r
46     sk_getaddr(addr, addrbuf, lenof(addrbuf));\r
47 \r
48     if (type == 0)\r
49         msg = dupprintf("Connecting to %s port %d", addrbuf, port);\r
50     else\r
51         msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);\r
52 \r
53     logevent(rlogin->frontend, msg);\r
54 }\r
55 \r
56 static int rlogin_closing(Plug plug, const char *error_msg, int error_code,\r
57                           int calling_back)\r
58 {\r
59     Rlogin rlogin = (Rlogin) plug;\r
60     if (rlogin->s) {\r
61         sk_close(rlogin->s);\r
62         rlogin->s = NULL;\r
63         notify_remote_exit(rlogin->frontend);\r
64     }\r
65     if (error_msg) {\r
66         /* A socket error has occurred. */\r
67         logevent(rlogin->frontend, error_msg);\r
68         connection_fatal(rlogin->frontend, "%s", error_msg);\r
69     }                                  /* Otherwise, the remote side closed the connection normally. */\r
70     return 0;\r
71 }\r
72 \r
73 static int rlogin_receive(Plug plug, int urgent, char *data, int len)\r
74 {\r
75     Rlogin rlogin = (Rlogin) plug;\r
76     if (urgent == 2) {\r
77         char c;\r
78 \r
79         c = *data++;\r
80         len--;\r
81         if (c == '\x80') {\r
82             rlogin->cansize = 1;\r
83             rlogin_size(rlogin, rlogin->term_width, rlogin->term_height);\r
84         }\r
85         /*\r
86          * We should flush everything (aka Telnet SYNCH) if we see\r
87          * 0x02, and we should turn off and on _local_ flow control\r
88          * on 0x10 and 0x20 respectively. I'm not convinced it's\r
89          * worth it...\r
90          */\r
91     } else {\r
92         /*\r
93          * Main rlogin protocol. This is really simple: the first\r
94          * byte is expected to be NULL and is ignored, and the rest\r
95          * is printed.\r
96          */\r
97         if (rlogin->firstbyte) {\r
98             if (data[0] == '\0') {\r
99                 data++;\r
100                 len--;\r
101             }\r
102             rlogin->firstbyte = 0;\r
103         }\r
104         if (len > 0)\r
105             c_write(rlogin, data, len);\r
106     }\r
107     return 1;\r
108 }\r
109 \r
110 static void rlogin_sent(Plug plug, int bufsize)\r
111 {\r
112     Rlogin rlogin = (Rlogin) plug;\r
113     rlogin->bufsize = bufsize;\r
114 }\r
115 \r
116 /*\r
117  * Called to set up the rlogin connection.\r
118  * \r
119  * Returns an error message, or NULL on success.\r
120  *\r
121  * Also places the canonical host name into `realhost'. It must be\r
122  * freed by the caller.\r
123  */\r
124 static const char *rlogin_init(void *frontend_handle, void **backend_handle,\r
125                                Config *cfg,\r
126                                char *host, int port, char **realhost,\r
127                                int nodelay, int keepalive)\r
128 {\r
129     static const struct plug_function_table fn_table = {\r
130         rlogin_log,\r
131         rlogin_closing,\r
132         rlogin_receive,\r
133         rlogin_sent\r
134     };\r
135     SockAddr addr;\r
136     const char *err;\r
137     Rlogin rlogin;\r
138 \r
139     rlogin = snew(struct rlogin_tag);\r
140     rlogin->fn = &fn_table;\r
141     rlogin->s = NULL;\r
142     rlogin->frontend = frontend_handle;\r
143     rlogin->term_width = cfg->width;\r
144     rlogin->term_height = cfg->height;\r
145     rlogin->firstbyte = 1;\r
146     rlogin->cansize = 0;\r
147     *backend_handle = rlogin;\r
148 \r
149     /*\r
150      * Try to find host.\r
151      */\r
152     {\r
153         char *buf;\r
154         buf = dupprintf("Looking up host \"%s\"%s", host,\r
155                         (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :\r
156                          (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :\r
157                           "")));\r
158         logevent(rlogin->frontend, buf);\r
159         sfree(buf);\r
160     }\r
161     addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);\r
162     if ((err = sk_addr_error(addr)) != NULL) {\r
163         sk_addr_free(addr);\r
164         return err;\r
165     }\r
166 \r
167     if (port < 0)\r
168         port = 513;                    /* default rlogin port */\r
169 \r
170     /*\r
171      * Open socket.\r
172      */\r
173     rlogin->s = new_connection(addr, *realhost, port, 1, 0,\r
174                                nodelay, keepalive, (Plug) rlogin, cfg);\r
175     if ((err = sk_socket_error(rlogin->s)) != NULL)\r
176         return err;\r
177 \r
178     /*\r
179      * Send local username, remote username, terminal/speed\r
180      */\r
181 \r
182     {\r
183         char z = 0;\r
184         char *p;\r
185         sk_write(rlogin->s, &z, 1);\r
186         sk_write(rlogin->s, cfg->localusername,\r
187                  strlen(cfg->localusername));\r
188         sk_write(rlogin->s, &z, 1);\r
189         sk_write(rlogin->s, cfg->username,\r
190                  strlen(cfg->username));\r
191         sk_write(rlogin->s, &z, 1);\r
192         sk_write(rlogin->s, cfg->termtype,\r
193                  strlen(cfg->termtype));\r
194         sk_write(rlogin->s, "/", 1);\r
195         for (p = cfg->termspeed; isdigit((unsigned char)*p); p++) continue;\r
196         sk_write(rlogin->s, cfg->termspeed, p - cfg->termspeed);\r
197         rlogin->bufsize = sk_write(rlogin->s, &z, 1);\r
198     }\r
199 \r
200     return NULL;\r
201 }\r
202 \r
203 static void rlogin_free(void *handle)\r
204 {\r
205     Rlogin rlogin = (Rlogin) handle;\r
206 \r
207     if (rlogin->s)\r
208         sk_close(rlogin->s);\r
209     sfree(rlogin);\r
210 }\r
211 \r
212 /*\r
213  * Stub routine (we don't have any need to reconfigure this backend).\r
214  */\r
215 static void rlogin_reconfig(void *handle, Config *cfg)\r
216 {\r
217 }\r
218 \r
219 /*\r
220  * Called to send data down the rlogin connection.\r
221  */\r
222 static int rlogin_send(void *handle, char *buf, int len)\r
223 {\r
224     Rlogin rlogin = (Rlogin) handle;\r
225 \r
226     if (rlogin->s == NULL)\r
227         return 0;\r
228 \r
229     rlogin->bufsize = sk_write(rlogin->s, buf, len);\r
230 \r
231     return rlogin->bufsize;\r
232 }\r
233 \r
234 /*\r
235  * Called to query the current socket sendability status.\r
236  */\r
237 static int rlogin_sendbuffer(void *handle)\r
238 {\r
239     Rlogin rlogin = (Rlogin) handle;\r
240     return rlogin->bufsize;\r
241 }\r
242 \r
243 /*\r
244  * Called to set the size of the window\r
245  */\r
246 static void rlogin_size(void *handle, int width, int height)\r
247 {\r
248     Rlogin rlogin = (Rlogin) handle;\r
249     char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };\r
250 \r
251     rlogin->term_width = width;\r
252     rlogin->term_height = height;\r
253 \r
254     if (rlogin->s == NULL || !rlogin->cansize)\r
255         return;\r
256 \r
257     b[6] = rlogin->term_width >> 8;\r
258     b[7] = rlogin->term_width & 0xFF;\r
259     b[4] = rlogin->term_height >> 8;\r
260     b[5] = rlogin->term_height & 0xFF;\r
261     rlogin->bufsize = sk_write(rlogin->s, b, 12);\r
262     return;\r
263 }\r
264 \r
265 /*\r
266  * Send rlogin special codes.\r
267  */\r
268 static void rlogin_special(void *handle, Telnet_Special code)\r
269 {\r
270     /* Do nothing! */\r
271     return;\r
272 }\r
273 \r
274 /*\r
275  * Return a list of the special codes that make sense in this\r
276  * protocol.\r
277  */\r
278 static const struct telnet_special *rlogin_get_specials(void *handle)\r
279 {\r
280     return NULL;\r
281 }\r
282 \r
283 static int rlogin_connected(void *handle)\r
284 {\r
285     Rlogin rlogin = (Rlogin) handle;\r
286     return rlogin->s != NULL;\r
287 }\r
288 \r
289 static int rlogin_sendok(void *handle)\r
290 {\r
291     /* Rlogin rlogin = (Rlogin) handle; */\r
292     return 1;\r
293 }\r
294 \r
295 static void rlogin_unthrottle(void *handle, int backlog)\r
296 {\r
297     Rlogin rlogin = (Rlogin) handle;\r
298     sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG);\r
299 }\r
300 \r
301 static int rlogin_ldisc(void *handle, int option)\r
302 {\r
303     /* Rlogin rlogin = (Rlogin) handle; */\r
304     return 0;\r
305 }\r
306 \r
307 static void rlogin_provide_ldisc(void *handle, void *ldisc)\r
308 {\r
309     /* This is a stub. */\r
310 }\r
311 \r
312 static void rlogin_provide_logctx(void *handle, void *logctx)\r
313 {\r
314     /* This is a stub. */\r
315 }\r
316 \r
317 static int rlogin_exitcode(void *handle)\r
318 {\r
319     Rlogin rlogin = (Rlogin) handle;\r
320     if (rlogin->s != NULL)\r
321         return -1;                     /* still connected */\r
322     else\r
323         /* If we ever implement RSH, we'll probably need to do this properly */\r
324         return 0;\r
325 }\r
326 \r
327 /*\r
328  * cfg_info for rlogin does nothing at all.\r
329  */\r
330 static int rlogin_cfg_info(void *handle)\r
331 {\r
332     return 0;\r
333 }\r
334 \r
335 Backend rlogin_backend = {\r
336     rlogin_init,\r
337     rlogin_free,\r
338     rlogin_reconfig,\r
339     rlogin_send,\r
340     rlogin_sendbuffer,\r
341     rlogin_size,\r
342     rlogin_special,\r
343     rlogin_get_specials,\r
344     rlogin_connected,\r
345     rlogin_exitcode,\r
346     rlogin_sendok,\r
347     rlogin_ldisc,\r
348     rlogin_provide_ldisc,\r
349     rlogin_provide_logctx,\r
350     rlogin_unthrottle,\r
351     rlogin_cfg_info,\r
352     1\r
353 };\r