2 * Copyright 1994-2002 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 #pragma ident "%Z%%M% %I% %E% SMI"
9 * usr/src/cmd/cmd-inet/usr.bin/telnet/utilities.c
13 * Copyright (c) 1988, 1993
14 * The Regents of the University of California. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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
46 static char sccsid
[] = "@(#)utilities.c 8.1 (Berkeley) 6/6/93";
51 static char *telcmds
[] = {0};
52 static char *slc_names
[] = {0};
53 static char *encrypt_names
[] = {0};
54 static char *enctype_names
[] = {0};
59 #include <arpa/telnet.h>
60 #include <sys/types.h>
62 #include <sys/param.h>
63 #include <sys/socket.h>
76 FILE *NetTrace
= 0; /* Not in bss, since needs to stay */
82 * Upcase (in place) the argument.
87 register char *argument
;
91 while ((c
= *argument
) != 0) {
93 *argument
= toupper(c
);
102 * Compensate for differences in 4.2 and 4.3 systems.
106 SetSockOpt(fd
, level
, option
, yesno
)
107 int fd
, level
, option
, yesno
;
109 return (setsockopt(fd
, level
, option
, &yesno
, sizeof (yesno
)));
113 * The following are routines used to print out debugging information.
116 unsigned char NetTraceFile
[MAXPATHLEN
] = "(standard output)";
122 if (NetTrace
&& NetTrace
!= stdout
)
123 (void) fclose(NetTrace
);
124 if (file
&& (strcmp(file
, "-") != 0)) {
125 NetTrace
= fopen(file
, "w");
127 (void) strcpy((char *)NetTraceFile
, file
);
130 (void) fprintf(stderr
, "Cannot open %s.\n", file
);
133 (void) strcpy((char *)NetTraceFile
, "(standard output)");
137 Dump(direction
, buffer
, length
)
139 unsigned char *buffer
;
142 #define BYTES_PER_LINE 32
143 #define min(x, y) ((x < y) ? x:y)
144 unsigned char *pThis
;
151 (void) fprintf(NetTrace
, "%c 0x%x\t", direction
, offset
);
154 buffer
= buffer
+ min(length
, BYTES_PER_LINE
/2);
155 while (pThis
< buffer
) {
156 (void) fprintf(NetTrace
, "%c%.2x",
157 (((*pThis
)&0xff) == 0xff) ? '*' : ' ',
161 length
-= BYTES_PER_LINE
/2;
162 offset
+= BYTES_PER_LINE
/2;
164 buffer
= buffer
+ min(length
, BYTES_PER_LINE
);
165 while (pThis
< buffer
) {
166 (void) fprintf(NetTrace
, "%.2x", (*pThis
)&0xff);
169 length
-= BYTES_PER_LINE
;
170 offset
+= BYTES_PER_LINE
;
172 if (NetTrace
== stdout
) {
173 (void) fprintf(NetTrace
, "\r\n");
175 (void) fprintf(NetTrace
, "\n");
178 (void) fflush(NetTrace
);
181 /* find next unique line */
183 (void) fflush(NetTrace
);
188 printoption(direction
, cmd
, option
)
195 if (TELCMD_OK(option
))
196 (void) fprintf(NetTrace
, "%s IAC %s", direction
,
199 (void) fprintf(NetTrace
, "%s IAC %d", direction
,
203 fmt
= (cmd
== WILL
) ? "WILL" : (cmd
== WONT
) ? "WONT" :
204 (cmd
== DO
) ? "DO" : (cmd
== DONT
) ? "DONT" : 0;
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");
212 (void) fprintf(NetTrace
, "%d", option
);
214 (void) fprintf(NetTrace
, "%s %d %d", direction
, cmd
,
217 if (NetTrace
== stdout
) {
218 (void) fprintf(NetTrace
, "\r\n");
219 (void) fflush(NetTrace
);
221 (void) fprintf(NetTrace
, "\n");
229 extern char will_wont_resp
[], do_dont_resp
[];
231 for (i
= 0; i
< SUBBUFSIZE
; i
++) {
232 if (do_dont_resp
[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
]);
240 (void) printf("resp DO_DONT %d: %d\n", i
,
242 if (my_want_state_is_do(i
)) {
244 (void) printf("want DO %s\n",
246 else if (TELCMD_OK(i
))
247 (void) printf("want DO %s\n",
250 (void) printf("want DO %d\n", i
);
253 (void) printf("want DONT %s\n",
255 else if (TELCMD_OK(i
))
256 (void) printf("want DONT %s\n",
259 (void) printf("want DONT %d\n", i
);
262 if (my_state_is_do(i
)) {
264 (void) printf(" DO %s\n",
266 else if (TELCMD_OK(i
))
267 (void) printf(" DO %s\n",
270 (void) printf(" DO %d\n", i
);
273 if (will_wont_resp
[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
]);
281 (void) printf("resp WILL_WONT %d: %d\n",
282 i
, will_wont_resp
[i
]);
283 if (my_want_state_is_will(i
)) {
285 (void) printf("want WILL %s\n",
287 else if (TELCMD_OK(i
))
288 (void) printf("want WILL %s\n",
291 (void) printf("want WILL %d\n", i
);
294 (void) printf("want WONT %s\n",
296 else if (TELCMD_OK(i
))
297 (void) printf("want WONT %s\n",
300 (void) printf("want WONT %d\n", i
);
303 if (my_state_is_will(i
)) {
305 (void) printf(" WILL %s\n",
307 else if (TELCMD_OK(i
))
308 (void) printf(" WILL %s\n",
311 (void) printf(" WILL %d\n", i
);
319 printsub(direction
, pointer
, length
)
320 char direction
; /* '<' or '>' */
321 unsigned char *pointer
; /* where suboption data sits */
322 int length
; /* length of suboption data */
326 extern int want_status_response
;
328 if (showoptions
|| direction
== 0 ||
329 (want_status_response
&& (pointer
[0] == TELOPT_STATUS
))) {
331 (void) fprintf(NetTrace
, "%s IAC SB ",
332 (direction
== '<')? "RCVD":"SENT");
336 i
= pointer
[length
-2];
337 j
= pointer
[length
-1];
339 if (i
!= IAC
|| j
!= SE
) {
340 (void) fprintf(NetTrace
,
343 (void) fprintf(NetTrace
, "%s ",
345 else if (TELCMD_OK(i
))
346 (void) fprintf(NetTrace
, "%s ",
349 (void) fprintf(NetTrace
, "%d ",
352 (void) fprintf(NetTrace
, "%s",
354 else if (TELCMD_OK(j
))
355 (void) fprintf(NetTrace
, "%s",
358 (void) fprintf(NetTrace
, "%d",
360 (void) fprintf(NetTrace
,
367 (void) fprintf(NetTrace
, "(Empty suboption??\?)");
368 if (NetTrace
== stdout
)
369 (void) fflush(NetTrace
);
372 switch (pointer
[0]) {
374 (void) fprintf(NetTrace
, "TERMINAL-TYPE ");
375 switch (pointer
[1]) {
377 (void) fprintf(NetTrace
, "IS \"%.*s\"",
382 (void) fprintf(NetTrace
, "SEND");
385 (void) fprintf(NetTrace
,
386 "- unknown qualifier %d (0x%x).",
387 pointer
[1], pointer
[1]);
391 (void) fprintf(NetTrace
, "TERMINAL-SPEED");
393 (void) fprintf(NetTrace
,
394 " (empty suboption??\?)");
397 switch (pointer
[1]) {
399 (void) fprintf(NetTrace
, " IS ");
400 (void) fprintf(NetTrace
, "%.*s", length
-2,
405 (void) fprintf(NetTrace
, " SEND");
407 (void) fprintf(NetTrace
,
408 " %d (unknown)", pointer
[1]);
409 for (i
= 2; i
< length
; i
++)
410 (void) fprintf(NetTrace
, " ?%d?",
417 (void) fprintf(NetTrace
, "TOGGLE-FLOW-CONTROL");
419 (void) fprintf(NetTrace
,
420 " (empty suboption??\?)");
423 switch (pointer
[1]) {
425 (void) fprintf(NetTrace
, " OFF");
428 (void) fprintf(NetTrace
, " ON");
430 case LFLOW_RESTART_ANY
:
431 (void) fprintf(NetTrace
, " RESTART-ANY");
433 case LFLOW_RESTART_XON
:
434 (void) fprintf(NetTrace
, " RESTART-XON");
437 (void) fprintf(NetTrace
, " %d (unknown)",
440 for (i
= 2; i
< length
; i
++)
441 (void) fprintf(NetTrace
, " ?%d?",
446 (void) fprintf(NetTrace
, "NAWS");
448 (void) fprintf(NetTrace
,
449 " (empty suboption??\?)");
453 (void) fprintf(NetTrace
, " ?%d?", pointer
[1]);
456 (void) fprintf(NetTrace
, " %d %d (%d)",
457 pointer
[1], pointer
[2],
458 (int)((((unsigned int)pointer
[1])<<8)|
459 ((unsigned int)pointer
[2])));
461 (void) fprintf(NetTrace
, " ?%d?", pointer
[3]);
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
]);
472 case TELOPT_AUTHENTICATION
:
473 (void) fprintf(NetTrace
, "AUTHENTICATION");
475 (void) fprintf(NetTrace
,
476 " (empty suboption??\?)");
479 switch (pointer
[1]) {
482 (void) fprintf(NetTrace
, " %s ",
483 (pointer
[1] == TELQUAL_IS
) ?
485 if (AUTHTYPE_NAME_OK(pointer
[2]))
486 (void) fprintf(NetTrace
, "%s ",
487 AUTHTYPE_NAME(pointer
[2]));
489 (void) fprintf(NetTrace
, "%d ",
492 (void) fprintf(NetTrace
,
493 "(partial suboption??\?)");
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");
502 auth_printsub(&pointer
[1], length
- 1,
503 (uchar_t
*)buf
, sizeof (buf
));
504 (void) fprintf(NetTrace
, "%s", buf
);
509 (void) fprintf(NetTrace
, " SEND ");
511 if (AUTHTYPE_NAME_OK(pointer
[i
]))
512 (void) fprintf(NetTrace
, "%s ",
513 AUTHTYPE_NAME(pointer
[i
]));
515 (void) fprintf(NetTrace
, "%d ",
518 (void) fprintf(NetTrace
,
523 (void) fprintf(NetTrace
, "%s|%s ",
524 ((pointer
[i
] & AUTH_WHO_MASK
) ==
527 ((pointer
[i
] & AUTH_HOW_MASK
) ==
529 "MUTUAL" : "ONE-WAY");
536 (void) fprintf(NetTrace
, " NAME \"");
538 (void) putc(pointer
[i
++], NetTrace
);
539 (void) putc('"', NetTrace
);
543 for (i
= 2; i
< length
; i
++)
544 (void) fprintf(NetTrace
, " ?%d?", pointer
[i
]);
550 (void) fprintf(NetTrace
, "ENCRYPT");
552 (void) fprintf(NetTrace
,
553 " (empty suboption??\?)");
556 switch (pointer
[1]) {
558 (void) fprintf(NetTrace
, " START");
562 (void) fprintf(NetTrace
, " END");
565 case ENCRYPT_REQSTART
:
566 (void) fprintf(NetTrace
, " REQUEST-START");
570 (void) fprintf(NetTrace
, " REQUEST-END");
575 (void) fprintf(NetTrace
, " %s ",
576 (pointer
[1] == ENCRYPT_IS
) ?
579 (void) fprintf(NetTrace
, " (partial "
583 if (ENCTYPE_NAME_OK(pointer
[2]))
584 (void) fprintf(NetTrace
, "%s ",
585 ENCTYPE_NAME(pointer
[2]));
587 (void) fprintf(NetTrace
,
588 " %d (unknown)", pointer
[2]);
590 encrypt_printsub(&pointer
[1], length
- 1,
591 (uchar_t
*)buf
, sizeof (buf
));
592 (void) fprintf(NetTrace
, "%s", buf
);
595 case ENCRYPT_SUPPORT
:
597 (void) fprintf(NetTrace
, " SUPPORT ");
599 if (ENCTYPE_NAME_OK(pointer
[i
]))
600 (void) fprintf(NetTrace
, "%s ",
601 ENCTYPE_NAME(pointer
[i
]));
603 (void) fprintf(NetTrace
, "%d ",
609 case ENCRYPT_ENC_KEYID
:
610 (void) fprintf(NetTrace
, " ENC_KEYID ");
613 case ENCRYPT_DEC_KEYID
:
614 (void) fprintf(NetTrace
, " DEC_KEYID ");
618 (void) fprintf(NetTrace
, " %d (unknown)",
621 for (i
= 2; i
< length
; i
++)
622 (void) fprintf(NetTrace
, " %d",
628 case TELOPT_LINEMODE
:
629 (void) fprintf(NetTrace
, "LINEMODE ");
631 (void) fprintf(NetTrace
,
632 " (empty suboption??\?)");
635 switch (pointer
[1]) {
637 (void) fprintf(NetTrace
, "WILL ");
640 (void) fprintf(NetTrace
, "WONT ");
643 (void) fprintf(NetTrace
, "DO ");
646 (void) fprintf(NetTrace
, "DONT ");
649 (void) fprintf(NetTrace
,
653 switch (pointer
[2]) {
655 (void) fprintf(NetTrace
,
657 for (i
= 3; i
< length
; i
++)
658 (void) fprintf(NetTrace
, " %x",
662 (void) fprintf(NetTrace
, "%d (unknown)",
664 for (i
= 3; i
< length
; i
++)
665 (void) fprintf(NetTrace
,
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",
679 (void) fprintf(NetTrace
, " %d",
680 pointer
[i
+SLC_FUNC
]);
681 switch (pointer
[i
+SLC_FLAGS
] &
684 (void) fprintf(NetTrace
,
688 (void) fprintf(NetTrace
,
692 (void) fprintf(NetTrace
,
696 (void) fprintf(NetTrace
,
700 (void) fprintf(NetTrace
, "%s%s%s",
701 pointer
[i
+SLC_FLAGS
]&SLC_ACK
?
703 pointer
[i
+SLC_FLAGS
]&SLC_FLUSHIN
?
705 pointer
[i
+SLC_FLAGS
]&SLC_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
))
718 for (; i
< length
; i
++)
719 (void) fprintf(NetTrace
, " ?%d?",
724 (void) fprintf(NetTrace
, "MODE ");
726 (void) fprintf(NetTrace
,
732 (void) sprintf(tbuf
, "%s%s%s%s%s",
733 pointer
[2]&MODE_EDIT
? "|EDIT" : "",
734 pointer
[2]&MODE_TRAPSIG
?
736 pointer
[2]&MODE_SOFT_TAB
?
738 pointer
[2]&MODE_LIT_ECHO
?
740 pointer
[2]&MODE_ACK
? "|ACK" : "");
741 (void) fprintf(NetTrace
, "%s", tbuf
[1] ?
744 if (pointer
[2]&~(MODE_MASK
))
745 (void) fprintf(NetTrace
, " (0x%x)",
747 for (i
= 3; i
< length
; i
++)
748 (void) fprintf(NetTrace
, " ?0x%x?",
752 (void) fprintf(NetTrace
, "%d (unknown)",
754 for (i
= 2; i
< length
; i
++)
755 (void) fprintf(NetTrace
, " %d",
760 case TELOPT_STATUS
: {
764 (void) fprintf(NetTrace
, "STATUS");
766 switch (pointer
[1]) {
768 if (pointer
[1] == TELQUAL_SEND
)
769 (void) fprintf(NetTrace
,
772 (void) fprintf(NetTrace
,
775 for (i
= 2; i
< length
; i
++)
776 (void) fprintf(NetTrace
, " ?%d?",
780 if (--want_status_response
< 0)
781 want_status_response
= 0;
782 if (NetTrace
== stdout
)
783 (void) fprintf(NetTrace
,
786 (void) fprintf(NetTrace
,
789 for (i
= 2; i
< length
; i
++) {
790 switch (pointer
[i
]) {
821 if (NetTrace
== stdout
)
832 (void) fprintf(NetTrace
,
837 if (pointer
[j
] == SE
) {
840 if (pointer
[j
+1] == SE
)
845 pointer
[k
++] = pointer
[j
++];
850 (void) fprintf(NetTrace
, " SE");
855 if (NetTrace
== stdout
)
856 (void) fprintf(NetTrace
, "\r\n");
858 (void) fprintf(NetTrace
, "\n");
863 (void) fprintf(NetTrace
,
873 case TELOPT_XDISPLOC
:
874 (void) fprintf(NetTrace
, "X-DISPLAY-LOCATION ");
875 switch (pointer
[1]) {
877 (void) fprintf(NetTrace
, "IS \"%.*s\"",
878 length
-2, (char *)pointer
+2);
881 (void) fprintf(NetTrace
, "SEND");
884 (void) fprintf(NetTrace
,
885 "- unknown qualifier %d (0x%x).",
886 pointer
[1], pointer
[1]);
890 case TELOPT_NEW_ENVIRON
:
891 (void) fprintf(NetTrace
, "NEW-ENVIRON ");
894 case TELOPT_OLD_ENVIRON
:
895 (void) fprintf(NetTrace
, "OLD-ENVIRON ");
898 switch (pointer
[1]) {
900 (void) fprintf(NetTrace
, "IS ");
903 (void) fprintf(NetTrace
, "SEND ");
906 (void) fprintf(NetTrace
, "INFO ");
909 register int noquote
= 2;
910 #if defined(ENV_HACK) && defined(OLD_ENVIRON)
911 extern int old_env_var
, old_env_value
;
913 for (i
= 2; i
< length
; i
++) {
914 switch (pointer
[i
]) {
917 /* case NEW_ENV_OVAR: */
918 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
920 if (old_env_var
== OLD_ENV_VALUE
)
921 (void) fprintf(NetTrace
,
922 "\" (VALUE) " + noquote
);
925 (void) fprintf(NetTrace
,
926 "\" VAR " + noquote
);
928 #endif /* OLD_ENVIRON */
929 (void) fprintf(NetTrace
, "\" VALUE " + noquote
);
935 /* case OLD_ENV_VALUE: */
936 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
938 if (old_env_value
== OLD_ENV_VAR
)
939 (void) fprintf(NetTrace
,
940 "\" (VAR) " + noquote
);
943 (void) fprintf(NetTrace
,
944 "\" VALUE " + noquote
);
946 #endif /* OLD_ENVIRON */
947 (void) fprintf(NetTrace
, "\" VAR " + noquote
);
952 (void) fprintf(NetTrace
, "\" ESC " + noquote
);
957 (void) fprintf(NetTrace
, "\" USERVAR " + noquote
);
963 if (isprint(pointer
[i
]) && pointer
[i
] != '"') {
965 (void) putc('"', NetTrace
);
968 (void) putc(pointer
[i
], NetTrace
);
970 (void) fprintf(NetTrace
, "\" %03o " + noquote
,
978 (void) putc('"', NetTrace
);
985 if (TELOPT_OK(pointer
[0]))
986 (void) fprintf(NetTrace
, "%s (unknown)", TELOPT(pointer
[0]));
988 (void) fprintf(NetTrace
, "%d (unknown)", pointer
[0]);
989 for (i
= 1; i
< length
; i
++)
990 (void) fprintf(NetTrace
, " %d", pointer
[i
]);
994 if (NetTrace
== stdout
)
995 (void) fprintf(NetTrace
, "\r\n");
997 (void) fprintf(NetTrace
, "\n");
999 if (NetTrace
== stdout
)
1000 (void) fflush(NetTrace
);
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).
1017 if (TTYBYTES() == 0) {
1019 /* wait for TTLOWAT */
1020 (void) select(tout
+1, NULL
, &o
, NULL
, NULL
);
1022 while (TTYBYTES()) {
1023 if (ttyflush(0) == -2) {
1024 /* This will not return. */
1025 fatal_tty_error("write");
1028 /* wait for TTLOWAT */
1029 (void) select(tout
+1, NULL
, &o
, NULL
, NULL
);
1039 (void) telrcv(); /* Process any incoming data */
1041 } while (ring_full_count(&netiring
)); /* While there is any */
1043 (void) fflush(stdout
);
1044 (void) fflush(stderr
);
1046 EmptyTerminal(); /* Flush the path to the tty */
1059 ExitString(string
, returnCode
)
1064 (void) fwrite(string
, 1, strlen(string
), stderr
);
1068 #define BUFFER_CHUNK_SIZE 64
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)
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.
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
1089 * If no buffer is to be supplied, specify a buffer address of NULL, via
1090 * the first argument.
1092 * If the pointer to the buffer address is NULL, the function just returns
1093 * NULL, and performs no other processing.
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.
1099 * The returned buffer will be a multiple of BUFFER_CHUNK_SIZE in size.
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.
1105 * The function returns the address of the buffer if any characters
1106 * are read and no error occurred, otherwise it returns NULL.
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.
1114 GetStringAtOffset(bufp
, cbufsiz
, off
, st
)
1116 unsigned int *cbufsiz
;
1120 unsigned int bufsiz
;
1123 unsigned int idx
= off
;
1130 bufsiz
= ROUND_CHUNK_SIZE(off
+ 1);
1132 if (buf
== NULL
|| cbufsiz
== NULL
|| *cbufsiz
!= bufsiz
) {
1133 if ((nbuf
= realloc(buf
, bufsiz
)) == NULL
)
1138 if (cbufsiz
!= NULL
)
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. */
1161 if (cbufsiz
!= NULL
)
1165 if (c
== EOF
|| c
== '\n') {
1167 if (ferror(st
) != 0) {
1168 /* Retry if interrupted by a signal. */
1169 if (errno
== EINTR
) {
1174 } else if (feof(st
) != 0) {
1175 /* No characters transferred? */
1187 * Read a string from the supplied stream. Stop reading when a newline
1188 * is read, end of file reached, or an error occurs.
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.
1196 * If no buffer is to be supplied, specify a buffer address of NULL,
1197 * via the first argument.
1199 * If the first argument is NULL, the function just returns NULL, and
1200 * performs no other processing.
1202 * The function returns the address of the buffer if any characters are
1203 * read and no error occurred.
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.
1210 GetString(bufp
, bufsiz
, st
)
1212 unsigned int *bufsiz
;
1215 return (GetStringAtOffset(bufp
, bufsiz
, 0, st
));
1219 * Allocate a buffer to hold a string of given length.
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.
1226 * If no existing buffer is to be supplied, pass a NULL buffer address via
1227 * the first argument.
1229 * If the first argument is NULL, the function just returns NULL,
1230 * and performs no other processing.
1233 AllocStringBuffer(bufp
, bufsiz
, size
)
1235 unsigned int *bufsiz
;
1238 return (GetStringAtOffset(bufp
, bufsiz
, size
, (FILE *)NULL
));
1242 * This function is similar to GetString(), except that the string read
1243 * from the stream is appended to the supplied string.
1246 GetAndAppendString(bufp
, bufsiz
, str
, st
)
1248 unsigned int *bufsiz
;
1252 unsigned int off
= strlen(str
);
1254 if (GetStringAtOffset(bufp
, bufsiz
, off
, st
) == NULL
)
1257 return (memcpy(*bufp
, str
, off
));