Mercurial > illumos > onarm
comparison usr/src/cmd/cmd-inet/usr.bin/telnet/utilities.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c9caec207d52 |
---|---|
1 /* | |
2 * Copyright 1994-2002 Sun Microsystems, Inc. All rights reserved. | |
3 * Use is subject to license terms. | |
4 */ | |
5 | |
6 #pragma ident "@(#)utilities.c 1.19 05/06/12 SMI" | |
7 | |
8 /* | |
9 * usr/src/cmd/cmd-inet/usr.bin/telnet/utilities.c | |
10 */ | |
11 | |
12 /* | |
13 * Copyright (c) 1988, 1993 | |
14 * The Regents of the University of California. All rights reserved. | |
15 * | |
16 * Redistribution and use in source and binary forms, with or without | |
17 * modification, are permitted provided that the following conditions | |
18 * are met: | |
19 * 1. Redistributions of source code must retain the above copyright | |
20 * notice, this list of conditions and the following disclaimer. | |
21 * 2. Redistributions in binary form must reproduce the above copyright | |
22 * notice, this list of conditions and the following disclaimer in the | |
23 * documentation and/or other materials provided with the distribution. | |
24 * 3. All advertising materials mentioning features or use of this software | |
25 * must display the following acknowledgement: | |
26 * This product includes software developed by the University of | |
27 * California, Berkeley and its contributors. | |
28 * 4. Neither the name of the University nor the names of its contributors | |
29 * may be used to endorse or promote products derived from this software | |
30 * without specific prior written permission. | |
31 * | |
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
42 * SUCH DAMAGE. | |
43 */ | |
44 | |
45 #ifndef lint | |
46 static char sccsid[] = "@(#)utilities.c 8.1 (Berkeley) 6/6/93"; | |
47 #endif /* not lint */ | |
48 | |
49 #define TELOPTS | |
50 #ifdef lint | |
51 static char *telcmds[] = {0}; | |
52 static char *slc_names[] = {0}; | |
53 static char *encrypt_names[] = {0}; | |
54 static char *enctype_names[] = {0}; | |
55 #else /* lint */ | |
56 #define TELCMDS | |
57 #define SLC_NAMES | |
58 #endif /* lint */ | |
59 #include <arpa/telnet.h> | |
60 #include <sys/types.h> | |
61 #include <sys/time.h> | |
62 #include <sys/param.h> | |
63 #include <sys/socket.h> | |
64 #include <errno.h> | |
65 | |
66 #include <ctype.h> | |
67 | |
68 #include "general.h" | |
69 | |
70 #include "ring.h" | |
71 | |
72 #include "defines.h" | |
73 | |
74 #include "externs.h" | |
75 | |
76 FILE *NetTrace = 0; /* Not in bss, since needs to stay */ | |
77 int prettydump; | |
78 | |
79 /* | |
80 * upcase() | |
81 * | |
82 * Upcase (in place) the argument. | |
83 */ | |
84 | |
85 void | |
86 upcase(argument) | |
87 register char *argument; | |
88 { | |
89 register int c; | |
90 | |
91 while ((c = *argument) != 0) { | |
92 if (islower(c)) { | |
93 *argument = toupper(c); | |
94 } | |
95 argument++; | |
96 } | |
97 } | |
98 | |
99 /* | |
100 * SetSockOpt() | |
101 * | |
102 * Compensate for differences in 4.2 and 4.3 systems. | |
103 */ | |
104 | |
105 int | |
106 SetSockOpt(fd, level, option, yesno) | |
107 int fd, level, option, yesno; | |
108 { | |
109 return (setsockopt(fd, level, option, &yesno, sizeof (yesno))); | |
110 } | |
111 | |
112 /* | |
113 * The following are routines used to print out debugging information. | |
114 */ | |
115 | |
116 unsigned char NetTraceFile[MAXPATHLEN] = "(standard output)"; | |
117 | |
118 void | |
119 SetNetTrace(file) | |
120 register char *file; | |
121 { | |
122 if (NetTrace && NetTrace != stdout) | |
123 (void) fclose(NetTrace); | |
124 if (file && (strcmp(file, "-") != 0)) { | |
125 NetTrace = fopen(file, "w"); | |
126 if (NetTrace) { | |
127 (void) strcpy((char *)NetTraceFile, file); | |
128 return; | |
129 } | |
130 (void) fprintf(stderr, "Cannot open %s.\n", file); | |
131 } | |
132 NetTrace = stdout; | |
133 (void) strcpy((char *)NetTraceFile, "(standard output)"); | |
134 } | |
135 | |
136 void | |
137 Dump(direction, buffer, length) | |
138 char direction; | |
139 unsigned char *buffer; | |
140 int length; | |
141 { | |
142 #define BYTES_PER_LINE 32 | |
143 #define min(x, y) ((x < y) ? x:y) | |
144 unsigned char *pThis; | |
145 int offset; | |
146 | |
147 offset = 0; | |
148 | |
149 while (length) { | |
150 /* print one line */ | |
151 (void) fprintf(NetTrace, "%c 0x%x\t", direction, offset); | |
152 pThis = buffer; | |
153 if (prettydump) { | |
154 buffer = buffer + min(length, BYTES_PER_LINE/2); | |
155 while (pThis < buffer) { | |
156 (void) fprintf(NetTrace, "%c%.2x", | |
157 (((*pThis)&0xff) == 0xff) ? '*' : ' ', | |
158 (*pThis)&0xff); | |
159 pThis++; | |
160 } | |
161 length -= BYTES_PER_LINE/2; | |
162 offset += BYTES_PER_LINE/2; | |
163 } else { | |
164 buffer = buffer + min(length, BYTES_PER_LINE); | |
165 while (pThis < buffer) { | |
166 (void) fprintf(NetTrace, "%.2x", (*pThis)&0xff); | |
167 pThis++; | |
168 } | |
169 length -= BYTES_PER_LINE; | |
170 offset += BYTES_PER_LINE; | |
171 } | |
172 if (NetTrace == stdout) { | |
173 (void) fprintf(NetTrace, "\r\n"); | |
174 } else { | |
175 (void) fprintf(NetTrace, "\n"); | |
176 } | |
177 if (length < 0) { | |
178 (void) fflush(NetTrace); | |
179 return; | |
180 } | |
181 /* find next unique line */ | |
182 } | |
183 (void) fflush(NetTrace); | |
184 } | |
185 | |
186 | |
187 void | |
188 printoption(direction, cmd, option) | |
189 char *direction; | |
190 int cmd, option; | |
191 { | |
192 if (!showoptions) | |
193 return; | |
194 if (cmd == IAC) { | |
195 if (TELCMD_OK(option)) | |
196 (void) fprintf(NetTrace, "%s IAC %s", direction, | |
197 TELCMD(option)); | |
198 else | |
199 (void) fprintf(NetTrace, "%s IAC %d", direction, | |
200 option); | |
201 } else { | |
202 register char *fmt; | |
203 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : | |
204 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; | |
205 if (fmt) { | |
206 (void) fprintf(NetTrace, "%s %s ", direction, fmt); | |
207 if (TELOPT_OK(option)) | |
208 (void) fprintf(NetTrace, "%s", TELOPT(option)); | |
209 else if (option == TELOPT_EXOPL) | |
210 (void) fprintf(NetTrace, "EXOPL"); | |
211 else | |
212 (void) fprintf(NetTrace, "%d", option); | |
213 } else | |
214 (void) fprintf(NetTrace, "%s %d %d", direction, cmd, | |
215 option); | |
216 } | |
217 if (NetTrace == stdout) { | |
218 (void) fprintf(NetTrace, "\r\n"); | |
219 (void) fflush(NetTrace); | |
220 } else { | |
221 (void) fprintf(NetTrace, "\n"); | |
222 } | |
223 } | |
224 | |
225 void | |
226 optionstatus() | |
227 { | |
228 register int i; | |
229 extern char will_wont_resp[], do_dont_resp[]; | |
230 | |
231 for (i = 0; i < SUBBUFSIZE; i++) { | |
232 if (do_dont_resp[i]) { | |
233 if (TELOPT_OK(i)) | |
234 (void) printf("resp DO_DONT %s: %d\n", | |
235 TELOPT(i), do_dont_resp[i]); | |
236 else if (TELCMD_OK(i)) | |
237 (void) printf("resp DO_DONT %s: %d\n", | |
238 TELCMD(i), do_dont_resp[i]); | |
239 else | |
240 (void) printf("resp DO_DONT %d: %d\n", i, | |
241 do_dont_resp[i]); | |
242 if (my_want_state_is_do(i)) { | |
243 if (TELOPT_OK(i)) | |
244 (void) printf("want DO %s\n", | |
245 TELOPT(i)); | |
246 else if (TELCMD_OK(i)) | |
247 (void) printf("want DO %s\n", | |
248 TELCMD(i)); | |
249 else | |
250 (void) printf("want DO %d\n", i); | |
251 } else { | |
252 if (TELOPT_OK(i)) | |
253 (void) printf("want DONT %s\n", | |
254 TELOPT(i)); | |
255 else if (TELCMD_OK(i)) | |
256 (void) printf("want DONT %s\n", | |
257 TELCMD(i)); | |
258 else | |
259 (void) printf("want DONT %d\n", i); | |
260 } | |
261 } else { | |
262 if (my_state_is_do(i)) { | |
263 if (TELOPT_OK(i)) | |
264 (void) printf(" DO %s\n", | |
265 TELOPT(i)); | |
266 else if (TELCMD_OK(i)) | |
267 (void) printf(" DO %s\n", | |
268 TELCMD(i)); | |
269 else | |
270 (void) printf(" DO %d\n", i); | |
271 } | |
272 } | |
273 if (will_wont_resp[i]) { | |
274 if (TELOPT_OK(i)) | |
275 (void) printf("resp WILL_WONT %s: %d\n", | |
276 TELOPT(i), will_wont_resp[i]); | |
277 else if (TELCMD_OK(i)) | |
278 (void) printf("resp WILL_WONT %s: %d\n", | |
279 TELCMD(i), will_wont_resp[i]); | |
280 else | |
281 (void) printf("resp WILL_WONT %d: %d\n", | |
282 i, will_wont_resp[i]); | |
283 if (my_want_state_is_will(i)) { | |
284 if (TELOPT_OK(i)) | |
285 (void) printf("want WILL %s\n", | |
286 TELOPT(i)); | |
287 else if (TELCMD_OK(i)) | |
288 (void) printf("want WILL %s\n", | |
289 TELCMD(i)); | |
290 else | |
291 (void) printf("want WILL %d\n", i); | |
292 } else { | |
293 if (TELOPT_OK(i)) | |
294 (void) printf("want WONT %s\n", | |
295 TELOPT(i)); | |
296 else if (TELCMD_OK(i)) | |
297 (void) printf("want WONT %s\n", | |
298 TELCMD(i)); | |
299 else | |
300 (void) printf("want WONT %d\n", i); | |
301 } | |
302 } else { | |
303 if (my_state_is_will(i)) { | |
304 if (TELOPT_OK(i)) | |
305 (void) printf(" WILL %s\n", | |
306 TELOPT(i)); | |
307 else if (TELCMD_OK(i)) | |
308 (void) printf(" WILL %s\n", | |
309 TELCMD(i)); | |
310 else | |
311 (void) printf(" WILL %d\n", i); | |
312 } | |
313 } | |
314 } | |
315 | |
316 } | |
317 | |
318 void | |
319 printsub(direction, pointer, length) | |
320 char direction; /* '<' or '>' */ | |
321 unsigned char *pointer; /* where suboption data sits */ | |
322 int length; /* length of suboption data */ | |
323 { | |
324 register int i; | |
325 char buf[512]; | |
326 extern int want_status_response; | |
327 | |
328 if (showoptions || direction == 0 || | |
329 (want_status_response && (pointer[0] == TELOPT_STATUS))) { | |
330 if (direction) { | |
331 (void) fprintf(NetTrace, "%s IAC SB ", | |
332 (direction == '<')? "RCVD":"SENT"); | |
333 if (length >= 3) { | |
334 register int j; | |
335 | |
336 i = pointer[length-2]; | |
337 j = pointer[length-1]; | |
338 | |
339 if (i != IAC || j != SE) { | |
340 (void) fprintf(NetTrace, | |
341 "(terminated by "); | |
342 if (TELOPT_OK(i)) | |
343 (void) fprintf(NetTrace, "%s ", | |
344 TELOPT(i)); | |
345 else if (TELCMD_OK(i)) | |
346 (void) fprintf(NetTrace, "%s ", | |
347 TELCMD(i)); | |
348 else | |
349 (void) fprintf(NetTrace, "%d ", | |
350 i); | |
351 if (TELOPT_OK(j)) | |
352 (void) fprintf(NetTrace, "%s", | |
353 TELOPT(j)); | |
354 else if (TELCMD_OK(j)) | |
355 (void) fprintf(NetTrace, "%s", | |
356 TELCMD(j)); | |
357 else | |
358 (void) fprintf(NetTrace, "%d", | |
359 j); | |
360 (void) fprintf(NetTrace, | |
361 ", not IAC SE!) "); | |
362 } | |
363 } | |
364 length -= 2; | |
365 } | |
366 if (length < 1) { | |
367 (void) fprintf(NetTrace, "(Empty suboption??\?)"); | |
368 if (NetTrace == stdout) | |
369 (void) fflush(NetTrace); | |
370 return; | |
371 } | |
372 switch (pointer[0]) { | |
373 case TELOPT_TTYPE: | |
374 (void) fprintf(NetTrace, "TERMINAL-TYPE "); | |
375 switch (pointer[1]) { | |
376 case TELQUAL_IS: | |
377 (void) fprintf(NetTrace, "IS \"%.*s\"", | |
378 length-2, | |
379 (char *)pointer+2); | |
380 break; | |
381 case TELQUAL_SEND: | |
382 (void) fprintf(NetTrace, "SEND"); | |
383 break; | |
384 default: | |
385 (void) fprintf(NetTrace, | |
386 "- unknown qualifier %d (0x%x).", | |
387 pointer[1], pointer[1]); | |
388 } | |
389 break; | |
390 case TELOPT_TSPEED: | |
391 (void) fprintf(NetTrace, "TERMINAL-SPEED"); | |
392 if (length < 2) { | |
393 (void) fprintf(NetTrace, | |
394 " (empty suboption??\?)"); | |
395 break; | |
396 } | |
397 switch (pointer[1]) { | |
398 case TELQUAL_IS: | |
399 (void) fprintf(NetTrace, " IS "); | |
400 (void) fprintf(NetTrace, "%.*s", length-2, | |
401 (char *)pointer+2); | |
402 break; | |
403 default: | |
404 if (pointer[1] == 1) | |
405 (void) fprintf(NetTrace, " SEND"); | |
406 else | |
407 (void) fprintf(NetTrace, | |
408 " %d (unknown)", pointer[1]); | |
409 for (i = 2; i < length; i++) | |
410 (void) fprintf(NetTrace, " ?%d?", | |
411 pointer[i]); | |
412 break; | |
413 } | |
414 break; | |
415 | |
416 case TELOPT_LFLOW: | |
417 (void) fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); | |
418 if (length < 2) { | |
419 (void) fprintf(NetTrace, | |
420 " (empty suboption??\?)"); | |
421 break; | |
422 } | |
423 switch (pointer[1]) { | |
424 case LFLOW_OFF: | |
425 (void) fprintf(NetTrace, " OFF"); | |
426 break; | |
427 case LFLOW_ON: | |
428 (void) fprintf(NetTrace, " ON"); | |
429 break; | |
430 case LFLOW_RESTART_ANY: | |
431 (void) fprintf(NetTrace, " RESTART-ANY"); | |
432 break; | |
433 case LFLOW_RESTART_XON: | |
434 (void) fprintf(NetTrace, " RESTART-XON"); | |
435 break; | |
436 default: | |
437 (void) fprintf(NetTrace, " %d (unknown)", | |
438 pointer[1]); | |
439 } | |
440 for (i = 2; i < length; i++) | |
441 (void) fprintf(NetTrace, " ?%d?", | |
442 pointer[i]); | |
443 break; | |
444 | |
445 case TELOPT_NAWS: | |
446 (void) fprintf(NetTrace, "NAWS"); | |
447 if (length < 2) { | |
448 (void) fprintf(NetTrace, | |
449 " (empty suboption??\?)"); | |
450 break; | |
451 } | |
452 if (length == 2) { | |
453 (void) fprintf(NetTrace, " ?%d?", pointer[1]); | |
454 break; | |
455 } | |
456 (void) fprintf(NetTrace, " %d %d (%d)", | |
457 pointer[1], pointer[2], | |
458 (int)((((unsigned int)pointer[1])<<8)| | |
459 ((unsigned int)pointer[2]))); | |
460 if (length == 4) { | |
461 (void) fprintf(NetTrace, " ?%d?", pointer[3]); | |
462 break; | |
463 } | |
464 (void) fprintf(NetTrace, " %d %d (%d)", | |
465 pointer[3], pointer[4], | |
466 (int)((((unsigned int)pointer[3])<<8)| | |
467 ((unsigned int)pointer[4]))); | |
468 for (i = 5; i < length; i++) | |
469 (void) fprintf(NetTrace, " ?%d?", pointer[i]); | |
470 break; | |
471 | |
472 case TELOPT_AUTHENTICATION: | |
473 (void) fprintf(NetTrace, "AUTHENTICATION"); | |
474 if (length < 2) { | |
475 (void) fprintf(NetTrace, | |
476 " (empty suboption??\?)"); | |
477 break; | |
478 } | |
479 switch (pointer[1]) { | |
480 case TELQUAL_REPLY: | |
481 case TELQUAL_IS: | |
482 (void) fprintf(NetTrace, " %s ", | |
483 (pointer[1] == TELQUAL_IS) ? | |
484 "IS" : "REPLY"); | |
485 if (AUTHTYPE_NAME_OK(pointer[2])) | |
486 (void) fprintf(NetTrace, "%s ", | |
487 AUTHTYPE_NAME(pointer[2])); | |
488 else | |
489 (void) fprintf(NetTrace, "%d ", | |
490 pointer[2]); | |
491 if (length < 3) { | |
492 (void) fprintf(NetTrace, | |
493 "(partial suboption??\?)"); | |
494 break; | |
495 } | |
496 (void) fprintf(NetTrace, "%s|%s", | |
497 ((pointer[3] & AUTH_WHO_MASK) == | |
498 AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", | |
499 ((pointer[3] & AUTH_HOW_MASK) == | |
500 AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); | |
501 | |
502 auth_printsub(&pointer[1], length - 1, | |
503 (uchar_t *)buf, sizeof (buf)); | |
504 (void) fprintf(NetTrace, "%s", buf); | |
505 break; | |
506 | |
507 case TELQUAL_SEND: | |
508 i = 2; | |
509 (void) fprintf(NetTrace, " SEND "); | |
510 while (i < length) { | |
511 if (AUTHTYPE_NAME_OK(pointer[i])) | |
512 (void) fprintf(NetTrace, "%s ", | |
513 AUTHTYPE_NAME(pointer[i])); | |
514 else | |
515 (void) fprintf(NetTrace, "%d ", | |
516 pointer[i]); | |
517 if (++i >= length) { | |
518 (void) fprintf(NetTrace, | |
519 "(partial " | |
520 "suboption??\?)"); | |
521 break; | |
522 } | |
523 (void) fprintf(NetTrace, "%s|%s ", | |
524 ((pointer[i] & AUTH_WHO_MASK) == | |
525 AUTH_WHO_CLIENT) ? | |
526 "CLIENT" : "SERVER", | |
527 ((pointer[i] & AUTH_HOW_MASK) == | |
528 AUTH_HOW_MUTUAL) ? | |
529 "MUTUAL" : "ONE-WAY"); | |
530 ++i; | |
531 } | |
532 break; | |
533 | |
534 case TELQUAL_NAME: | |
535 i = 2; | |
536 (void) fprintf(NetTrace, " NAME \""); | |
537 while (i < length) | |
538 (void) putc(pointer[i++], NetTrace); | |
539 (void) putc('"', NetTrace); | |
540 break; | |
541 | |
542 default: | |
543 for (i = 2; i < length; i++) | |
544 (void) fprintf(NetTrace, " ?%d?", pointer[i]); | |
545 break; | |
546 } | |
547 break; | |
548 | |
549 case TELOPT_ENCRYPT: | |
550 (void) fprintf(NetTrace, "ENCRYPT"); | |
551 if (length < 2) { | |
552 (void) fprintf(NetTrace, | |
553 " (empty suboption??\?)"); | |
554 break; | |
555 } | |
556 switch (pointer[1]) { | |
557 case ENCRYPT_START: | |
558 (void) fprintf(NetTrace, " START"); | |
559 break; | |
560 | |
561 case ENCRYPT_END: | |
562 (void) fprintf(NetTrace, " END"); | |
563 break; | |
564 | |
565 case ENCRYPT_REQSTART: | |
566 (void) fprintf(NetTrace, " REQUEST-START"); | |
567 break; | |
568 | |
569 case ENCRYPT_REQEND: | |
570 (void) fprintf(NetTrace, " REQUEST-END"); | |
571 break; | |
572 | |
573 case ENCRYPT_IS: | |
574 case ENCRYPT_REPLY: | |
575 (void) fprintf(NetTrace, " %s ", | |
576 (pointer[1] == ENCRYPT_IS) ? | |
577 "IS" : "REPLY"); | |
578 if (length < 3) { | |
579 (void) fprintf(NetTrace, " (partial " | |
580 "suboption??\?)"); | |
581 break; | |
582 } | |
583 if (ENCTYPE_NAME_OK(pointer[2])) | |
584 (void) fprintf(NetTrace, "%s ", | |
585 ENCTYPE_NAME(pointer[2])); | |
586 else | |
587 (void) fprintf(NetTrace, | |
588 " %d (unknown)", pointer[2]); | |
589 | |
590 encrypt_printsub(&pointer[1], length - 1, | |
591 (uchar_t *)buf, sizeof (buf)); | |
592 (void) fprintf(NetTrace, "%s", buf); | |
593 break; | |
594 | |
595 case ENCRYPT_SUPPORT: | |
596 i = 2; | |
597 (void) fprintf(NetTrace, " SUPPORT "); | |
598 while (i < length) { | |
599 if (ENCTYPE_NAME_OK(pointer[i])) | |
600 (void) fprintf(NetTrace, "%s ", | |
601 ENCTYPE_NAME(pointer[i])); | |
602 else | |
603 (void) fprintf(NetTrace, "%d ", | |
604 pointer[i]); | |
605 i++; | |
606 } | |
607 break; | |
608 | |
609 case ENCRYPT_ENC_KEYID: | |
610 (void) fprintf(NetTrace, " ENC_KEYID "); | |
611 goto encommon; | |
612 | |
613 case ENCRYPT_DEC_KEYID: | |
614 (void) fprintf(NetTrace, " DEC_KEYID "); | |
615 goto encommon; | |
616 | |
617 default: | |
618 (void) fprintf(NetTrace, " %d (unknown)", | |
619 pointer[1]); | |
620 encommon: | |
621 for (i = 2; i < length; i++) | |
622 (void) fprintf(NetTrace, " %d", | |
623 pointer[i]); | |
624 break; | |
625 } | |
626 break; | |
627 | |
628 case TELOPT_LINEMODE: | |
629 (void) fprintf(NetTrace, "LINEMODE "); | |
630 if (length < 2) { | |
631 (void) fprintf(NetTrace, | |
632 " (empty suboption??\?)"); | |
633 break; | |
634 } | |
635 switch (pointer[1]) { | |
636 case WILL: | |
637 (void) fprintf(NetTrace, "WILL "); | |
638 goto common; | |
639 case WONT: | |
640 (void) fprintf(NetTrace, "WONT "); | |
641 goto common; | |
642 case DO: | |
643 (void) fprintf(NetTrace, "DO "); | |
644 goto common; | |
645 case DONT: | |
646 (void) fprintf(NetTrace, "DONT "); | |
647 common: | |
648 if (length < 3) { | |
649 (void) fprintf(NetTrace, | |
650 "(no option??\?)"); | |
651 break; | |
652 } | |
653 switch (pointer[2]) { | |
654 case LM_FORWARDMASK: | |
655 (void) fprintf(NetTrace, | |
656 "Forward Mask"); | |
657 for (i = 3; i < length; i++) | |
658 (void) fprintf(NetTrace, " %x", | |
659 pointer[i]); | |
660 break; | |
661 default: | |
662 (void) fprintf(NetTrace, "%d (unknown)", | |
663 pointer[2]); | |
664 for (i = 3; i < length; i++) | |
665 (void) fprintf(NetTrace, | |
666 " %d", pointer[i]); | |
667 break; | |
668 } | |
669 break; | |
670 | |
671 case LM_SLC: | |
672 (void) fprintf(NetTrace, "SLC"); | |
673 for (i = 2; i < length - 2; i += 3) { | |
674 if (SLC_NAME_OK(pointer[i+SLC_FUNC])) | |
675 (void) fprintf(NetTrace, " %s", | |
676 SLC_NAME(pointer[ | |
677 i+SLC_FUNC])); | |
678 else | |
679 (void) fprintf(NetTrace, " %d", | |
680 pointer[i+SLC_FUNC]); | |
681 switch (pointer[i+SLC_FLAGS] & | |
682 SLC_LEVELBITS) { | |
683 case SLC_NOSUPPORT: | |
684 (void) fprintf(NetTrace, | |
685 " NOSUPPORT"); | |
686 break; | |
687 case SLC_CANTCHANGE: | |
688 (void) fprintf(NetTrace, | |
689 " CANTCHANGE"); | |
690 break; | |
691 case SLC_VARIABLE: | |
692 (void) fprintf(NetTrace, | |
693 " VARIABLE"); | |
694 break; | |
695 case SLC_DEFAULT: | |
696 (void) fprintf(NetTrace, | |
697 " DEFAULT"); | |
698 break; | |
699 } | |
700 (void) fprintf(NetTrace, "%s%s%s", | |
701 pointer[i+SLC_FLAGS]&SLC_ACK ? | |
702 "|ACK" : "", | |
703 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? | |
704 "|FLUSHIN" : "", | |
705 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? | |
706 "|FLUSHOUT" : ""); | |
707 if (pointer[i+SLC_FLAGS] & | |
708 ~(SLC_ACK|SLC_FLUSHIN| | |
709 SLC_FLUSHOUT| SLC_LEVELBITS)) | |
710 (void) fprintf(NetTrace, "(0x%x)", | |
711 pointer[i+SLC_FLAGS]); | |
712 (void) fprintf(NetTrace, " %d;", | |
713 pointer[i+SLC_VALUE]); | |
714 if ((pointer[i+SLC_VALUE] == IAC) && | |
715 (pointer[i+SLC_VALUE+1] == IAC)) | |
716 i++; | |
717 } | |
718 for (; i < length; i++) | |
719 (void) fprintf(NetTrace, " ?%d?", | |
720 pointer[i]); | |
721 break; | |
722 | |
723 case LM_MODE: | |
724 (void) fprintf(NetTrace, "MODE "); | |
725 if (length < 3) { | |
726 (void) fprintf(NetTrace, | |
727 "(no mode??\?)"); | |
728 break; | |
729 } | |
730 { | |
731 char tbuf[64]; | |
732 (void) sprintf(tbuf, "%s%s%s%s%s", | |
733 pointer[2]&MODE_EDIT ? "|EDIT" : "", | |
734 pointer[2]&MODE_TRAPSIG ? | |
735 "|TRAPSIG" : "", | |
736 pointer[2]&MODE_SOFT_TAB ? | |
737 "|SOFT_TAB" : "", | |
738 pointer[2]&MODE_LIT_ECHO ? | |
739 "|LIT_ECHO" : "", | |
740 pointer[2]&MODE_ACK ? "|ACK" : ""); | |
741 (void) fprintf(NetTrace, "%s", tbuf[1] ? | |
742 &tbuf[1] : "0"); | |
743 } | |
744 if (pointer[2]&~(MODE_MASK)) | |
745 (void) fprintf(NetTrace, " (0x%x)", | |
746 pointer[2]); | |
747 for (i = 3; i < length; i++) | |
748 (void) fprintf(NetTrace, " ?0x%x?", | |
749 pointer[i]); | |
750 break; | |
751 default: | |
752 (void) fprintf(NetTrace, "%d (unknown)", | |
753 pointer[1]); | |
754 for (i = 2; i < length; i++) | |
755 (void) fprintf(NetTrace, " %d", | |
756 pointer[i]); | |
757 } | |
758 break; | |
759 | |
760 case TELOPT_STATUS: { | |
761 register char *cp; | |
762 register int j, k; | |
763 | |
764 (void) fprintf(NetTrace, "STATUS"); | |
765 | |
766 switch (pointer[1]) { | |
767 default: | |
768 if (pointer[1] == TELQUAL_SEND) | |
769 (void) fprintf(NetTrace, | |
770 " SEND"); | |
771 else | |
772 (void) fprintf(NetTrace, | |
773 " %d (unknown)", | |
774 pointer[1]); | |
775 for (i = 2; i < length; i++) | |
776 (void) fprintf(NetTrace, " ?%d?", | |
777 pointer[i]); | |
778 break; | |
779 case TELQUAL_IS: | |
780 if (--want_status_response < 0) | |
781 want_status_response = 0; | |
782 if (NetTrace == stdout) | |
783 (void) fprintf(NetTrace, | |
784 " IS\r\n"); | |
785 else | |
786 (void) fprintf(NetTrace, | |
787 " IS\n"); | |
788 | |
789 for (i = 2; i < length; i++) { | |
790 switch (pointer[i]) { | |
791 case DO: | |
792 cp = "DO"; | |
793 goto common2; | |
794 case DONT: | |
795 cp = "DONT"; | |
796 goto common2; | |
797 case WILL: | |
798 cp = "WILL"; | |
799 goto common2; | |
800 case WONT: | |
801 cp = "WONT"; | |
802 goto common2; | |
803 common2: | |
804 i++; | |
805 if (TELOPT_OK( | |
806 (int)pointer[i])) | |
807 (void) fprintf( | |
808 NetTrace, | |
809 " %s %s", | |
810 cp, | |
811 TELOPT( | |
812 pointer[ | |
813 i])); | |
814 else | |
815 (void) fprintf( | |
816 NetTrace, | |
817 " %s %d", | |
818 cp, | |
819 pointer[i]); | |
820 | |
821 if (NetTrace == stdout) | |
822 (void) fprintf( | |
823 NetTrace, | |
824 "\r\n"); | |
825 else | |
826 (void) fprintf( | |
827 NetTrace, | |
828 "\n"); | |
829 break; | |
830 | |
831 case SB: | |
832 (void) fprintf(NetTrace, | |
833 " SB "); | |
834 i++; | |
835 j = k = i; | |
836 while (j < length) { | |
837 if (pointer[j] == SE) { | |
838 if (j+1 == length) | |
839 break; | |
840 if (pointer[j+1] == SE) | |
841 j++; | |
842 else | |
843 break; | |
844 } | |
845 pointer[k++] = pointer[j++]; | |
846 } | |
847 printsub(0, | |
848 &pointer[i], k - i); | |
849 if (i < length) { | |
850 (void) fprintf(NetTrace, " SE"); | |
851 i = j; | |
852 } else | |
853 i = j - 1; | |
854 | |
855 if (NetTrace == stdout) | |
856 (void) fprintf(NetTrace, "\r\n"); | |
857 else | |
858 (void) fprintf(NetTrace, "\n"); | |
859 | |
860 break; | |
861 | |
862 default: | |
863 (void) fprintf(NetTrace, | |
864 " %d", pointer[i]); | |
865 break; | |
866 } | |
867 } | |
868 break; | |
869 } | |
870 break; | |
871 } | |
872 | |
873 case TELOPT_XDISPLOC: | |
874 (void) fprintf(NetTrace, "X-DISPLAY-LOCATION "); | |
875 switch (pointer[1]) { | |
876 case TELQUAL_IS: | |
877 (void) fprintf(NetTrace, "IS \"%.*s\"", | |
878 length-2, (char *)pointer+2); | |
879 break; | |
880 case TELQUAL_SEND: | |
881 (void) fprintf(NetTrace, "SEND"); | |
882 break; | |
883 default: | |
884 (void) fprintf(NetTrace, | |
885 "- unknown qualifier %d (0x%x).", | |
886 pointer[1], pointer[1]); | |
887 } | |
888 break; | |
889 | |
890 case TELOPT_NEW_ENVIRON: | |
891 (void) fprintf(NetTrace, "NEW-ENVIRON "); | |
892 #ifdef OLD_ENVIRON | |
893 goto env_common1; | |
894 case TELOPT_OLD_ENVIRON: | |
895 (void) fprintf(NetTrace, "OLD-ENVIRON "); | |
896 env_common1: | |
897 #endif | |
898 switch (pointer[1]) { | |
899 case TELQUAL_IS: | |
900 (void) fprintf(NetTrace, "IS "); | |
901 goto env_common; | |
902 case TELQUAL_SEND: | |
903 (void) fprintf(NetTrace, "SEND "); | |
904 goto env_common; | |
905 case TELQUAL_INFO: | |
906 (void) fprintf(NetTrace, "INFO "); | |
907 env_common: | |
908 { | |
909 register int noquote = 2; | |
910 #if defined(ENV_HACK) && defined(OLD_ENVIRON) | |
911 extern int old_env_var, old_env_value; | |
912 #endif | |
913 for (i = 2; i < length; i++) { | |
914 switch (pointer[i]) { | |
915 case NEW_ENV_VALUE: | |
916 #ifdef OLD_ENVIRON | |
917 /* case NEW_ENV_OVAR: */ | |
918 if (pointer[0] == TELOPT_OLD_ENVIRON) { | |
919 #ifdef ENV_HACK | |
920 if (old_env_var == OLD_ENV_VALUE) | |
921 (void) fprintf(NetTrace, | |
922 "\" (VALUE) " + noquote); | |
923 else | |
924 #endif | |
925 (void) fprintf(NetTrace, | |
926 "\" VAR " + noquote); | |
927 } else | |
928 #endif /* OLD_ENVIRON */ | |
929 (void) fprintf(NetTrace, "\" VALUE " + noquote); | |
930 noquote = 2; | |
931 break; | |
932 | |
933 case NEW_ENV_VAR: | |
934 #ifdef OLD_ENVIRON | |
935 /* case OLD_ENV_VALUE: */ | |
936 if (pointer[0] == TELOPT_OLD_ENVIRON) { | |
937 #ifdef ENV_HACK | |
938 if (old_env_value == OLD_ENV_VAR) | |
939 (void) fprintf(NetTrace, | |
940 "\" (VAR) " + noquote); | |
941 else | |
942 #endif | |
943 (void) fprintf(NetTrace, | |
944 "\" VALUE " + noquote); | |
945 } else | |
946 #endif /* OLD_ENVIRON */ | |
947 (void) fprintf(NetTrace, "\" VAR " + noquote); | |
948 noquote = 2; | |
949 break; | |
950 | |
951 case ENV_ESC: | |
952 (void) fprintf(NetTrace, "\" ESC " + noquote); | |
953 noquote = 2; | |
954 break; | |
955 | |
956 case ENV_USERVAR: | |
957 (void) fprintf(NetTrace, "\" USERVAR " + noquote); | |
958 noquote = 2; | |
959 break; | |
960 | |
961 default: | |
962 def_case: | |
963 if (isprint(pointer[i]) && pointer[i] != '"') { | |
964 if (noquote) { | |
965 (void) putc('"', NetTrace); | |
966 noquote = 0; | |
967 } | |
968 (void) putc(pointer[i], NetTrace); | |
969 } else { | |
970 (void) fprintf(NetTrace, "\" %03o " + noquote, | |
971 pointer[i]); | |
972 noquote = 2; | |
973 } | |
974 break; | |
975 } | |
976 } | |
977 if (!noquote) | |
978 (void) putc('"', NetTrace); | |
979 break; | |
980 } | |
981 } | |
982 break; | |
983 | |
984 default: | |
985 if (TELOPT_OK(pointer[0])) | |
986 (void) fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); | |
987 else | |
988 (void) fprintf(NetTrace, "%d (unknown)", pointer[0]); | |
989 for (i = 1; i < length; i++) | |
990 (void) fprintf(NetTrace, " %d", pointer[i]); | |
991 break; | |
992 } | |
993 if (direction) { | |
994 if (NetTrace == stdout) | |
995 (void) fprintf(NetTrace, "\r\n"); | |
996 else | |
997 (void) fprintf(NetTrace, "\n"); | |
998 } | |
999 if (NetTrace == stdout) | |
1000 (void) fflush(NetTrace); | |
1001 } | |
1002 } | |
1003 | |
1004 /* | |
1005 * EmptyTerminal - called to make sure that the terminal buffer is empty. | |
1006 * Note that we consider the buffer to run all the | |
1007 * way to the kernel (thus the select). | |
1008 */ | |
1009 | |
1010 static void | |
1011 EmptyTerminal() | |
1012 { | |
1013 fd_set o; | |
1014 | |
1015 FD_ZERO(&o); | |
1016 | |
1017 if (TTYBYTES() == 0) { | |
1018 FD_SET(tout, &o); | |
1019 /* wait for TTLOWAT */ | |
1020 (void) select(tout+1, NULL, &o, NULL, NULL); | |
1021 } else { | |
1022 while (TTYBYTES()) { | |
1023 if (ttyflush(0) == -2) { | |
1024 /* This will not return. */ | |
1025 fatal_tty_error("write"); | |
1026 } | |
1027 FD_SET(tout, &o); | |
1028 /* wait for TTLOWAT */ | |
1029 (void) select(tout+1, NULL, &o, NULL, NULL); | |
1030 } | |
1031 } | |
1032 } | |
1033 | |
1034 static void | |
1035 SetForExit() | |
1036 { | |
1037 setconnmode(0); | |
1038 do { | |
1039 (void) telrcv(); /* Process any incoming data */ | |
1040 EmptyTerminal(); | |
1041 } while (ring_full_count(&netiring)); /* While there is any */ | |
1042 setcommandmode(); | |
1043 (void) fflush(stdout); | |
1044 (void) fflush(stderr); | |
1045 setconnmode(0); | |
1046 EmptyTerminal(); /* Flush the path to the tty */ | |
1047 setcommandmode(); | |
1048 } | |
1049 | |
1050 void | |
1051 Exit(returnCode) | |
1052 int returnCode; | |
1053 { | |
1054 SetForExit(); | |
1055 exit(returnCode); | |
1056 } | |
1057 | |
1058 void | |
1059 ExitString(string, returnCode) | |
1060 char *string; | |
1061 int returnCode; | |
1062 { | |
1063 SetForExit(); | |
1064 (void) fwrite(string, 1, strlen(string), stderr); | |
1065 exit(returnCode); | |
1066 } | |
1067 | |
1068 #define BUFFER_CHUNK_SIZE 64 | |
1069 | |
1070 /* Round up to a multiple of BUFFER_CHUNK_SIZE */ | |
1071 #define ROUND_CHUNK_SIZE(s) ((((s) + BUFFER_CHUNK_SIZE - 1) / \ | |
1072 BUFFER_CHUNK_SIZE) * BUFFER_CHUNK_SIZE) | |
1073 | |
1074 /* | |
1075 * Optionally allocate a buffer, and optionally read a string from a stream | |
1076 * into the buffer, starting at the given offset. If the buffer isn't | |
1077 * large enough for the given offset, or if buffer space is exhausted | |
1078 * when reading the string, the size of the buffer is increased. | |
1079 * | |
1080 * A buffer can be supplied when the function is called, passing the | |
1081 * buffer address via the first argument. The buffer size can be | |
1082 * passed as well, in the second argument. If the second argument is | |
1083 * NULL, the function makes no assumptions about the buffer size. | |
1084 * The address of the buffer is returned via the first argument, and the | |
1085 * buffer size via the second argument if this is not NULL. | |
1086 * These returned values may differ from the supplied values if the buffer | |
1087 * was reallocated. | |
1088 * | |
1089 * If no buffer is to be supplied, specify a buffer address of NULL, via | |
1090 * the first argument. | |
1091 * | |
1092 * If the pointer to the buffer address is NULL, the function just returns | |
1093 * NULL, and performs no other processing. | |
1094 * | |
1095 * If a NULL stream is passed, the function will just make sure the | |
1096 * supplied buffer is large enough to hold the supplied offset, | |
1097 * reallocating it if is too small or too large. | |
1098 * | |
1099 * The returned buffer will be a multiple of BUFFER_CHUNK_SIZE in size. | |
1100 * | |
1101 * The function stops reading from the stream when a newline is read, | |
1102 * end of file is reached, or an error occurs. The newline is not | |
1103 * returned in the buffer. The returned string will be NULL terminated. | |
1104 * | |
1105 * The function returns the address of the buffer if any characters | |
1106 * are read and no error occurred, otherwise it returns NULL. | |
1107 * | |
1108 * If the function returns NULL, a buffer may have been allocated. The | |
1109 * buffer address will be returned via the first argument, together with | |
1110 * the buffer size if the second argument is not NULL. | |
1111 * | |
1112 */ | |
1113 static char * | |
1114 GetStringAtOffset(bufp, cbufsiz, off, st) | |
1115 char **bufp; | |
1116 unsigned int *cbufsiz; | |
1117 unsigned int off; | |
1118 FILE *st; | |
1119 { | |
1120 unsigned int bufsiz; | |
1121 char *buf; | |
1122 char *nbuf; | |
1123 unsigned int idx = off; | |
1124 | |
1125 if (bufp == NULL) | |
1126 return (NULL); | |
1127 | |
1128 buf = *bufp; | |
1129 | |
1130 bufsiz = ROUND_CHUNK_SIZE(off + 1); | |
1131 | |
1132 if (buf == NULL || cbufsiz == NULL || *cbufsiz != bufsiz) { | |
1133 if ((nbuf = realloc(buf, bufsiz)) == NULL) | |
1134 return (NULL); | |
1135 | |
1136 buf = nbuf; | |
1137 *bufp = buf; | |
1138 if (cbufsiz != NULL) | |
1139 *cbufsiz = bufsiz; | |
1140 } | |
1141 | |
1142 | |
1143 if (st == NULL) | |
1144 return (buf); | |
1145 | |
1146 clearerr(st); | |
1147 for (;;) { | |
1148 int c = getc(st); | |
1149 | |
1150 /* Expand the buffer as needed. */ | |
1151 if (idx == bufsiz) { | |
1152 bufsiz += BUFFER_CHUNK_SIZE; | |
1153 if ((nbuf = realloc(buf, bufsiz)) == NULL) { | |
1154 /* Discard everything we read. */ | |
1155 buf[off] = 0; | |
1156 buf = NULL; | |
1157 break; | |
1158 } | |
1159 buf = nbuf; | |
1160 *bufp = buf; | |
1161 if (cbufsiz != NULL) | |
1162 *cbufsiz = bufsiz; | |
1163 } | |
1164 | |
1165 if (c == EOF || c == '\n') { | |
1166 buf[idx] = 0; | |
1167 if (ferror(st) != 0) { | |
1168 /* Retry if interrupted by a signal. */ | |
1169 if (errno == EINTR) { | |
1170 clearerr(st); | |
1171 continue; | |
1172 } | |
1173 buf = NULL; | |
1174 } else if (feof(st) != 0) { | |
1175 /* No characters transferred? */ | |
1176 if (off == idx) | |
1177 buf = NULL; | |
1178 } | |
1179 break; | |
1180 } | |
1181 buf[idx++] = c; | |
1182 } | |
1183 return (buf); | |
1184 } | |
1185 | |
1186 /* | |
1187 * Read a string from the supplied stream. Stop reading when a newline | |
1188 * is read, end of file reached, or an error occurs. | |
1189 * | |
1190 * A buffer can be supplied by specifying the buffer address via the | |
1191 * first argument. The buffer size can be passed via the second argument. | |
1192 * If the second argument is NULL, the function makes no assumptions | |
1193 * about the buffer size. The buffer will be reallocated if it is too | |
1194 * small or too large for the returned string. | |
1195 * | |
1196 * If no buffer is to be supplied, specify a buffer address of NULL, | |
1197 * via the first argument. | |
1198 * | |
1199 * If the first argument is NULL, the function just returns NULL, and | |
1200 * performs no other processing. | |
1201 * | |
1202 * The function returns the address of the buffer if any characters are | |
1203 * read and no error occurred. | |
1204 * | |
1205 * If the function returns NULL, a buffer may have been allocated. The | |
1206 * buffer address and buffer size will be returned via the first argument, | |
1207 * and the buffer size via the second argument, if this isn't NULL. | |
1208 */ | |
1209 char * | |
1210 GetString(bufp, bufsiz, st) | |
1211 char **bufp; | |
1212 unsigned int *bufsiz; | |
1213 FILE *st; | |
1214 { | |
1215 return (GetStringAtOffset(bufp, bufsiz, 0, st)); | |
1216 } | |
1217 | |
1218 /* | |
1219 * Allocate a buffer to hold a string of given length. | |
1220 * | |
1221 * An existing buffer can be reallocated by passing its address and via | |
1222 * the first argument. The buffer size can be passed via the second | |
1223 * argument. If the second argument is NULL, the function makes no | |
1224 * assumptions about the buffer size. | |
1225 * | |
1226 * If no existing buffer is to be supplied, pass a NULL buffer address via | |
1227 * the first argument. | |
1228 * | |
1229 * If the first argument is NULL, the function just returns NULL, | |
1230 * and performs no other processing. | |
1231 */ | |
1232 char * | |
1233 AllocStringBuffer(bufp, bufsiz, size) | |
1234 char **bufp; | |
1235 unsigned int *bufsiz; | |
1236 unsigned int size; | |
1237 { | |
1238 return (GetStringAtOffset(bufp, bufsiz, size, (FILE *)NULL)); | |
1239 } | |
1240 | |
1241 /* | |
1242 * This function is similar to GetString(), except that the string read | |
1243 * from the stream is appended to the supplied string. | |
1244 */ | |
1245 char * | |
1246 GetAndAppendString(bufp, bufsiz, str, st) | |
1247 char **bufp; | |
1248 unsigned int *bufsiz; | |
1249 char *str; | |
1250 FILE *st; | |
1251 { | |
1252 unsigned int off = strlen(str); | |
1253 | |
1254 if (GetStringAtOffset(bufp, bufsiz, off, st) == NULL) | |
1255 return (NULL); | |
1256 | |
1257 return (memcpy(*bufp, str, off)); | |
1258 } |