]>
Commit | Line | Data |
---|---|---|
b7080c8e A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License." | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright (c) 1988, 1993 | |
26 | * The Regents of the University of California. All rights reserved. | |
27 | * | |
28 | * Redistribution and use in source and binary forms, with or without | |
29 | * modification, are permitted provided that the following conditions | |
30 | * are met: | |
31 | * 1. Redistributions of source code must retain the above copyright | |
32 | * notice, this list of conditions and the following disclaimer. | |
33 | * 2. Redistributions in binary form must reproduce the above copyright | |
34 | * notice, this list of conditions and the following disclaimer in the | |
35 | * documentation and/or other materials provided with the distribution. | |
36 | * 3. All advertising materials mentioning features or use of this software | |
37 | * must display the following acknowledgement: | |
38 | * This product includes software developed by the University of | |
39 | * California, Berkeley and its contributors. | |
40 | * 4. Neither the name of the University nor the names of its contributors | |
41 | * may be used to endorse or promote products derived from this software | |
42 | * without specific prior written permission. | |
43 | * | |
44 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
45 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
46 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
47 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
48 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
49 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
50 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
51 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
52 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
53 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
54 | * SUCH DAMAGE. | |
55 | */ | |
56 | ||
57 | #ifndef lint | |
58 | static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; | |
59 | #endif /* not lint */ | |
60 | ||
61 | #define TELOPTS | |
62 | #define TELCMDS | |
63 | #define SLC_NAMES | |
64 | #include <arpa/telnet.h> | |
65 | #include <sys/types.h> | |
66 | #include <sys/time.h> | |
67 | ||
68 | #include <ctype.h> | |
69 | ||
70 | #include "general.h" | |
71 | ||
72 | #include "fdset.h" | |
73 | ||
74 | #include "ring.h" | |
75 | ||
76 | #include "defines.h" | |
77 | ||
78 | #include "externs.h" | |
79 | ||
80 | FILE *NetTrace = 0; /* Not in bss, since needs to stay */ | |
81 | int prettydump; | |
82 | ||
83 | /* | |
84 | * upcase() | |
85 | * | |
86 | * Upcase (in place) the argument. | |
87 | */ | |
88 | ||
89 | void | |
90 | upcase(argument) | |
91 | register char *argument; | |
92 | { | |
93 | register int c; | |
94 | ||
95 | while ((c = *argument) != 0) { | |
96 | if (islower(c)) { | |
97 | *argument = toupper(c); | |
98 | } | |
99 | argument++; | |
100 | } | |
101 | } | |
102 | ||
103 | /* | |
104 | * SetSockOpt() | |
105 | * | |
106 | * Compensate for differences in 4.2 and 4.3 systems. | |
107 | */ | |
108 | ||
109 | int | |
110 | SetSockOpt(fd, level, option, yesno) | |
111 | int fd, level, option, yesno; | |
112 | { | |
113 | #ifndef NOT43 | |
114 | return setsockopt(fd, level, option, | |
115 | (char *)&yesno, sizeof yesno); | |
116 | #else /* NOT43 */ | |
117 | if (yesno == 0) { /* Can't do that in 4.2! */ | |
118 | fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", | |
119 | option); | |
120 | return -1; | |
121 | } | |
122 | return setsockopt(fd, level, option, 0, 0); | |
123 | #endif /* NOT43 */ | |
124 | } | |
125 | \f | |
126 | /* | |
127 | * The following are routines used to print out debugging information. | |
128 | */ | |
129 | ||
130 | unsigned char NetTraceFile[256] = "(standard output)"; | |
131 | ||
132 | void | |
133 | SetNetTrace(file) | |
134 | register char *file; | |
135 | { | |
136 | if (NetTrace && NetTrace != stdout) | |
137 | fclose(NetTrace); | |
138 | if (file && (strcmp(file, "-") != 0)) { | |
139 | NetTrace = fopen(file, "w"); | |
140 | if (NetTrace) { | |
141 | strcpy((char *)NetTraceFile, file); | |
142 | return; | |
143 | } | |
144 | fprintf(stderr, "Cannot open %s.\n", file); | |
145 | } | |
146 | NetTrace = stdout; | |
147 | strcpy((char *)NetTraceFile, "(standard output)"); | |
148 | } | |
149 | ||
150 | void | |
151 | Dump(direction, buffer, length) | |
152 | char direction; | |
153 | unsigned char *buffer; | |
154 | int length; | |
155 | { | |
156 | # define BYTES_PER_LINE 32 | |
157 | # define min(x,y) ((x<y)? x:y) | |
158 | unsigned char *pThis; | |
159 | int offset; | |
160 | extern pettydump; | |
161 | ||
162 | offset = 0; | |
163 | ||
164 | while (length) { | |
165 | /* print one line */ | |
166 | fprintf(NetTrace, "%c 0x%x\t", direction, offset); | |
167 | pThis = buffer; | |
168 | if (prettydump) { | |
169 | buffer = buffer + min(length, BYTES_PER_LINE/2); | |
170 | while (pThis < buffer) { | |
171 | fprintf(NetTrace, "%c%.2x", | |
172 | (((*pThis)&0xff) == 0xff) ? '*' : ' ', | |
173 | (*pThis)&0xff); | |
174 | pThis++; | |
175 | } | |
176 | length -= BYTES_PER_LINE/2; | |
177 | offset += BYTES_PER_LINE/2; | |
178 | } else { | |
179 | buffer = buffer + min(length, BYTES_PER_LINE); | |
180 | while (pThis < buffer) { | |
181 | fprintf(NetTrace, "%.2x", (*pThis)&0xff); | |
182 | pThis++; | |
183 | } | |
184 | length -= BYTES_PER_LINE; | |
185 | offset += BYTES_PER_LINE; | |
186 | } | |
187 | if (NetTrace == stdout) { | |
188 | fprintf(NetTrace, "\r\n"); | |
189 | } else { | |
190 | fprintf(NetTrace, "\n"); | |
191 | } | |
192 | if (length < 0) { | |
193 | fflush(NetTrace); | |
194 | return; | |
195 | } | |
196 | /* find next unique line */ | |
197 | } | |
198 | fflush(NetTrace); | |
199 | } | |
200 | ||
201 | ||
202 | void | |
203 | printoption(direction, cmd, option) | |
204 | char *direction; | |
205 | int cmd, option; | |
206 | { | |
207 | if (!showoptions) | |
208 | return; | |
209 | if (cmd == IAC) { | |
210 | if (TELCMD_OK(option)) | |
211 | fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); | |
212 | else | |
213 | fprintf(NetTrace, "%s IAC %d", direction, option); | |
214 | } else { | |
215 | register char *fmt; | |
216 | fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : | |
217 | (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; | |
218 | if (fmt) { | |
219 | fprintf(NetTrace, "%s %s ", direction, fmt); | |
220 | if (TELOPT_OK(option)) | |
221 | fprintf(NetTrace, "%s", TELOPT(option)); | |
222 | else if (option == TELOPT_EXOPL) | |
223 | fprintf(NetTrace, "EXOPL"); | |
224 | else | |
225 | fprintf(NetTrace, "%d", option); | |
226 | } else | |
227 | fprintf(NetTrace, "%s %d %d", direction, cmd, option); | |
228 | } | |
229 | if (NetTrace == stdout) { | |
230 | fprintf(NetTrace, "\r\n"); | |
231 | fflush(NetTrace); | |
232 | } else { | |
233 | fprintf(NetTrace, "\n"); | |
234 | } | |
235 | return; | |
236 | } | |
237 | ||
238 | void | |
239 | optionstatus() | |
240 | { | |
241 | register int i; | |
242 | extern char will_wont_resp[], do_dont_resp[]; | |
243 | ||
244 | for (i = 0; i < 256; i++) { | |
245 | if (do_dont_resp[i]) { | |
246 | if (TELOPT_OK(i)) | |
247 | printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); | |
248 | else if (TELCMD_OK(i)) | |
249 | printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); | |
250 | else | |
251 | printf("resp DO_DONT %d: %d\n", i, | |
252 | do_dont_resp[i]); | |
253 | if (my_want_state_is_do(i)) { | |
254 | if (TELOPT_OK(i)) | |
255 | printf("want DO %s\n", TELOPT(i)); | |
256 | else if (TELCMD_OK(i)) | |
257 | printf("want DO %s\n", TELCMD(i)); | |
258 | else | |
259 | printf("want DO %d\n", i); | |
260 | } else { | |
261 | if (TELOPT_OK(i)) | |
262 | printf("want DONT %s\n", TELOPT(i)); | |
263 | else if (TELCMD_OK(i)) | |
264 | printf("want DONT %s\n", TELCMD(i)); | |
265 | else | |
266 | printf("want DONT %d\n", i); | |
267 | } | |
268 | } else { | |
269 | if (my_state_is_do(i)) { | |
270 | if (TELOPT_OK(i)) | |
271 | printf(" DO %s\n", TELOPT(i)); | |
272 | else if (TELCMD_OK(i)) | |
273 | printf(" DO %s\n", TELCMD(i)); | |
274 | else | |
275 | printf(" DO %d\n", i); | |
276 | } | |
277 | } | |
278 | if (will_wont_resp[i]) { | |
279 | if (TELOPT_OK(i)) | |
280 | printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); | |
281 | else if (TELCMD_OK(i)) | |
282 | printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); | |
283 | else | |
284 | printf("resp WILL_WONT %d: %d\n", | |
285 | i, will_wont_resp[i]); | |
286 | if (my_want_state_is_will(i)) { | |
287 | if (TELOPT_OK(i)) | |
288 | printf("want WILL %s\n", TELOPT(i)); | |
289 | else if (TELCMD_OK(i)) | |
290 | printf("want WILL %s\n", TELCMD(i)); | |
291 | else | |
292 | printf("want WILL %d\n", i); | |
293 | } else { | |
294 | if (TELOPT_OK(i)) | |
295 | printf("want WONT %s\n", TELOPT(i)); | |
296 | else if (TELCMD_OK(i)) | |
297 | printf("want WONT %s\n", TELCMD(i)); | |
298 | else | |
299 | printf("want WONT %d\n", i); | |
300 | } | |
301 | } else { | |
302 | if (my_state_is_will(i)) { | |
303 | if (TELOPT_OK(i)) | |
304 | printf(" WILL %s\n", TELOPT(i)); | |
305 | else if (TELCMD_OK(i)) | |
306 | printf(" WILL %s\n", TELCMD(i)); | |
307 | else | |
308 | printf(" WILL %d\n", i); | |
309 | } | |
310 | } | |
311 | } | |
312 | ||
313 | } | |
314 | ||
315 | void | |
316 | printsub(direction, pointer, length) | |
317 | char direction; /* '<' or '>' */ | |
318 | unsigned char *pointer; /* where suboption data sits */ | |
319 | int length; /* length of suboption data */ | |
320 | { | |
321 | register int i; | |
322 | char buf[512]; | |
323 | extern int want_status_response; | |
324 | ||
325 | if (showoptions || direction == 0 || | |
326 | (want_status_response && (pointer[0] == TELOPT_STATUS))) { | |
327 | if (direction) { | |
328 | fprintf(NetTrace, "%s IAC SB ", | |
329 | (direction == '<')? "RCVD":"SENT"); | |
330 | if (length >= 3) { | |
331 | register int j; | |
332 | ||
333 | i = pointer[length-2]; | |
334 | j = pointer[length-1]; | |
335 | ||
336 | if (i != IAC || j != SE) { | |
337 | fprintf(NetTrace, "(terminated by "); | |
338 | if (TELOPT_OK(i)) | |
339 | fprintf(NetTrace, "%s ", TELOPT(i)); | |
340 | else if (TELCMD_OK(i)) | |
341 | fprintf(NetTrace, "%s ", TELCMD(i)); | |
342 | else | |
343 | fprintf(NetTrace, "%d ", i); | |
344 | if (TELOPT_OK(j)) | |
345 | fprintf(NetTrace, "%s", TELOPT(j)); | |
346 | else if (TELCMD_OK(j)) | |
347 | fprintf(NetTrace, "%s", TELCMD(j)); | |
348 | else | |
349 | fprintf(NetTrace, "%d", j); | |
350 | fprintf(NetTrace, ", not IAC SE!) "); | |
351 | } | |
352 | } | |
353 | length -= 2; | |
354 | } | |
355 | if (length < 1) { | |
356 | fprintf(NetTrace, "(Empty suboption??\?)"); | |
357 | if (NetTrace == stdout) | |
358 | fflush(NetTrace); | |
359 | return; | |
360 | } | |
361 | switch (pointer[0]) { | |
362 | case TELOPT_TTYPE: | |
363 | fprintf(NetTrace, "TERMINAL-TYPE "); | |
364 | switch (pointer[1]) { | |
365 | case TELQUAL_IS: | |
366 | fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); | |
367 | break; | |
368 | case TELQUAL_SEND: | |
369 | fprintf(NetTrace, "SEND"); | |
370 | break; | |
371 | default: | |
372 | fprintf(NetTrace, | |
373 | "- unknown qualifier %d (0x%x).", | |
374 | pointer[1], pointer[1]); | |
375 | } | |
376 | break; | |
377 | case TELOPT_TSPEED: | |
378 | fprintf(NetTrace, "TERMINAL-SPEED"); | |
379 | if (length < 2) { | |
380 | fprintf(NetTrace, " (empty suboption??\?)"); | |
381 | break; | |
382 | } | |
383 | switch (pointer[1]) { | |
384 | case TELQUAL_IS: | |
385 | fprintf(NetTrace, " IS "); | |
386 | fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); | |
387 | break; | |
388 | default: | |
389 | if (pointer[1] == 1) | |
390 | fprintf(NetTrace, " SEND"); | |
391 | else | |
392 | fprintf(NetTrace, " %d (unknown)", pointer[1]); | |
393 | for (i = 2; i < length; i++) | |
394 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
395 | break; | |
396 | } | |
397 | break; | |
398 | ||
399 | case TELOPT_LFLOW: | |
400 | fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); | |
401 | if (length < 2) { | |
402 | fprintf(NetTrace, " (empty suboption??\?)"); | |
403 | break; | |
404 | } | |
405 | switch (pointer[1]) { | |
406 | case LFLOW_OFF: | |
407 | fprintf(NetTrace, " OFF"); break; | |
408 | case LFLOW_ON: | |
409 | fprintf(NetTrace, " ON"); break; | |
410 | case LFLOW_RESTART_ANY: | |
411 | fprintf(NetTrace, " RESTART-ANY"); break; | |
412 | case LFLOW_RESTART_XON: | |
413 | fprintf(NetTrace, " RESTART-XON"); break; | |
414 | default: | |
415 | fprintf(NetTrace, " %d (unknown)", pointer[1]); | |
416 | } | |
417 | for (i = 2; i < length; i++) | |
418 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
419 | break; | |
420 | ||
421 | case TELOPT_NAWS: | |
422 | fprintf(NetTrace, "NAWS"); | |
423 | if (length < 2) { | |
424 | fprintf(NetTrace, " (empty suboption??\?)"); | |
425 | break; | |
426 | } | |
427 | if (length == 2) { | |
428 | fprintf(NetTrace, " ?%d?", pointer[1]); | |
429 | break; | |
430 | } | |
431 | fprintf(NetTrace, " %d %d (%d)", | |
432 | pointer[1], pointer[2], | |
433 | (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); | |
434 | if (length == 4) { | |
435 | fprintf(NetTrace, " ?%d?", pointer[3]); | |
436 | break; | |
437 | } | |
438 | fprintf(NetTrace, " %d %d (%d)", | |
439 | pointer[3], pointer[4], | |
440 | (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); | |
441 | for (i = 5; i < length; i++) | |
442 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
443 | break; | |
444 | ||
445 | #if defined(AUTHENTICATION) | |
446 | case TELOPT_AUTHENTICATION: | |
447 | fprintf(NetTrace, "AUTHENTICATION"); | |
448 | if (length < 2) { | |
449 | fprintf(NetTrace, " (empty suboption??\?)"); | |
450 | break; | |
451 | } | |
452 | switch (pointer[1]) { | |
453 | case TELQUAL_REPLY: | |
454 | case TELQUAL_IS: | |
455 | fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? | |
456 | "IS" : "REPLY"); | |
457 | if (AUTHTYPE_NAME_OK(pointer[2])) | |
458 | fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); | |
459 | else | |
460 | fprintf(NetTrace, "%d ", pointer[2]); | |
461 | if (length < 3) { | |
462 | fprintf(NetTrace, "(partial suboption??\?)"); | |
463 | break; | |
464 | } | |
465 | fprintf(NetTrace, "%s|%s", | |
466 | ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? | |
467 | "CLIENT" : "SERVER", | |
468 | ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? | |
469 | "MUTUAL" : "ONE-WAY"); | |
470 | ||
471 | auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); | |
472 | fprintf(NetTrace, "%s", buf); | |
473 | break; | |
474 | ||
475 | case TELQUAL_SEND: | |
476 | i = 2; | |
477 | fprintf(NetTrace, " SEND "); | |
478 | while (i < length) { | |
479 | if (AUTHTYPE_NAME_OK(pointer[i])) | |
480 | fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); | |
481 | else | |
482 | fprintf(NetTrace, "%d ", pointer[i]); | |
483 | if (++i >= length) { | |
484 | fprintf(NetTrace, "(partial suboption??\?)"); | |
485 | break; | |
486 | } | |
487 | fprintf(NetTrace, "%s|%s ", | |
488 | ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? | |
489 | "CLIENT" : "SERVER", | |
490 | ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? | |
491 | "MUTUAL" : "ONE-WAY"); | |
492 | ++i; | |
493 | } | |
494 | break; | |
495 | ||
496 | case TELQUAL_NAME: | |
497 | i = 2; | |
498 | fprintf(NetTrace, " NAME \""); | |
499 | while (i < length) | |
500 | putc(pointer[i++], NetTrace); | |
501 | putc('"', NetTrace); | |
502 | break; | |
503 | ||
504 | default: | |
505 | for (i = 2; i < length; i++) | |
506 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
507 | break; | |
508 | } | |
509 | break; | |
510 | #endif | |
511 | ||
512 | #ifdef ENCRYPTION | |
513 | case TELOPT_ENCRYPT: | |
514 | fprintf(NetTrace, "ENCRYPT"); | |
515 | if (length < 2) { | |
516 | fprintf(NetTrace, " (empty suboption??\?)"); | |
517 | break; | |
518 | } | |
519 | switch (pointer[1]) { | |
520 | case ENCRYPT_START: | |
521 | fprintf(NetTrace, " START"); | |
522 | break; | |
523 | ||
524 | case ENCRYPT_END: | |
525 | fprintf(NetTrace, " END"); | |
526 | break; | |
527 | ||
528 | case ENCRYPT_REQSTART: | |
529 | fprintf(NetTrace, " REQUEST-START"); | |
530 | break; | |
531 | ||
532 | case ENCRYPT_REQEND: | |
533 | fprintf(NetTrace, " REQUEST-END"); | |
534 | break; | |
535 | ||
536 | case ENCRYPT_IS: | |
537 | case ENCRYPT_REPLY: | |
538 | fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? | |
539 | "IS" : "REPLY"); | |
540 | if (length < 3) { | |
541 | fprintf(NetTrace, " (partial suboption??\?)"); | |
542 | break; | |
543 | } | |
544 | if (ENCTYPE_NAME_OK(pointer[2])) | |
545 | fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); | |
546 | else | |
547 | fprintf(NetTrace, " %d (unknown)", pointer[2]); | |
548 | ||
549 | encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); | |
550 | fprintf(NetTrace, "%s", buf); | |
551 | break; | |
552 | ||
553 | case ENCRYPT_SUPPORT: | |
554 | i = 2; | |
555 | fprintf(NetTrace, " SUPPORT "); | |
556 | while (i < length) { | |
557 | if (ENCTYPE_NAME_OK(pointer[i])) | |
558 | fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); | |
559 | else | |
560 | fprintf(NetTrace, "%d ", pointer[i]); | |
561 | i++; | |
562 | } | |
563 | break; | |
564 | ||
565 | case ENCRYPT_ENC_KEYID: | |
566 | fprintf(NetTrace, " ENC_KEYID "); | |
567 | goto encommon; | |
568 | ||
569 | case ENCRYPT_DEC_KEYID: | |
570 | fprintf(NetTrace, " DEC_KEYID "); | |
571 | goto encommon; | |
572 | ||
573 | default: | |
574 | fprintf(NetTrace, " %d (unknown)", pointer[1]); | |
575 | encommon: | |
576 | for (i = 2; i < length; i++) | |
577 | fprintf(NetTrace, " %d", pointer[i]); | |
578 | break; | |
579 | } | |
580 | break; | |
581 | #endif /* ENCRYPTION */ | |
582 | ||
583 | case TELOPT_LINEMODE: | |
584 | fprintf(NetTrace, "LINEMODE "); | |
585 | if (length < 2) { | |
586 | fprintf(NetTrace, " (empty suboption??\?)"); | |
587 | break; | |
588 | } | |
589 | switch (pointer[1]) { | |
590 | case WILL: | |
591 | fprintf(NetTrace, "WILL "); | |
592 | goto common; | |
593 | case WONT: | |
594 | fprintf(NetTrace, "WONT "); | |
595 | goto common; | |
596 | case DO: | |
597 | fprintf(NetTrace, "DO "); | |
598 | goto common; | |
599 | case DONT: | |
600 | fprintf(NetTrace, "DONT "); | |
601 | common: | |
602 | if (length < 3) { | |
603 | fprintf(NetTrace, "(no option??\?)"); | |
604 | break; | |
605 | } | |
606 | switch (pointer[2]) { | |
607 | case LM_FORWARDMASK: | |
608 | fprintf(NetTrace, "Forward Mask"); | |
609 | for (i = 3; i < length; i++) | |
610 | fprintf(NetTrace, " %x", pointer[i]); | |
611 | break; | |
612 | default: | |
613 | fprintf(NetTrace, "%d (unknown)", pointer[2]); | |
614 | for (i = 3; i < length; i++) | |
615 | fprintf(NetTrace, " %d", pointer[i]); | |
616 | break; | |
617 | } | |
618 | break; | |
619 | ||
620 | case LM_SLC: | |
621 | fprintf(NetTrace, "SLC"); | |
622 | for (i = 2; i < length - 2; i += 3) { | |
623 | if (SLC_NAME_OK(pointer[i+SLC_FUNC])) | |
624 | fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); | |
625 | else | |
626 | fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); | |
627 | switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { | |
628 | case SLC_NOSUPPORT: | |
629 | fprintf(NetTrace, " NOSUPPORT"); break; | |
630 | case SLC_CANTCHANGE: | |
631 | fprintf(NetTrace, " CANTCHANGE"); break; | |
632 | case SLC_VARIABLE: | |
633 | fprintf(NetTrace, " VARIABLE"); break; | |
634 | case SLC_DEFAULT: | |
635 | fprintf(NetTrace, " DEFAULT"); break; | |
636 | } | |
637 | fprintf(NetTrace, "%s%s%s", | |
638 | pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", | |
639 | pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", | |
640 | pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); | |
641 | if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| | |
642 | SLC_FLUSHOUT| SLC_LEVELBITS)) | |
643 | fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); | |
644 | fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); | |
645 | if ((pointer[i+SLC_VALUE] == IAC) && | |
646 | (pointer[i+SLC_VALUE+1] == IAC)) | |
647 | i++; | |
648 | } | |
649 | for (; i < length; i++) | |
650 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
651 | break; | |
652 | ||
653 | case LM_MODE: | |
654 | fprintf(NetTrace, "MODE "); | |
655 | if (length < 3) { | |
656 | fprintf(NetTrace, "(no mode??\?)"); | |
657 | break; | |
658 | } | |
659 | { | |
660 | char tbuf[64]; | |
661 | sprintf(tbuf, "%s%s%s%s%s", | |
662 | pointer[2]&MODE_EDIT ? "|EDIT" : "", | |
663 | pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", | |
664 | pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", | |
665 | pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", | |
666 | pointer[2]&MODE_ACK ? "|ACK" : ""); | |
667 | fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); | |
668 | } | |
669 | if (pointer[2]&~(MODE_MASK)) | |
670 | fprintf(NetTrace, " (0x%x)", pointer[2]); | |
671 | for (i = 3; i < length; i++) | |
672 | fprintf(NetTrace, " ?0x%x?", pointer[i]); | |
673 | break; | |
674 | default: | |
675 | fprintf(NetTrace, "%d (unknown)", pointer[1]); | |
676 | for (i = 2; i < length; i++) | |
677 | fprintf(NetTrace, " %d", pointer[i]); | |
678 | } | |
679 | break; | |
680 | ||
681 | case TELOPT_STATUS: { | |
682 | register char *cp; | |
683 | register int j, k; | |
684 | ||
685 | fprintf(NetTrace, "STATUS"); | |
686 | ||
687 | switch (pointer[1]) { | |
688 | default: | |
689 | if (pointer[1] == TELQUAL_SEND) | |
690 | fprintf(NetTrace, " SEND"); | |
691 | else | |
692 | fprintf(NetTrace, " %d (unknown)", pointer[1]); | |
693 | for (i = 2; i < length; i++) | |
694 | fprintf(NetTrace, " ?%d?", pointer[i]); | |
695 | break; | |
696 | case TELQUAL_IS: | |
697 | if (--want_status_response < 0) | |
698 | want_status_response = 0; | |
699 | if (NetTrace == stdout) | |
700 | fprintf(NetTrace, " IS\r\n"); | |
701 | else | |
702 | fprintf(NetTrace, " IS\n"); | |
703 | ||
704 | for (i = 2; i < length; i++) { | |
705 | switch(pointer[i]) { | |
706 | case DO: cp = "DO"; goto common2; | |
707 | case DONT: cp = "DONT"; goto common2; | |
708 | case WILL: cp = "WILL"; goto common2; | |
709 | case WONT: cp = "WONT"; goto common2; | |
710 | common2: | |
711 | i++; | |
712 | if (TELOPT_OK((int)pointer[i])) | |
713 | fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); | |
714 | else | |
715 | fprintf(NetTrace, " %s %d", cp, pointer[i]); | |
716 | ||
717 | if (NetTrace == stdout) | |
718 | fprintf(NetTrace, "\r\n"); | |
719 | else | |
720 | fprintf(NetTrace, "\n"); | |
721 | break; | |
722 | ||
723 | case SB: | |
724 | fprintf(NetTrace, " SB "); | |
725 | i++; | |
726 | j = k = i; | |
727 | while (j < length) { | |
728 | if (pointer[j] == SE) { | |
729 | if (j+1 == length) | |
730 | break; | |
731 | if (pointer[j+1] == SE) | |
732 | j++; | |
733 | else | |
734 | break; | |
735 | } | |
736 | pointer[k++] = pointer[j++]; | |
737 | } | |
738 | printsub(0, &pointer[i], k - i); | |
739 | if (i < length) { | |
740 | fprintf(NetTrace, " SE"); | |
741 | i = j; | |
742 | } else | |
743 | i = j - 1; | |
744 | ||
745 | if (NetTrace == stdout) | |
746 | fprintf(NetTrace, "\r\n"); | |
747 | else | |
748 | fprintf(NetTrace, "\n"); | |
749 | ||
750 | break; | |
751 | ||
752 | default: | |
753 | fprintf(NetTrace, " %d", pointer[i]); | |
754 | break; | |
755 | } | |
756 | } | |
757 | break; | |
758 | } | |
759 | break; | |
760 | } | |
761 | ||
762 | case TELOPT_XDISPLOC: | |
763 | fprintf(NetTrace, "X-DISPLAY-LOCATION "); | |
764 | switch (pointer[1]) { | |
765 | case TELQUAL_IS: | |
766 | fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); | |
767 | break; | |
768 | case TELQUAL_SEND: | |
769 | fprintf(NetTrace, "SEND"); | |
770 | break; | |
771 | default: | |
772 | fprintf(NetTrace, "- unknown qualifier %d (0x%x).", | |
773 | pointer[1], pointer[1]); | |
774 | } | |
775 | break; | |
776 | ||
777 | case TELOPT_NEW_ENVIRON: | |
778 | fprintf(NetTrace, "NEW-ENVIRON "); | |
779 | #ifdef OLD_ENVIRON | |
780 | goto env_common1; | |
781 | case TELOPT_OLD_ENVIRON: | |
782 | fprintf(NetTrace, "OLD-ENVIRON"); | |
783 | env_common1: | |
784 | #endif | |
785 | switch (pointer[1]) { | |
786 | case TELQUAL_IS: | |
787 | fprintf(NetTrace, "IS "); | |
788 | goto env_common; | |
789 | case TELQUAL_SEND: | |
790 | fprintf(NetTrace, "SEND "); | |
791 | goto env_common; | |
792 | case TELQUAL_INFO: | |
793 | fprintf(NetTrace, "INFO "); | |
794 | env_common: | |
795 | { | |
796 | register int noquote = 2; | |
797 | #if defined(ENV_HACK) && defined(OLD_ENVIRON) | |
798 | extern int old_env_var, old_env_value; | |
799 | #endif | |
800 | for (i = 2; i < length; i++ ) { | |
801 | switch (pointer[i]) { | |
802 | case NEW_ENV_VALUE: | |
803 | #ifdef OLD_ENVIRON | |
804 | /* case NEW_ENV_OVAR: */ | |
805 | if (pointer[0] == TELOPT_OLD_ENVIRON) { | |
806 | # ifdef ENV_HACK | |
807 | if (old_env_var == OLD_ENV_VALUE) | |
808 | fprintf(NetTrace, "\" (VALUE) " + noquote); | |
809 | else | |
810 | # endif | |
811 | fprintf(NetTrace, "\" VAR " + noquote); | |
812 | } else | |
813 | #endif /* OLD_ENVIRON */ | |
814 | fprintf(NetTrace, "\" VALUE " + noquote); | |
815 | noquote = 2; | |
816 | break; | |
817 | ||
818 | case NEW_ENV_VAR: | |
819 | #ifdef OLD_ENVIRON | |
820 | /* case OLD_ENV_VALUE: */ | |
821 | if (pointer[0] == TELOPT_OLD_ENVIRON) { | |
822 | # ifdef ENV_HACK | |
823 | if (old_env_value == OLD_ENV_VAR) | |
824 | fprintf(NetTrace, "\" (VAR) " + noquote); | |
825 | else | |
826 | # endif | |
827 | fprintf(NetTrace, "\" VALUE " + noquote); | |
828 | } else | |
829 | #endif /* OLD_ENVIRON */ | |
830 | fprintf(NetTrace, "\" VAR " + noquote); | |
831 | noquote = 2; | |
832 | break; | |
833 | ||
834 | case ENV_ESC: | |
835 | fprintf(NetTrace, "\" ESC " + noquote); | |
836 | noquote = 2; | |
837 | break; | |
838 | ||
839 | case ENV_USERVAR: | |
840 | fprintf(NetTrace, "\" USERVAR " + noquote); | |
841 | noquote = 2; | |
842 | break; | |
843 | ||
844 | default: | |
845 | def_case: | |
846 | if (isprint(pointer[i]) && pointer[i] != '"') { | |
847 | if (noquote) { | |
848 | putc('"', NetTrace); | |
849 | noquote = 0; | |
850 | } | |
851 | putc(pointer[i], NetTrace); | |
852 | } else { | |
853 | fprintf(NetTrace, "\" %03o " + noquote, | |
854 | pointer[i]); | |
855 | noquote = 2; | |
856 | } | |
857 | break; | |
858 | } | |
859 | } | |
860 | if (!noquote) | |
861 | putc('"', NetTrace); | |
862 | break; | |
863 | } | |
864 | } | |
865 | break; | |
866 | ||
867 | default: | |
868 | if (TELOPT_OK(pointer[0])) | |
869 | fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); | |
870 | else | |
871 | fprintf(NetTrace, "%d (unknown)", pointer[0]); | |
872 | for (i = 1; i < length; i++) | |
873 | fprintf(NetTrace, " %d", pointer[i]); | |
874 | break; | |
875 | } | |
876 | if (direction) { | |
877 | if (NetTrace == stdout) | |
878 | fprintf(NetTrace, "\r\n"); | |
879 | else | |
880 | fprintf(NetTrace, "\n"); | |
881 | } | |
882 | if (NetTrace == stdout) | |
883 | fflush(NetTrace); | |
884 | } | |
885 | } | |
886 | ||
887 | /* EmptyTerminal - called to make sure that the terminal buffer is empty. | |
888 | * Note that we consider the buffer to run all the | |
889 | * way to the kernel (thus the select). | |
890 | */ | |
891 | ||
892 | void | |
893 | EmptyTerminal() | |
894 | { | |
895 | #if defined(unix) || defined(__APPLE__) | |
896 | fd_set o; | |
897 | ||
898 | FD_ZERO(&o); | |
899 | #endif /* defined(unix) || defined(__APPLE__) */ | |
900 | ||
901 | if (TTYBYTES() == 0) { | |
902 | #if defined(unix) || defined(__APPLE__) | |
903 | FD_SET(tout, &o); | |
904 | (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, | |
905 | (struct timeval *) 0); /* wait for TTLOWAT */ | |
906 | #endif /* defined(unix) || defined(__APPLE__) */ | |
907 | } else { | |
908 | while (TTYBYTES()) { | |
909 | (void) ttyflush(0); | |
910 | #if defined(unix) || defined(__APPLE__) | |
911 | FD_SET(tout, &o); | |
912 | (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, | |
913 | (struct timeval *) 0); /* wait for TTLOWAT */ | |
914 | #endif /* defined(unix) || defined(__APPLE__) */ | |
915 | } | |
916 | } | |
917 | } | |
918 | ||
919 | void | |
920 | SetForExit() | |
921 | { | |
922 | setconnmode(0); | |
923 | #if defined(TN3270) | |
924 | if (In3270) { | |
925 | Finish3270(); | |
926 | } | |
927 | #else /* defined(TN3270) */ | |
928 | do { | |
929 | (void)telrcv(); /* Process any incoming data */ | |
930 | EmptyTerminal(); | |
931 | } while (ring_full_count(&netiring)); /* While there is any */ | |
932 | #endif /* defined(TN3270) */ | |
933 | setcommandmode(); | |
934 | fflush(stdout); | |
935 | fflush(stderr); | |
936 | #if defined(TN3270) | |
937 | if (In3270) { | |
938 | StopScreen(1); | |
939 | } | |
940 | #endif /* defined(TN3270) */ | |
941 | setconnmode(0); | |
942 | EmptyTerminal(); /* Flush the path to the tty */ | |
943 | setcommandmode(); | |
944 | } | |
945 | ||
946 | void | |
947 | Exit(returnCode) | |
948 | int returnCode; | |
949 | { | |
950 | SetForExit(); | |
951 | exit(returnCode); | |
952 | } | |
953 | ||
954 | void | |
955 | ExitString(string, returnCode) | |
956 | char *string; | |
957 | int returnCode; | |
958 | { | |
959 | SetForExit(); | |
960 | fwrite(string, 1, strlen(string), stderr); | |
961 | exit(returnCode); | |
962 | } |