source: trunk/minix/commands/telnetd/telnet.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.8 KB
Line 
1/*
2 * TNET A server program for MINIX which implements the TCP/IP
3 * suite of networking protocols. It is based on the
4 * TCP/IP code written by Phil Karn et al, as found in
5 * his NET package for Packet Radio communications.
6 *
7 * This module handles telnet option processing.
8 *
9 * Author: Michael Temari, <temari@temari.ae.ge.com> 01/13/93
10 *
11 */
12#include <sys/types.h>
13#include <string.h>
14#include <fcntl.h>
15#include <errno.h>
16#include <unistd.h>
17#include <termios.h>
18#include "telnetd.h"
19#include "telnet.h"
20#include <stdio.h>
21#include <sys/ioctl.h>
22
23
24#define IN_DATA 0
25#define IN_CR 1
26#define IN_IAC 2
27#define IN_IAC2 3
28#define IN_SB 4
29
30_PROTOTYPE(static void dowill, (int c));
31_PROTOTYPE(static void dowont, (int c));
32_PROTOTYPE(static void dodo, (int c));
33_PROTOTYPE(static void dodont, (int c));
34_PROTOTYPE(static void respond, (int ack, int option));
35_PROTOTYPE(static void respond_really, (int ack, int option));
36
37#define LASTTELOPT TELOPT_SGA
38
39static int r_winch = 0;
40
41static int TelROpts[LASTTELOPT+1];
42static int TelLOpts[LASTTELOPT+1];
43
44static int telfdout;
45
46void tel_init()
47{
48int i;
49
50 for(i = 0; i <= LASTTELOPT; i++) {
51 TelROpts[i] = 0;
52 TelLOpts[i] = 0;
53 }
54}
55
56void telopt(fdout, what, option)
57int fdout;
58int what;
59int option;
60{
61char buf[3];
62int len;
63
64 buf[0] = IAC;
65 buf[1] = what;
66 buf[2] = option;
67 len = 0;
68
69 switch(what) {
70 case DO:
71 if(option <= LASTTELOPT) {
72 TelROpts[option] = 1;
73 len = 3;
74 } else if(option == TELOPT_WINCH && !r_winch) { r_winch = 1; len = 3; }
75 break;
76 case DONT:
77 if(option <= LASTTELOPT) {
78 TelROpts[option] = 1;
79 len = 3;
80 }
81 break;
82 case WILL:
83 if(option <= LASTTELOPT) {
84 TelLOpts[option] = 1;
85 len = 3;
86 }
87 break;
88 case WONT:
89 if(option <= LASTTELOPT) {
90 TelLOpts[option] = 1;
91 len = 3;
92 }
93 break;
94 }
95 if(len > 0)
96 (void) write(fdout, buf, len);
97}
98
99int set_winsize(int fd, unsigned int cols, unsigned int rows)
100{
101 struct winsize w;
102 memset(&w, 0, sizeof(w));
103 w.ws_col = cols;
104 w.ws_row = rows;
105 ioctl(fd, TIOCSWINSZ, (char *) &w);
106}
107
108int tel_in(fdout, telout, buffer, len)
109int fdout;
110int telout;
111char *buffer;
112int len;
113{
114static int InState = IN_DATA;
115static int ThisOpt = 0;
116char *p;
117char *p2;
118int size;
119int c;
120
121 telfdout = telout;
122 p = p2 = buffer;
123 size = 0;
124
125 while(len > 0) {
126 c = (unsigned char)*p++; len--;
127 switch(InState) {
128 case IN_CR:
129 InState = IN_DATA;
130 if(c == 0 || c == '\n')
131 break;
132 /* fall through */
133 case IN_DATA:
134 if(c == IAC) {
135 InState = IN_IAC;
136 break;
137 }
138 *p2++ = c; size++;
139 if(c == '\r') InState = IN_CR;
140 break;
141 case IN_IAC:
142 switch(c) {
143 case IAC:
144 *p2++ = c; size++;
145 InState = IN_DATA;
146 break;
147 case WILL:
148 case WONT:
149 case DO:
150 case DONT:
151 InState = IN_IAC2;
152 ThisOpt = c;
153 break;
154 case SB:
155 InState = IN_SB;
156 break;
157 case EOR:
158 case SE:
159 case NOP:
160 case BREAK:
161 case IP:
162 case AO:
163 case AYT:
164 case EC:
165 case EL:
166 case GA:
167 break;
168 default:
169 break;
170 }
171 break;
172 case IN_IAC2:
173 if(size > 0) {
174 write(fdout, buffer, size);
175 p2 = buffer;
176 size = 0;
177 }
178 InState = IN_DATA;
179 switch(ThisOpt) {
180 case WILL: dowill(c); break;
181 case WONT: dowont(c); break;
182 case DO: dodo(c); break;
183 case DONT: dodont(c); break;
184 }
185 break;
186 case IN_SB:
187 {
188 static int winchpos = -1;
189 /* Subnegotiation. */
190 if(winchpos >= 0) {
191 static unsigned int winchbuf[5], iacs = 0;
192 winchbuf[winchpos] = c;
193 /* IAC is escaped - unescape it. */
194 if(c == IAC) iacs++; else { iacs = 0; winchpos++; }
195 if(iacs == 2) { winchpos++; iacs = 0; }
196 if(winchpos >= 4) {
197 /* End of WINCH data. */
198 set_winsize(fdout,
199 (winchbuf[0] << 8) | winchbuf[1],
200 (winchbuf[2] << 8) | winchbuf[3]);
201 winchpos = -1;
202 }
203 } else {
204 static int lastiac = 0;
205 switch(c) {
206 case TELOPT_WINCH:
207 /* Start listening. */
208 winchpos = 0;
209 break;
210 case SE:
211 if(lastiac) InState = IN_DATA;
212 break;
213 default:
214 break;
215 }
216 if(c == IAC) lastiac = 1;
217 else lastiac = 0;
218
219
220 }
221 break;
222 }
223 }
224 }
225
226 if(size > 0)
227 write(fdout, buffer, size);
228}
229
230int tel_out(fdout, buf, size)
231int fdout;
232char *buf;
233int size;
234{
235char *p;
236int got_iac, len;
237
238 p = buf;
239 while(size > 0) {
240 buf = p;
241 got_iac = 0;
242 if((p = (char *)memchr(buf, IAC, size)) != (char *)NULL) {
243 got_iac = 1;
244 p++;
245 } else
246 p = buf + size;
247 len = p - buf;
248 if(len > 0)
249 (void) write(fdout, buf, len);
250 if(got_iac)
251 (void) write(fdout, p - 1, 1);
252 size = size - len;
253 }
254}
255
256static void dowill(c)
257int c;
258{
259int ack;
260
261 switch(c) {
262 case TELOPT_BINARY:
263 case TELOPT_ECHO:
264 case TELOPT_SGA:
265 if(TelROpts[c] == 1)
266 return;
267 TelROpts[c] = 1;
268 ack = DO;
269 break;
270 case TELOPT_WINCH:
271 if(r_winch) return;
272 r_winch = 1;
273 ack = DO;
274 respond_really(ack, c);
275 return;
276 default:
277 ack = DONT;
278 }
279
280 respond(ack, c);
281}
282
283static void dowont(c)
284int c;
285{
286 if(c <= LASTTELOPT) {
287 if(TelROpts[c] == 0)
288 return;
289 TelROpts[c] = 0;
290 }
291 respond(DONT, c);
292}
293
294static void dodo(c)
295int c;
296{
297int ack;
298
299 switch(c) {
300 default:
301 ack = WONT;
302 }
303 respond(ack, c);
304}
305
306static void dodont(c)
307int c;
308{
309 if(c <= LASTTELOPT) {
310 if(TelLOpts[c] == 0)
311 return;
312 TelLOpts[c] = 0;
313 }
314 respond(WONT, c);
315}
316
317static void respond(ack, option)
318int ack, option;
319{
320unsigned char c[3];
321
322 c[0] = IAC;
323 c[1] = ack;
324 c[2] = option;
325/* write(telfdout, c, 3); */
326}
327
328static void respond_really(ack, option)
329int ack, option;
330{
331unsigned char c[3];
332
333 c[0] = IAC;
334 c[1] = ack;
335 c[2] = option;
336 write(telfdout, c, 3);
337}
Note: See TracBrowser for help on using the repository browser.