]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - rlogin.c
Move MODULE files out of individual project directories into a
[PuTTY.git] / rlogin.c
1 #include <windows.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5
6 #include "putty.h"
7
8 #ifndef FALSE
9 #define FALSE 0
10 #endif
11 #ifndef TRUE
12 #define TRUE 1
13 #endif
14
15 #define RLOGIN_MAX_BACKLOG 4096
16
17 static Socket s = NULL;
18 static int rlogin_bufsize;
19
20 static void rlogin_size(void);
21
22 static void c_write(char *buf, int len)
23 {
24     int backlog = from_backend(0, buf, len);
25     sk_set_frozen(s, backlog > RLOGIN_MAX_BACKLOG);
26 }
27
28 static int rlogin_closing(Plug plug, char *error_msg, int error_code,
29                           int calling_back)
30 {
31     if (s) {
32         sk_close(s);
33         s = NULL;
34     }
35     if (error_msg) {
36         /* A socket error has occurred. */
37         logevent(error_msg);
38         connection_fatal("%s", error_msg);
39     }                                  /* Otherwise, the remote side closed the connection normally. */
40     return 0;
41 }
42
43 static int rlogin_receive(Plug plug, int urgent, char *data, int len)
44 {
45     if (urgent == 2) {
46         char c;
47
48         c = *data++;
49         len--;
50         if (c == '\x80')
51             rlogin_size();
52         /*
53          * We should flush everything (aka Telnet SYNCH) if we see
54          * 0x02, and we should turn off and on _local_ flow control
55          * on 0x10 and 0x20 respectively. I'm not convinced it's
56          * worth it...
57          */
58     } else {
59         /*
60          * Main rlogin protocol. This is really simple: the first
61          * byte is expected to be NULL and is ignored, and the rest
62          * is printed.
63          */
64         static int firstbyte = 1;
65         if (firstbyte) {
66             if (data[0] == '\0') {
67                 data++;
68                 len--;
69             }
70             firstbyte = 0;
71         }
72         if (len > 0)
73             c_write(data, len);
74     }
75     return 1;
76 }
77
78 static void rlogin_sent(Plug plug, int bufsize)
79 {
80     rlogin_bufsize = bufsize;
81 }
82
83 /*
84  * Called to set up the rlogin connection.
85  * 
86  * Returns an error message, or NULL on success.
87  *
88  * Also places the canonical host name into `realhost'. It must be
89  * freed by the caller.
90  */
91 static char *rlogin_init(char *host, int port, char **realhost, int nodelay)
92 {
93     static struct plug_function_table fn_table = {
94         rlogin_closing,
95         rlogin_receive,
96         rlogin_sent
97     }, *fn_table_ptr = &fn_table;
98
99     SockAddr addr;
100     char *err;
101
102     /*
103      * Try to find host.
104      */
105     {
106         char buf[200];
107         sprintf(buf, "Looking up host \"%.170s\"", host);
108         logevent(buf);
109     }
110     addr = sk_namelookup(host, realhost);
111     if ((err = sk_addr_error(addr)))
112         return err;
113
114     if (port < 0)
115         port = 513;                    /* default rlogin port */
116
117     /*
118      * Open socket.
119      */
120     {
121         char buf[200], addrbuf[100];
122         sk_getaddr(addr, addrbuf, 100);
123         sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
124         logevent(buf);
125     }
126     s = new_connection(addr, *realhost, port, 1, 0, nodelay, &fn_table_ptr);
127     if ((err = sk_socket_error(s)))
128         return err;
129
130     sk_addr_free(addr);
131
132     /*
133      * Send local username, remote username, terminal/speed
134      */
135
136     {
137         char z = 0;
138         char *p;
139         sk_write(s, &z, 1);
140         sk_write(s, cfg.localusername, strlen(cfg.localusername));
141         sk_write(s, &z, 1);
142         sk_write(s, cfg.username, strlen(cfg.username));
143         sk_write(s, &z, 1);
144         sk_write(s, cfg.termtype, strlen(cfg.termtype));
145         sk_write(s, "/", 1);
146         for (p = cfg.termspeed; isdigit(*p); p++);
147         sk_write(s, cfg.termspeed, p - cfg.termspeed);
148         rlogin_bufsize = sk_write(s, &z, 1);
149     }
150
151     return NULL;
152 }
153
154 /*
155  * Called to send data down the rlogin connection.
156  */
157 static int rlogin_send(char *buf, int len)
158 {
159     if (s == NULL)
160         return 0;
161
162     rlogin_bufsize = sk_write(s, buf, len);
163
164     return rlogin_bufsize;
165 }
166
167 /*
168  * Called to query the current socket sendability status.
169  */
170 static int rlogin_sendbuffer(void)
171 {
172     return rlogin_bufsize;
173 }
174
175 /*
176  * Called to set the size of the window
177  */
178 static void rlogin_size(void)
179 {
180     char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
181
182     if (s == NULL)
183         return;
184     
185     b[6] = cols >> 8;
186     b[7] = cols & 0xFF;
187     b[4] = rows >> 8;
188     b[5] = rows & 0xFF;
189     rlogin_bufsize = sk_write(s, b, 12);
190     return;
191 }
192
193 /*
194  * Send rlogin special codes.
195  */
196 static void rlogin_special(Telnet_Special code)
197 {
198     /* Do nothing! */
199     return;
200 }
201
202 static Socket rlogin_socket(void)
203 {
204     return s;
205 }
206
207 static int rlogin_sendok(void)
208 {
209     return 1;
210 }
211
212 static void rlogin_unthrottle(int backlog)
213 {
214     sk_set_frozen(s, backlog > RLOGIN_MAX_BACKLOG);
215 }
216
217 static int rlogin_ldisc(int option)
218 {
219     return 0;
220 }
221
222 static int rlogin_exitcode(void)
223 {
224     /* If we ever implement RSH, we'll probably need to do this properly */
225     return 0;
226 }
227
228 Backend rlogin_backend = {
229     rlogin_init,
230     rlogin_send,
231     rlogin_sendbuffer,
232     rlogin_size,
233     rlogin_special,
234     rlogin_socket,
235     rlogin_exitcode,
236     rlogin_sendok,
237     rlogin_ldisc,
238     rlogin_unthrottle,
239     1
240 };