diff options
Diffstat (limited to 'networking/telnet.c')
-rw-r--r-- | networking/telnet.c | 142 |
1 files changed, 68 insertions, 74 deletions
diff --git a/networking/telnet.c b/networking/telnet.c index 9085c5848..78229cd01 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -101,6 +101,7 @@ static void iacflush(void) | |||
101 | 101 | ||
102 | #define write_str(fd, str) write(fd, str, sizeof(str) - 1) | 102 | #define write_str(fd, str) write(fd, str, sizeof(str) - 1) |
103 | 103 | ||
104 | static void doexit(int ev) ATTRIBUTE_NORETURN; | ||
104 | static void doexit(int ev) | 105 | static void doexit(int ev) |
105 | { | 106 | { |
106 | cookmode(); | 107 | cookmode(); |
@@ -157,31 +158,29 @@ static void conescape(void) | |||
157 | 158 | ||
158 | static void handlenetoutput(int len) | 159 | static void handlenetoutput(int len) |
159 | { | 160 | { |
160 | /* here we could do smart tricks how to handle 0xFF:s in output | 161 | /* here we could do smart tricks how to handle 0xFF:s in output |
161 | * stream like writing twice every sequence of FF:s (thus doing | 162 | * stream like writing twice every sequence of FF:s (thus doing |
162 | * many write()s. But I think interactive telnet application does | 163 | * many write()s. But I think interactive telnet application does |
163 | * not need to be 100% 8-bit clean, so changing every 0xff:s to | 164 | * not need to be 100% 8-bit clean, so changing every 0xff:s to |
164 | * 0x7f:s | 165 | * 0x7f:s |
165 | * | 166 | * |
166 | * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com) | 167 | * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com) |
167 | * I don't agree. | 168 | * I don't agree. |
168 | * first - I cannot use programs like sz/rz | 169 | * first - I cannot use programs like sz/rz |
169 | * second - the 0x0D is sent as one character and if the next | 170 | * second - the 0x0D is sent as one character and if the next |
170 | * char is 0x0A then it's eaten by a server side. | 171 | * char is 0x0A then it's eaten by a server side. |
171 | * third - whay doy you have to make 'many write()s'? | 172 | * third - whay doy you have to make 'many write()s'? |
172 | * I don't understand. | 173 | * I don't understand. |
173 | * So I implemented it. It's realy useful for me. I hope that | 174 | * So I implemented it. It's realy useful for me. I hope that |
174 | * others people will find it interesting to. | 175 | * others people will find it interesting too. |
175 | */ | 176 | */ |
176 | 177 | ||
177 | int i, j; | 178 | int i, j; |
178 | byte * p = (byte*)G.buf; | 179 | byte * p = (byte*)G.buf; |
179 | byte outbuf[4*DATABUFSIZE]; | 180 | byte outbuf[4*DATABUFSIZE]; |
180 | 181 | ||
181 | for (i = len, j = 0; i > 0; i--, p++) | 182 | for (i = len, j = 0; i > 0; i--, p++) { |
182 | { | 183 | if (*p == 0x1d) { |
183 | if (*p == 0x1d) | ||
184 | { | ||
185 | conescape(); | 184 | conescape(); |
186 | return; | 185 | return; |
187 | } | 186 | } |
@@ -200,68 +199,59 @@ static void handlenetinput(int len) | |||
200 | int i; | 199 | int i; |
201 | int cstart = 0; | 200 | int cstart = 0; |
202 | 201 | ||
203 | for (i = 0; i < len; i++) | 202 | for (i = 0; i < len; i++) { |
204 | { | ||
205 | byte c = G.buf[i]; | 203 | byte c = G.buf[i]; |
206 | 204 | ||
207 | if (G.telstate == 0) /* most of the time state == 0 */ | 205 | if (G.telstate == 0) { /* most of the time state == 0 */ |
208 | { | 206 | if (c == IAC) { |
209 | if (c == IAC) | ||
210 | { | ||
211 | cstart = i; | 207 | cstart = i; |
212 | G.telstate = TS_IAC; | 208 | G.telstate = TS_IAC; |
213 | } | 209 | } |
214 | } | 210 | } else |
215 | else | 211 | switch (G.telstate) { |
216 | switch (G.telstate) | 212 | case TS_0: |
217 | { | 213 | if (c == IAC) |
218 | case TS_0: | 214 | G.telstate = TS_IAC; |
219 | if (c == IAC) | 215 | else |
220 | G.telstate = TS_IAC; | 216 | G.buf[cstart++] = c; |
221 | else | 217 | break; |
222 | G.buf[cstart++] = c; | 218 | |
223 | break; | 219 | case TS_IAC: |
224 | 220 | if (c == IAC) { /* IAC IAC -> 0xFF */ | |
225 | case TS_IAC: | 221 | G.buf[cstart++] = c; |
226 | if (c == IAC) /* IAC IAC -> 0xFF */ | 222 | G.telstate = TS_0; |
227 | { | 223 | break; |
228 | G.buf[cstart++] = c; | 224 | } |
229 | G.telstate = TS_0; | 225 | /* else */ |
230 | break; | 226 | switch (c) { |
231 | } | 227 | case SB: |
232 | /* else */ | 228 | G.telstate = TS_SUB1; |
233 | switch (c) | 229 | break; |
234 | { | 230 | case DO: |
235 | case SB: | 231 | case DONT: |
236 | G.telstate = TS_SUB1; | 232 | case WILL: |
237 | break; | 233 | case WONT: |
238 | case DO: | 234 | G.telwish = c; |
239 | case DONT: | 235 | G.telstate = TS_OPT; |
240 | case WILL: | 236 | break; |
241 | case WONT: | 237 | default: |
242 | G.telwish = c; | 238 | G.telstate = TS_0; /* DATA MARK must be added later */ |
243 | G.telstate = TS_OPT; | 239 | } |
244 | break; | 240 | break; |
245 | default: | 241 | case TS_OPT: /* WILL, WONT, DO, DONT */ |
246 | G.telstate = TS_0; /* DATA MARK must be added later */ | 242 | telopt(c); |
247 | } | 243 | G.telstate = TS_0; |
248 | break; | 244 | break; |
249 | case TS_OPT: /* WILL, WONT, DO, DONT */ | 245 | case TS_SUB1: /* Subnegotiation */ |
250 | telopt(c); | 246 | case TS_SUB2: /* Subnegotiation */ |
251 | G.telstate = TS_0; | 247 | if (subneg(c)) |
252 | break; | 248 | G.telstate = TS_0; |
253 | case TS_SUB1: /* Subnegotiation */ | 249 | break; |
254 | case TS_SUB2: /* Subnegotiation */ | 250 | } |
255 | if (subneg(c)) | ||
256 | G.telstate = TS_0; | ||
257 | break; | ||
258 | } | ||
259 | } | 251 | } |
260 | if (G.telstate) | 252 | if (G.telstate) { |
261 | { | 253 | if (G.iaclen) iacflush(); |
262 | if (G.iaclen) iacflush(); | ||
263 | if (G.telstate == TS_0) G.telstate = 0; | 254 | if (G.telstate == TS_0) G.telstate = 0; |
264 | |||
265 | len = cstart; | 255 | len = cstart; |
266 | } | 256 | } |
267 | 257 | ||
@@ -440,7 +430,8 @@ static void to_sga(void) | |||
440 | } else if (G.telwish == WONT) | 430 | } else if (G.telwish == WONT) |
441 | return; | 431 | return; |
442 | 432 | ||
443 | if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */ | 433 | G.telflags ^= UF_SGA; /* toggle */ |
434 | if (G.telflags & UF_SGA) | ||
444 | putiac2(DO, TELOPT_SGA); | 435 | putiac2(DO, TELOPT_SGA); |
445 | else | 436 | else |
446 | putiac2(DONT, TELOPT_SGA); | 437 | putiac2(DONT, TELOPT_SGA); |
@@ -550,6 +541,9 @@ static void cookmode(void) | |||
550 | tcsetattr(0, TCSADRAIN, &G.termios_def); | 541 | tcsetattr(0, TCSADRAIN, &G.termios_def); |
551 | } | 542 | } |
552 | 543 | ||
544 | /* poll gives smaller (-70 bytes) code */ | ||
545 | #define USE_POLL 1 | ||
546 | |||
553 | int telnet_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 547 | int telnet_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
554 | int telnet_main(int argc, char **argv) | 548 | int telnet_main(int argc, char **argv) |
555 | { | 549 | { |