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
45 static char sccsid
[] = "@(#)utilities.c 8.1 (Berkeley) 6/6/93";
50 #include <arpa/telnet.h>
51 #include <sys/types.h>
53 #include <sys/param.h>
54 #include <sys/socket.h>
67 FILE *NetTrace
= 0; /* Not in bss, since needs to stay */
73 * Upcase (in place) the argument.
78 register char *argument
;
82 while ((c
= *argument
) != 0) {
84 *argument
= toupper(c
);
93 * Compensate for differences in 4.2 and 4.3 systems.
97 SetSockOpt(fd
, level
, option
, yesno
)
98 int fd
, level
, option
, yesno
;
100 return (setsockopt(fd
, level
, option
, &yesno
, sizeof (yesno
)));
104 * The following are routines used to print out debugging information.
107 unsigned char NetTraceFile
[MAXPATHLEN
] = "(standard output)";
113 if (NetTrace
&& NetTrace
!= stdout
)
114 (void) fclose(NetTrace
);
115 if (file
&& (strcmp(file
, "-") != 0)) {
116 NetTrace
= fopen(file
, "w");
118 (void) strcpy((char *)NetTraceFile
, file
);
121 (void) fprintf(stderr
, "Cannot open %s.\n", file
);
124 (void) strcpy((char *)NetTraceFile
, "(standard output)");
128 Dump(direction
, buffer
, length
)
130 unsigned char *buffer
;
133 #define BYTES_PER_LINE 32
134 #define min(x, y) ((x < y) ? x:y)
135 unsigned char *pThis
;
142 (void) fprintf(NetTrace
, "%c 0x%x\t", direction
, offset
);
145 buffer
= buffer
+ min(length
, BYTES_PER_LINE
/2);
146 while (pThis
< buffer
) {
147 (void) fprintf(NetTrace
, "%c%.2x",
148 (((*pThis
)&0xff) == 0xff) ? '*' : ' ',
152 length
-= BYTES_PER_LINE
/2;
153 offset
+= BYTES_PER_LINE
/2;
155 buffer
= buffer
+ min(length
, BYTES_PER_LINE
);
156 while (pThis
< buffer
) {
157 (void) fprintf(NetTrace
, "%.2x", (*pThis
)&0xff);
160 length
-= BYTES_PER_LINE
;
161 offset
+= BYTES_PER_LINE
;
163 if (NetTrace
== stdout
) {
164 (void) fprintf(NetTrace
, "\r\n");
166 (void) fprintf(NetTrace
, "\n");
169 (void) fflush(NetTrace
);
172 /* find next unique line */
174 (void) fflush(NetTrace
);
179 printoption(direction
, cmd
, option
)
186 if (TELCMD_OK(option
))
187 (void) fprintf(NetTrace
, "%s IAC %s", direction
,
190 (void) fprintf(NetTrace
, "%s IAC %d", direction
,
194 fmt
= (cmd
== WILL
) ? "WILL" : (cmd
== WONT
) ? "WONT" :
195 (cmd
== DO
) ? "DO" : (cmd
== DONT
) ? "DONT" : 0;
197 (void) fprintf(NetTrace
, "%s %s ", direction
, fmt
);
198 if (TELOPT_OK(option
))
199 (void) fprintf(NetTrace
, "%s", TELOPT(option
));
200 else if (option
== TELOPT_EXOPL
)
201 (void) fprintf(NetTrace
, "EXOPL");
203 (void) fprintf(NetTrace
, "%d", option
);
205 (void) fprintf(NetTrace
, "%s %d %d", direction
, cmd
,
208 if (NetTrace
== stdout
) {
209 (void) fprintf(NetTrace
, "\r\n");
210 (void) fflush(NetTrace
);
212 (void) fprintf(NetTrace
, "\n");
220 extern char will_wont_resp
[], do_dont_resp
[];
222 for (i
= 0; i
< SUBBUFSIZE
; i
++) {
223 if (do_dont_resp
[i
]) {
225 (void) printf("resp DO_DONT %s: %d\n",
226 TELOPT(i
), do_dont_resp
[i
]);
227 else if (TELCMD_OK(i
))
228 (void) printf("resp DO_DONT %s: %d\n",
229 TELCMD(i
), do_dont_resp
[i
]);
231 (void) printf("resp DO_DONT %d: %d\n", i
,
233 if (my_want_state_is_do(i
)) {
235 (void) printf("want DO %s\n",
237 else if (TELCMD_OK(i
))
238 (void) printf("want DO %s\n",
241 (void) printf("want DO %d\n", i
);
244 (void) printf("want DONT %s\n",
246 else if (TELCMD_OK(i
))
247 (void) printf("want DONT %s\n",
250 (void) printf("want DONT %d\n", i
);
253 if (my_state_is_do(i
)) {
255 (void) printf(" DO %s\n",
257 else if (TELCMD_OK(i
))
258 (void) printf(" DO %s\n",
261 (void) printf(" DO %d\n", i
);
264 if (will_wont_resp
[i
]) {
266 (void) printf("resp WILL_WONT %s: %d\n",
267 TELOPT(i
), will_wont_resp
[i
]);
268 else if (TELCMD_OK(i
))
269 (void) printf("resp WILL_WONT %s: %d\n",
270 TELCMD(i
), will_wont_resp
[i
]);
272 (void) printf("resp WILL_WONT %d: %d\n",
273 i
, will_wont_resp
[i
]);
274 if (my_want_state_is_will(i
)) {
276 (void) printf("want WILL %s\n",
278 else if (TELCMD_OK(i
))
279 (void) printf("want WILL %s\n",
282 (void) printf("want WILL %d\n", i
);
285 (void) printf("want WONT %s\n",
287 else if (TELCMD_OK(i
))
288 (void) printf("want WONT %s\n",
291 (void) printf("want WONT %d\n", i
);
294 if (my_state_is_will(i
)) {
296 (void) printf(" WILL %s\n",
298 else if (TELCMD_OK(i
))
299 (void) printf(" WILL %s\n",
302 (void) printf(" WILL %d\n", i
);
310 printsub(direction
, pointer
, length
)
311 char direction
; /* '<' or '>' */
312 unsigned char *pointer
; /* where suboption data sits */
313 int length
; /* length of suboption data */
317 extern int want_status_response
;
319 if (showoptions
|| direction
== 0 ||
320 (want_status_response
&& (pointer
[0] == TELOPT_STATUS
))) {
322 (void) fprintf(NetTrace
, "%s IAC SB ",
323 (direction
== '<')? "RCVD":"SENT");
327 i
= pointer
[length
-2];
328 j
= pointer
[length
-1];
330 if (i
!= IAC
|| j
!= SE
) {
331 (void) fprintf(NetTrace
,
334 (void) fprintf(NetTrace
, "%s ",
336 else if (TELCMD_OK(i
))
337 (void) fprintf(NetTrace
, "%s ",
340 (void) fprintf(NetTrace
, "%d ",
343 (void) fprintf(NetTrace
, "%s",
345 else if (TELCMD_OK(j
))
346 (void) fprintf(NetTrace
, "%s",
349 (void) fprintf(NetTrace
, "%d",
351 (void) fprintf(NetTrace
,
358 (void) fprintf(NetTrace
, "(Empty suboption??\?)");
359 if (NetTrace
== stdout
)
360 (void) fflush(NetTrace
);
363 switch (pointer
[0]) {
365 (void) fprintf(NetTrace
, "TERMINAL-TYPE ");
366 switch (pointer
[1]) {
368 (void) fprintf(NetTrace
, "IS \"%.*s\"",
373 (void) fprintf(NetTrace
, "SEND");
376 (void) fprintf(NetTrace
,
377 "- unknown qualifier %d (0x%x).",
378 pointer
[1], pointer
[1]);
382 (void) fprintf(NetTrace
, "TERMINAL-SPEED");
384 (void) fprintf(NetTrace
,
385 " (empty suboption??\?)");
388 switch (pointer
[1]) {
390 (void) fprintf(NetTrace
, " IS ");
391 (void) fprintf(NetTrace
, "%.*s", length
-2,
396 (void) fprintf(NetTrace
, " SEND");
398 (void) fprintf(NetTrace
,
399 " %d (unknown)", pointer
[1]);
400 for (i
= 2; i
< length
; i
++)
401 (void) fprintf(NetTrace
, " ?%d?",
408 (void) fprintf(NetTrace
, "TOGGLE-FLOW-CONTROL");
410 (void) fprintf(NetTrace
,
411 " (empty suboption??\?)");
414 switch (pointer
[1]) {
416 (void) fprintf(NetTrace
, " OFF");
419 (void) fprintf(NetTrace
, " ON");
421 case LFLOW_RESTART_ANY
:
422 (void) fprintf(NetTrace
, " RESTART-ANY");
424 case LFLOW_RESTART_XON
:
425 (void) fprintf(NetTrace
, " RESTART-XON");
428 (void) fprintf(NetTrace
, " %d (unknown)",
431 for (i
= 2; i
< length
; i
++)
432 (void) fprintf(NetTrace
, " ?%d?",
437 (void) fprintf(NetTrace
, "NAWS");
439 (void) fprintf(NetTrace
,
440 " (empty suboption??\?)");
444 (void) fprintf(NetTrace
, " ?%d?", pointer
[1]);
447 (void) fprintf(NetTrace
, " %d %d (%d)",
448 pointer
[1], pointer
[2],
449 (int)((((unsigned int)pointer
[1])<<8)|
450 ((unsigned int)pointer
[2])));
452 (void) fprintf(NetTrace
, " ?%d?", pointer
[3]);
455 (void) fprintf(NetTrace
, " %d %d (%d)",
456 pointer
[3], pointer
[4],
457 (int)((((unsigned int)pointer
[3])<<8)|
458 ((unsigned int)pointer
[4])));
459 for (i
= 5; i
< length
; i
++)
460 (void) fprintf(NetTrace
, " ?%d?", pointer
[i
]);
463 case TELOPT_AUTHENTICATION
:
464 (void) fprintf(NetTrace
, "AUTHENTICATION");
466 (void) fprintf(NetTrace
,
467 " (empty suboption??\?)");
470 switch (pointer
[1]) {
473 (void) fprintf(NetTrace
, " %s ",
474 (pointer
[1] == TELQUAL_IS
) ?
476 if (AUTHTYPE_NAME_OK(pointer
[2]))
477 (void) fprintf(NetTrace
, "%s ",
478 AUTHTYPE_NAME(pointer
[2]));
480 (void) fprintf(NetTrace
, "%d ",
483 (void) fprintf(NetTrace
,
484 "(partial suboption??\?)");
487 (void) fprintf(NetTrace
, "%s|%s",
488 ((pointer
[3] & AUTH_WHO_MASK
) ==
489 AUTH_WHO_CLIENT
) ? "CLIENT" : "SERVER",
490 ((pointer
[3] & AUTH_HOW_MASK
) ==
491 AUTH_HOW_MUTUAL
) ? "MUTUAL" : "ONE-WAY");
493 auth_printsub(&pointer
[1], length
- 1,
494 (uchar_t
*)buf
, sizeof (buf
));
495 (void) fprintf(NetTrace
, "%s", buf
);
500 (void) fprintf(NetTrace
, " SEND ");
502 if (AUTHTYPE_NAME_OK(pointer
[i
]))
503 (void) fprintf(NetTrace
, "%s ",
504 AUTHTYPE_NAME(pointer
[i
]));
506 (void) fprintf(NetTrace
, "%d ",
509 (void) fprintf(NetTrace
,
514 (void) fprintf(NetTrace
, "%s|%s ",
515 ((pointer
[i
] & AUTH_WHO_MASK
) ==
518 ((pointer
[i
] & AUTH_HOW_MASK
) ==
520 "MUTUAL" : "ONE-WAY");
527 (void) fprintf(NetTrace
, " NAME \"");
529 (void) putc(pointer
[i
++], NetTrace
);
530 (void) putc('"', NetTrace
);
534 for (i
= 2; i
< length
; i
++)
535 (void) fprintf(NetTrace
, " ?%d?", pointer
[i
]);
541 (void) fprintf(NetTrace
, "ENCRYPT");
543 (void) fprintf(NetTrace
,
544 " (empty suboption??\?)");
547 switch (pointer
[1]) {
549 (void) fprintf(NetTrace
, " START");
553 (void) fprintf(NetTrace
, " END");
556 case ENCRYPT_REQSTART
:
557 (void) fprintf(NetTrace
, " REQUEST-START");
561 (void) fprintf(NetTrace
, " REQUEST-END");
566 (void) fprintf(NetTrace
, " %s ",
567 (pointer
[1] == ENCRYPT_IS
) ?
570 (void) fprintf(NetTrace
, " (partial "
574 if (ENCTYPE_NAME_OK(pointer
[2]))
575 (void) fprintf(NetTrace
, "%s ",
576 ENCTYPE_NAME(pointer
[2]));
578 (void) fprintf(NetTrace
,
579 " %d (unknown)", pointer
[2]);
581 encrypt_printsub(&pointer
[1], length
- 1,
582 (uchar_t
*)buf
, sizeof (buf
));
583 (void) fprintf(NetTrace
, "%s", buf
);
586 case ENCRYPT_SUPPORT
:
588 (void) fprintf(NetTrace
, " SUPPORT ");
590 if (ENCTYPE_NAME_OK(pointer
[i
]))
591 (void) fprintf(NetTrace
, "%s ",
592 ENCTYPE_NAME(pointer
[i
]));
594 (void) fprintf(NetTrace
, "%d ",
600 case ENCRYPT_ENC_KEYID
:
601 (void) fprintf(NetTrace
, " ENC_KEYID ");
604 case ENCRYPT_DEC_KEYID
:
605 (void) fprintf(NetTrace
, " DEC_KEYID ");
609 (void) fprintf(NetTrace
, " %d (unknown)",
612 for (i
= 2; i
< length
; i
++)
613 (void) fprintf(NetTrace
, " %d",
619 case TELOPT_LINEMODE
:
620 (void) fprintf(NetTrace
, "LINEMODE ");
622 (void) fprintf(NetTrace
,
623 " (empty suboption??\?)");
626 switch (pointer
[1]) {
628 (void) fprintf(NetTrace
, "WILL ");
631 (void) fprintf(NetTrace
, "WONT ");
634 (void) fprintf(NetTrace
, "DO ");
637 (void) fprintf(NetTrace
, "DONT ");
640 (void) fprintf(NetTrace
,
644 switch (pointer
[2]) {
646 (void) fprintf(NetTrace
,
648 for (i
= 3; i
< length
; i
++)
649 (void) fprintf(NetTrace
, " %x",
653 (void) fprintf(NetTrace
, "%d (unknown)",
655 for (i
= 3; i
< length
; i
++)
656 (void) fprintf(NetTrace
,
663 (void) fprintf(NetTrace
, "SLC");
664 for (i
= 2; i
< length
- 2; i
+= 3) {
665 if (SLC_NAME_OK(pointer
[i
+SLC_FUNC
]))
666 (void) fprintf(NetTrace
, " %s",
670 (void) fprintf(NetTrace
, " %d",
671 pointer
[i
+SLC_FUNC
]);
672 switch (pointer
[i
+SLC_FLAGS
] &
675 (void) fprintf(NetTrace
,
679 (void) fprintf(NetTrace
,
683 (void) fprintf(NetTrace
,
687 (void) fprintf(NetTrace
,
691 (void) fprintf(NetTrace
, "%s%s%s",
692 pointer
[i
+SLC_FLAGS
]&SLC_ACK
?
694 pointer
[i
+SLC_FLAGS
]&SLC_FLUSHIN
?
696 pointer
[i
+SLC_FLAGS
]&SLC_FLUSHOUT
?
698 if (pointer
[i
+SLC_FLAGS
] &
699 ~(SLC_ACK
|SLC_FLUSHIN
|
700 SLC_FLUSHOUT
| SLC_LEVELBITS
))
701 (void) fprintf(NetTrace
, "(0x%x)",
702 pointer
[i
+SLC_FLAGS
]);
703 (void) fprintf(NetTrace
, " %d;",
704 pointer
[i
+SLC_VALUE
]);
705 if ((pointer
[i
+SLC_VALUE
] == IAC
) &&
706 (pointer
[i
+SLC_VALUE
+1] == IAC
))
709 for (; i
< length
; i
++)
710 (void) fprintf(NetTrace
, " ?%d?",
715 (void) fprintf(NetTrace
, "MODE ");
717 (void) fprintf(NetTrace
,
723 (void) sprintf(tbuf
, "%s%s%s%s%s",
724 pointer
[2]&MODE_EDIT
? "|EDIT" : "",
725 pointer
[2]&MODE_TRAPSIG
?
727 pointer
[2]&MODE_SOFT_TAB
?
729 pointer
[2]&MODE_LIT_ECHO
?
731 pointer
[2]&MODE_ACK
? "|ACK" : "");
732 (void) fprintf(NetTrace
, "%s", tbuf
[1] ?
735 if (pointer
[2]&~(MODE_MASK
))
736 (void) fprintf(NetTrace
, " (0x%x)",
738 for (i
= 3; i
< length
; i
++)
739 (void) fprintf(NetTrace
, " ?0x%x?",
743 (void) fprintf(NetTrace
, "%d (unknown)",
745 for (i
= 2; i
< length
; i
++)
746 (void) fprintf(NetTrace
, " %d",
751 case TELOPT_STATUS
: {
755 (void) fprintf(NetTrace
, "STATUS");
757 switch (pointer
[1]) {
759 if (pointer
[1] == TELQUAL_SEND
)
760 (void) fprintf(NetTrace
,
763 (void) fprintf(NetTrace
,
766 for (i
= 2; i
< length
; i
++)
767 (void) fprintf(NetTrace
, " ?%d?",
771 if (--want_status_response
< 0)
772 want_status_response
= 0;
773 if (NetTrace
== stdout
)
774 (void) fprintf(NetTrace
,
777 (void) fprintf(NetTrace
,
780 for (i
= 2; i
< length
; i
++) {
781 switch (pointer
[i
]) {
812 if (NetTrace
== stdout
)
823 (void) fprintf(NetTrace
,
828 if (pointer
[j
] == SE
) {
831 if (pointer
[j
+1] == SE
)
836 pointer
[k
++] = pointer
[j
++];
841 (void) fprintf(NetTrace
, " SE");
846 if (NetTrace
== stdout
)
847 (void) fprintf(NetTrace
, "\r\n");
849 (void) fprintf(NetTrace
, "\n");
854 (void) fprintf(NetTrace
,
864 case TELOPT_XDISPLOC
:
865 (void) fprintf(NetTrace
, "X-DISPLAY-LOCATION ");
866 switch (pointer
[1]) {
868 (void) fprintf(NetTrace
, "IS \"%.*s\"",
869 length
-2, (char *)pointer
+2);
872 (void) fprintf(NetTrace
, "SEND");
875 (void) fprintf(NetTrace
,
876 "- unknown qualifier %d (0x%x).",
877 pointer
[1], pointer
[1]);
881 case TELOPT_NEW_ENVIRON
:
882 (void) fprintf(NetTrace
, "NEW-ENVIRON ");
885 case TELOPT_OLD_ENVIRON
:
886 (void) fprintf(NetTrace
, "OLD-ENVIRON ");
889 switch (pointer
[1]) {
891 (void) fprintf(NetTrace
, "IS ");
894 (void) fprintf(NetTrace
, "SEND ");
897 (void) fprintf(NetTrace
, "INFO ");
900 register int noquote
= 2;
901 #if defined(ENV_HACK) && defined(OLD_ENVIRON)
902 extern int old_env_var
, old_env_value
;
904 for (i
= 2; i
< length
; i
++) {
905 switch (pointer
[i
]) {
908 /* case NEW_ENV_OVAR: */
909 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
911 if (old_env_var
== OLD_ENV_VALUE
)
912 (void) fprintf(NetTrace
,
913 "\" (VALUE) " + noquote
);
916 (void) fprintf(NetTrace
,
917 "\" VAR " + noquote
);
919 #endif /* OLD_ENVIRON */
920 (void) fprintf(NetTrace
, "\" VALUE " + noquote
);
926 /* case OLD_ENV_VALUE: */
927 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
929 if (old_env_value
== OLD_ENV_VAR
)
930 (void) fprintf(NetTrace
,
931 "\" (VAR) " + noquote
);
934 (void) fprintf(NetTrace
,
935 "\" VALUE " + noquote
);
937 #endif /* OLD_ENVIRON */
938 (void) fprintf(NetTrace
, "\" VAR " + noquote
);
943 (void) fprintf(NetTrace
, "\" ESC " + noquote
);
948 (void) fprintf(NetTrace
, "\" USERVAR " + noquote
);
954 if (isprint(pointer
[i
]) && pointer
[i
] != '"') {
956 (void) putc('"', NetTrace
);
959 (void) putc(pointer
[i
], NetTrace
);
961 (void) fprintf(NetTrace
, "\" %03o " + noquote
,
969 (void) putc('"', NetTrace
);
976 if (TELOPT_OK(pointer
[0]))
977 (void) fprintf(NetTrace
, "%s (unknown)", TELOPT(pointer
[0]));
979 (void) fprintf(NetTrace
, "%d (unknown)", pointer
[0]);
980 for (i
= 1; i
< length
; i
++)
981 (void) fprintf(NetTrace
, " %d", pointer
[i
]);
985 if (NetTrace
== stdout
)
986 (void) fprintf(NetTrace
, "\r\n");
988 (void) fprintf(NetTrace
, "\n");
990 if (NetTrace
== stdout
)
991 (void) fflush(NetTrace
);
996 * EmptyTerminal - called to make sure that the terminal buffer is empty.
997 * Note that we consider the buffer to run all the
998 * way to the kernel (thus the select).
1008 if (TTYBYTES() == 0) {
1010 /* wait for TTLOWAT */
1011 (void) select(tout
+1, NULL
, &o
, NULL
, NULL
);
1013 while (TTYBYTES()) {
1014 if (ttyflush(0) == -2) {
1015 /* This will not return. */
1016 fatal_tty_error("write");
1019 /* wait for TTLOWAT */
1020 (void) select(tout
+1, NULL
, &o
, NULL
, NULL
);
1030 (void) telrcv(); /* Process any incoming data */
1032 } while (ring_full_count(&netiring
)); /* While there is any */
1034 (void) fflush(stdout
);
1035 (void) fflush(stderr
);
1037 EmptyTerminal(); /* Flush the path to the tty */
1050 ExitString(string
, returnCode
)
1055 (void) fwrite(string
, 1, strlen(string
), stderr
);
1059 #define BUFFER_CHUNK_SIZE 64
1061 /* Round up to a multiple of BUFFER_CHUNK_SIZE */
1062 #define ROUND_CHUNK_SIZE(s) ((((s) + BUFFER_CHUNK_SIZE - 1) / \
1063 BUFFER_CHUNK_SIZE) * BUFFER_CHUNK_SIZE)
1066 * Optionally allocate a buffer, and optionally read a string from a stream
1067 * into the buffer, starting at the given offset. If the buffer isn't
1068 * large enough for the given offset, or if buffer space is exhausted
1069 * when reading the string, the size of the buffer is increased.
1071 * A buffer can be supplied when the function is called, passing the
1072 * buffer address via the first argument. The buffer size can be
1073 * passed as well, in the second argument. If the second argument is
1074 * NULL, the function makes no assumptions about the buffer size.
1075 * The address of the buffer is returned via the first argument, and the
1076 * buffer size via the second argument if this is not NULL.
1077 * These returned values may differ from the supplied values if the buffer
1080 * If no buffer is to be supplied, specify a buffer address of NULL, via
1081 * the first argument.
1083 * If the pointer to the buffer address is NULL, the function just returns
1084 * NULL, and performs no other processing.
1086 * If a NULL stream is passed, the function will just make sure the
1087 * supplied buffer is large enough to hold the supplied offset,
1088 * reallocating it if is too small or too large.
1090 * The returned buffer will be a multiple of BUFFER_CHUNK_SIZE in size.
1092 * The function stops reading from the stream when a newline is read,
1093 * end of file is reached, or an error occurs. The newline is not
1094 * returned in the buffer. The returned string will be NULL terminated.
1096 * The function returns the address of the buffer if any characters
1097 * are read and no error occurred, otherwise it returns NULL.
1099 * If the function returns NULL, a buffer may have been allocated. The
1100 * buffer address will be returned via the first argument, together with
1101 * the buffer size if the second argument is not NULL.
1105 GetStringAtOffset(bufp
, cbufsiz
, off
, st
)
1107 unsigned int *cbufsiz
;
1111 unsigned int bufsiz
;
1114 unsigned int idx
= off
;
1121 bufsiz
= ROUND_CHUNK_SIZE(off
+ 1);
1123 if (buf
== NULL
|| cbufsiz
== NULL
|| *cbufsiz
!= bufsiz
) {
1124 if ((nbuf
= realloc(buf
, bufsiz
)) == NULL
)
1129 if (cbufsiz
!= NULL
)
1141 /* Expand the buffer as needed. */
1142 if (idx
== bufsiz
) {
1143 bufsiz
+= BUFFER_CHUNK_SIZE
;
1144 if ((nbuf
= realloc(buf
, bufsiz
)) == NULL
) {
1145 /* Discard everything we read. */
1152 if (cbufsiz
!= NULL
)
1156 if (c
== EOF
|| c
== '\n') {
1158 if (ferror(st
) != 0) {
1159 /* Retry if interrupted by a signal. */
1160 if (errno
== EINTR
) {
1165 } else if (feof(st
) != 0) {
1166 /* No characters transferred? */
1178 * Read a string from the supplied stream. Stop reading when a newline
1179 * is read, end of file reached, or an error occurs.
1181 * A buffer can be supplied by specifying the buffer address via the
1182 * first argument. The buffer size can be passed via the second argument.
1183 * If the second argument is NULL, the function makes no assumptions
1184 * about the buffer size. The buffer will be reallocated if it is too
1185 * small or too large for the returned string.
1187 * If no buffer is to be supplied, specify a buffer address of NULL,
1188 * via the first argument.
1190 * If the first argument is NULL, the function just returns NULL, and
1191 * performs no other processing.
1193 * The function returns the address of the buffer if any characters are
1194 * read and no error occurred.
1196 * If the function returns NULL, a buffer may have been allocated. The
1197 * buffer address and buffer size will be returned via the first argument,
1198 * and the buffer size via the second argument, if this isn't NULL.
1201 GetString(bufp
, bufsiz
, st
)
1203 unsigned int *bufsiz
;
1206 return (GetStringAtOffset(bufp
, bufsiz
, 0, st
));
1210 * Allocate a buffer to hold a string of given length.
1212 * An existing buffer can be reallocated by passing its address and via
1213 * the first argument. The buffer size can be passed via the second
1214 * argument. If the second argument is NULL, the function makes no
1215 * assumptions about the buffer size.
1217 * If no existing buffer is to be supplied, pass a NULL buffer address via
1218 * the first argument.
1220 * If the first argument is NULL, the function just returns NULL,
1221 * and performs no other processing.
1224 AllocStringBuffer(bufp
, bufsiz
, size
)
1226 unsigned int *bufsiz
;
1229 return (GetStringAtOffset(bufp
, bufsiz
, size
, NULL
));
1233 * This function is similar to GetString(), except that the string read
1234 * from the stream is appended to the supplied string.
1237 GetAndAppendString(bufp
, bufsiz
, str
, st
)
1239 unsigned int *bufsiz
;
1243 unsigned int off
= strlen(str
);
1245 if (GetStringAtOffset(bufp
, bufsiz
, off
, st
) == NULL
)
1248 return (memcpy(*bufp
, str
, off
));