1 /* $NetBSD: utilities.c,v 1.21 2005/02/06 20:39:35 dsl Exp $ */
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95";
37 __RCSID("$NetBSD: utilities.c,v 1.21 2005/02/06 20:39:35 dsl Exp $");
44 #include <arpa/telnet.h>
45 #include <sys/types.h>
47 #include <sys/socket.h>
59 #include "../sys_curses/telextrn.h"
63 #include <libtelnet/auth.h>
66 #include <libtelnet/encrypt.h>
69 FILE *NetTrace
= 0; /* Not in bss, since needs to stay */
75 * Upcase (in place) the argument.
79 upcase(char *argument
)
83 while ((c
= *argument
) != 0) {
85 *argument
= toupper(c
);
94 * Compensate for differences in 4.2 and 4.3 systems.
98 SetSockOpt(int fd
, int level
, int option
, int yesno
)
100 return setsockopt(fd
, level
, option
, (char *)&yesno
, sizeof yesno
);
104 * The following are routines used to print out debugging information.
107 char NetTraceFile
[256] = "(standard output)";
110 SetNetTrace(char *file
)
112 if (NetTrace
&& NetTrace
!= stdout
)
114 if (file
&& (strcmp(file
, "-") != 0)) {
115 NetTrace
= fopen(file
, "w");
117 strlcpy(NetTraceFile
, file
, sizeof(NetTraceFile
));
120 fprintf(stderr
, "Cannot open %s.\n", file
);
123 strlcpy(NetTraceFile
, "(standard output)", sizeof(NetTraceFile
));
127 Dump(int direction
, unsigned char *buffer
, int length
)
129 # define BYTES_PER_LINE 32
130 # define min(x,y) ((x<y)? x:y)
131 unsigned char *pThis
;
138 fprintf(NetTrace
, "%c 0x%x\t", direction
, offset
);
141 buffer
= buffer
+ min(length
, BYTES_PER_LINE
/2);
142 while (pThis
< buffer
) {
143 fprintf(NetTrace
, "%c%.2x",
144 (((*pThis
)&0xff) == 0xff) ? '*' : ' ',
148 length
-= BYTES_PER_LINE
/2;
149 offset
+= BYTES_PER_LINE
/2;
151 buffer
= buffer
+ min(length
, BYTES_PER_LINE
);
152 while (pThis
< buffer
) {
153 fprintf(NetTrace
, "%.2x", (*pThis
)&0xff);
156 length
-= BYTES_PER_LINE
;
157 offset
+= BYTES_PER_LINE
;
159 if (NetTrace
== stdout
) {
160 fprintf(NetTrace
, "\r\n");
162 fprintf(NetTrace
, "\n");
168 /* find next unique line */
175 printoption(char *direction
, int cmd
, int option
)
180 if (TELCMD_OK(option
))
181 fprintf(NetTrace
, "%s IAC %s", direction
, TELCMD(option
));
183 fprintf(NetTrace
, "%s IAC %d", direction
, option
);
186 fmt
= (cmd
== WILL
) ? "WILL" : (cmd
== WONT
) ? "WONT" :
187 (cmd
== DO
) ? "DO" : (cmd
== DONT
) ? "DONT" : 0;
189 fprintf(NetTrace
, "%s %s ", direction
, fmt
);
190 if (TELOPT_OK(option
))
191 fprintf(NetTrace
, "%s", TELOPT(option
));
192 else if (option
== TELOPT_EXOPL
)
193 fprintf(NetTrace
, "EXOPL");
195 fprintf(NetTrace
, "%d", option
);
197 fprintf(NetTrace
, "%s %d %d", direction
, cmd
, option
);
199 if (NetTrace
== stdout
) {
200 fprintf(NetTrace
, "\r\n");
203 fprintf(NetTrace
, "\n");
212 extern char will_wont_resp
[], do_dont_resp
[];
214 for (i
= 0; i
< 256; i
++) {
215 if (do_dont_resp
[i
]) {
217 printf("resp DO_DONT %s: %d\n", TELOPT(i
), do_dont_resp
[i
]);
218 else if (TELCMD_OK(i
))
219 printf("resp DO_DONT %s: %d\n", TELCMD(i
), do_dont_resp
[i
]);
221 printf("resp DO_DONT %d: %d\n", i
,
223 if (my_want_state_is_do(i
)) {
225 printf("want DO %s\n", TELOPT(i
));
226 else if (TELCMD_OK(i
))
227 printf("want DO %s\n", TELCMD(i
));
229 printf("want DO %d\n", i
);
232 printf("want DONT %s\n", TELOPT(i
));
233 else if (TELCMD_OK(i
))
234 printf("want DONT %s\n", TELCMD(i
));
236 printf("want DONT %d\n", i
);
239 if (my_state_is_do(i
)) {
241 printf(" DO %s\n", TELOPT(i
));
242 else if (TELCMD_OK(i
))
243 printf(" DO %s\n", TELCMD(i
));
245 printf(" DO %d\n", i
);
248 if (will_wont_resp
[i
]) {
250 printf("resp WILL_WONT %s: %d\n", TELOPT(i
), will_wont_resp
[i
]);
251 else if (TELCMD_OK(i
))
252 printf("resp WILL_WONT %s: %d\n", TELCMD(i
), will_wont_resp
[i
]);
254 printf("resp WILL_WONT %d: %d\n",
255 i
, will_wont_resp
[i
]);
256 if (my_want_state_is_will(i
)) {
258 printf("want WILL %s\n", TELOPT(i
));
259 else if (TELCMD_OK(i
))
260 printf("want WILL %s\n", TELCMD(i
));
262 printf("want WILL %d\n", i
);
265 printf("want WONT %s\n", TELOPT(i
));
266 else if (TELCMD_OK(i
))
267 printf("want WONT %s\n", TELCMD(i
));
269 printf("want WONT %d\n", i
);
272 if (my_state_is_will(i
)) {
274 printf(" WILL %s\n", TELOPT(i
));
275 else if (TELCMD_OK(i
))
276 printf(" WILL %s\n", TELCMD(i
));
278 printf(" WILL %d\n", i
);
287 int direction
, /* '<' or '>' */
288 unsigned char *pointer
, /* where suboption data sits */
289 int length
) /* length of suboption data */
294 #endif /* ENCRYPTION */
295 extern int want_status_response
;
297 if (showoptions
|| direction
== 0 ||
298 (want_status_response
&& (pointer
[0] == TELOPT_STATUS
))) {
300 fprintf(NetTrace
, "%s IAC SB ",
301 (direction
== '<')? "RCVD":"SENT");
305 i
= pointer
[length
-2];
306 j
= pointer
[length
-1];
308 if (i
!= IAC
|| j
!= SE
) {
309 fprintf(NetTrace
, "(terminated by ");
311 fprintf(NetTrace
, "%s ", TELOPT(i
));
312 else if (TELCMD_OK(i
))
313 fprintf(NetTrace
, "%s ", TELCMD(i
));
315 fprintf(NetTrace
, "%d ", i
);
317 fprintf(NetTrace
, "%s", TELOPT(j
));
318 else if (TELCMD_OK(j
))
319 fprintf(NetTrace
, "%s", TELCMD(j
));
321 fprintf(NetTrace
, "%d", j
);
322 fprintf(NetTrace
, ", not IAC SE!) ");
328 fprintf(NetTrace
, "(Empty suboption??\?)");
329 if (NetTrace
== stdout
)
333 switch (pointer
[0]) {
335 fprintf(NetTrace
, "TERMINAL-TYPE ");
336 switch (pointer
[1]) {
338 fprintf(NetTrace
, "IS \"%.*s\"", length
-2, (char *)pointer
+2);
341 fprintf(NetTrace
, "SEND");
345 "- unknown qualifier %d (0x%x).",
346 pointer
[1], pointer
[1]);
350 fprintf(NetTrace
, "TERMINAL-SPEED");
352 fprintf(NetTrace
, " (empty suboption??\?)");
355 switch (pointer
[1]) {
357 fprintf(NetTrace
, " IS ");
358 fprintf(NetTrace
, "%.*s", length
-2, (char *)pointer
+2);
362 fprintf(NetTrace
, " SEND");
364 fprintf(NetTrace
, " %d (unknown)", pointer
[1]);
365 for (i
= 2; i
< length
; i
++)
366 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
372 fprintf(NetTrace
, "TOGGLE-FLOW-CONTROL");
374 fprintf(NetTrace
, " (empty suboption??\?)");
377 switch (pointer
[1]) {
379 fprintf(NetTrace
, " OFF"); break;
381 fprintf(NetTrace
, " ON"); break;
382 case LFLOW_RESTART_ANY
:
383 fprintf(NetTrace
, " RESTART-ANY"); break;
384 case LFLOW_RESTART_XON
:
385 fprintf(NetTrace
, " RESTART-XON"); break;
387 fprintf(NetTrace
, " %d (unknown)", pointer
[1]);
389 for (i
= 2; i
< length
; i
++)
390 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
394 fprintf(NetTrace
, "NAWS");
396 fprintf(NetTrace
, " (empty suboption??\?)");
400 fprintf(NetTrace
, " ?%d?", pointer
[1]);
403 fprintf(NetTrace
, " %d %d (%d)",
404 pointer
[1], pointer
[2],
405 (int)((((unsigned int)pointer
[1])<<8)|((unsigned int)pointer
[2])));
407 fprintf(NetTrace
, " ?%d?", pointer
[3]);
410 fprintf(NetTrace
, " %d %d (%d)",
411 pointer
[3], pointer
[4],
412 (int)((((unsigned int)pointer
[3])<<8)|((unsigned int)pointer
[4])));
413 for (i
= 5; i
< length
; i
++)
414 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
417 #ifdef AUTHENTICATION
418 case TELOPT_AUTHENTICATION
:
419 fprintf(NetTrace
, "AUTHENTICATION");
421 fprintf(NetTrace
, " (empty suboption??\?)");
424 switch (pointer
[1]) {
427 fprintf(NetTrace
, " %s ", (pointer
[1] == TELQUAL_IS
) ?
429 if (AUTHTYPE_NAME_OK(pointer
[2]))
430 fprintf(NetTrace
, "%s ", AUTHTYPE_NAME(pointer
[2]));
432 fprintf(NetTrace
, "%d ", pointer
[2]);
434 fprintf(NetTrace
, "(partial suboption??\?)");
437 fprintf(NetTrace
, "%s|%s",
438 ((pointer
[3] & AUTH_WHO_MASK
) == AUTH_WHO_CLIENT
) ?
440 ((pointer
[3] & AUTH_HOW_MASK
) == AUTH_HOW_MUTUAL
) ?
441 "MUTUAL" : "ONE-WAY");
443 auth_printsub(&pointer
[1], length
- 1, buf
, sizeof(buf
));
444 fprintf(NetTrace
, "%s", buf
);
449 fprintf(NetTrace
, " SEND ");
451 if (AUTHTYPE_NAME_OK(pointer
[i
]))
452 fprintf(NetTrace
, "%s ", AUTHTYPE_NAME(pointer
[i
]));
454 fprintf(NetTrace
, "%d ", pointer
[i
]);
456 fprintf(NetTrace
, "(partial suboption??\?)");
459 fprintf(NetTrace
, "%s|%s ",
460 ((pointer
[i
] & AUTH_WHO_MASK
) == AUTH_WHO_CLIENT
) ?
462 ((pointer
[i
] & AUTH_HOW_MASK
) == AUTH_HOW_MUTUAL
) ?
463 "MUTUAL" : "ONE-WAY");
470 fprintf(NetTrace
, " NAME \"");
472 putc(pointer
[i
++], NetTrace
);
477 for (i
= 2; i
< length
; i
++)
478 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
486 fprintf(NetTrace
, "ENCRYPT");
488 fprintf(NetTrace
, " (empty suboption??\?)");
491 switch (pointer
[1]) {
493 fprintf(NetTrace
, " START");
497 fprintf(NetTrace
, " END");
500 case ENCRYPT_REQSTART
:
501 fprintf(NetTrace
, " REQUEST-START");
505 fprintf(NetTrace
, " REQUEST-END");
510 fprintf(NetTrace
, " %s ", (pointer
[1] == ENCRYPT_IS
) ?
513 fprintf(NetTrace
, " (partial suboption??\?)");
516 if (ENCTYPE_NAME_OK(pointer
[2]))
517 fprintf(NetTrace
, "%s ",
518 ENCTYPE_NAME(pointer
[2]));
520 fprintf(NetTrace
, " %d (unknown)", pointer
[2]);
522 encrypt_printsub(&pointer
[1], length
- 1, buf
,
524 fprintf(NetTrace
, "%s", buf
);
527 case ENCRYPT_SUPPORT
:
529 fprintf(NetTrace
, " SUPPORT ");
531 if (ENCTYPE_NAME_OK(pointer
[i
]))
532 fprintf(NetTrace
, "%s ",
533 ENCTYPE_NAME(pointer
[i
]));
535 fprintf(NetTrace
, "%d ", pointer
[i
]);
540 case ENCRYPT_ENC_KEYID
:
541 fprintf(NetTrace
, " ENC_KEYID ");
544 case ENCRYPT_DEC_KEYID
:
545 fprintf(NetTrace
, " DEC_KEYID ");
549 fprintf(NetTrace
, " %d (unknown)", pointer
[1]);
551 for (i
= 2; i
< length
; i
++)
552 fprintf(NetTrace
, " %d", pointer
[i
]);
556 #endif /* ENCRYPTION */
558 case TELOPT_LINEMODE
:
559 fprintf(NetTrace
, "LINEMODE ");
561 fprintf(NetTrace
, " (empty suboption??\?)");
564 switch (pointer
[1]) {
566 fprintf(NetTrace
, "WILL ");
569 fprintf(NetTrace
, "WONT ");
572 fprintf(NetTrace
, "DO ");
575 fprintf(NetTrace
, "DONT ");
578 fprintf(NetTrace
, "(no option??\?)");
581 switch (pointer
[2]) {
583 fprintf(NetTrace
, "Forward Mask");
584 for (i
= 3; i
< length
; i
++)
585 fprintf(NetTrace
, " %x", pointer
[i
]);
588 fprintf(NetTrace
, "%d (unknown)", pointer
[2]);
589 for (i
= 3; i
< length
; i
++)
590 fprintf(NetTrace
, " %d", pointer
[i
]);
596 fprintf(NetTrace
, "SLC");
597 for (i
= 2; i
< length
- 2; i
+= 3) {
598 if (SLC_NAME_OK(pointer
[i
+SLC_FUNC
]))
599 fprintf(NetTrace
, " %s", SLC_NAME(pointer
[i
+SLC_FUNC
]));
601 fprintf(NetTrace
, " %d", pointer
[i
+SLC_FUNC
]);
602 switch (pointer
[i
+SLC_FLAGS
]&SLC_LEVELBITS
) {
604 fprintf(NetTrace
, " NOSUPPORT"); break;
606 fprintf(NetTrace
, " CANTCHANGE"); break;
608 fprintf(NetTrace
, " VARIABLE"); break;
610 fprintf(NetTrace
, " DEFAULT"); break;
612 fprintf(NetTrace
, "%s%s%s",
613 pointer
[i
+SLC_FLAGS
]&SLC_ACK
? "|ACK" : "",
614 pointer
[i
+SLC_FLAGS
]&SLC_FLUSHIN
? "|FLUSHIN" : "",
615 pointer
[i
+SLC_FLAGS
]&SLC_FLUSHOUT
? "|FLUSHOUT" : "");
616 if (pointer
[i
+SLC_FLAGS
]& ~(SLC_ACK
|SLC_FLUSHIN
|
617 SLC_FLUSHOUT
| SLC_LEVELBITS
))
618 fprintf(NetTrace
, "(0x%x)", pointer
[i
+SLC_FLAGS
]);
619 fprintf(NetTrace
, " %d;", pointer
[i
+SLC_VALUE
]);
620 if ((pointer
[i
+SLC_VALUE
] == IAC
) &&
621 (pointer
[i
+SLC_VALUE
+1] == IAC
))
624 for (; i
< length
; i
++)
625 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
629 fprintf(NetTrace
, "MODE ");
631 fprintf(NetTrace
, "(no mode??\?)");
636 sprintf(tbuf
, "%s%s%s%s%s",
637 pointer
[2]&MODE_EDIT
? "|EDIT" : "",
638 pointer
[2]&MODE_TRAPSIG
? "|TRAPSIG" : "",
639 pointer
[2]&MODE_SOFT_TAB
? "|SOFT_TAB" : "",
640 pointer
[2]&MODE_LIT_ECHO
? "|LIT_ECHO" : "",
641 pointer
[2]&MODE_ACK
? "|ACK" : "");
642 fprintf(NetTrace
, "%s", tbuf
[1] ? &tbuf
[1] : "0");
644 if (pointer
[2]&~(MODE_MASK
))
645 fprintf(NetTrace
, " (0x%x)", pointer
[2]);
646 for (i
= 3; i
< length
; i
++)
647 fprintf(NetTrace
, " ?0x%x?", pointer
[i
]);
650 fprintf(NetTrace
, "%d (unknown)", pointer
[1]);
651 for (i
= 2; i
< length
; i
++)
652 fprintf(NetTrace
, " %d", pointer
[i
]);
656 case TELOPT_STATUS
: {
660 fprintf(NetTrace
, "STATUS");
662 switch (pointer
[1]) {
664 if (pointer
[1] == TELQUAL_SEND
)
665 fprintf(NetTrace
, " SEND");
667 fprintf(NetTrace
, " %d (unknown)", pointer
[1]);
668 for (i
= 2; i
< length
; i
++)
669 fprintf(NetTrace
, " ?%d?", pointer
[i
]);
672 if (--want_status_response
< 0)
673 want_status_response
= 0;
674 if (NetTrace
== stdout
)
675 fprintf(NetTrace
, " IS\r\n");
677 fprintf(NetTrace
, " IS\n");
679 for (i
= 2; i
< length
; i
++) {
681 case DO
: cp
= "DO"; goto common2
;
682 case DONT
: cp
= "DONT"; goto common2
;
683 case WILL
: cp
= "WILL"; goto common2
;
684 case WONT
: cp
= "WONT"; goto common2
;
687 if (TELOPT_OK((int)pointer
[i
]))
688 fprintf(NetTrace
, " %s %s", cp
, TELOPT(pointer
[i
]));
690 fprintf(NetTrace
, " %s %d", cp
, pointer
[i
]);
692 if (NetTrace
== stdout
)
693 fprintf(NetTrace
, "\r\n");
695 fprintf(NetTrace
, "\n");
699 fprintf(NetTrace
, " SB ");
703 if (pointer
[j
] == SE
) {
706 if (pointer
[j
+1] == SE
)
711 pointer
[k
++] = pointer
[j
++];
713 printsub(0, &pointer
[i
], k
- i
);
715 fprintf(NetTrace
, " SE");
720 if (NetTrace
== stdout
)
721 fprintf(NetTrace
, "\r\n");
723 fprintf(NetTrace
, "\n");
728 fprintf(NetTrace
, " %d", pointer
[i
]);
737 case TELOPT_XDISPLOC
:
738 fprintf(NetTrace
, "X-DISPLAY-LOCATION ");
739 switch (pointer
[1]) {
741 fprintf(NetTrace
, "IS \"%.*s\"", length
-2, (char *)pointer
+2);
744 fprintf(NetTrace
, "SEND");
747 fprintf(NetTrace
, "- unknown qualifier %d (0x%x).",
748 pointer
[1], pointer
[1]);
752 case TELOPT_NEW_ENVIRON
:
753 fprintf(NetTrace
, "NEW-ENVIRON ");
756 case TELOPT_OLD_ENVIRON
:
757 fprintf(NetTrace
, "OLD-ENVIRON");
760 switch (pointer
[1]) {
762 fprintf(NetTrace
, "IS ");
765 fprintf(NetTrace
, "SEND ");
768 fprintf(NetTrace
, "INFO ");
772 #if defined(ENV_HACK) && defined(OLD_ENVIRON)
773 extern int old_env_var
, old_env_value
;
775 for (i
= 2; i
< length
; i
++ ) {
776 switch (pointer
[i
]) {
779 /* case NEW_ENV_OVAR: */
780 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
782 if (old_env_var
== OLD_ENV_VALUE
)
783 fprintf(NetTrace
, "\" (VALUE) " + noquote
);
786 fprintf(NetTrace
, "\" VAR " + noquote
);
788 #endif /* OLD_ENVIRON */
789 fprintf(NetTrace
, "\" VALUE " + noquote
);
795 /* case OLD_ENV_VALUE: */
796 if (pointer
[0] == TELOPT_OLD_ENVIRON
) {
798 if (old_env_value
== OLD_ENV_VAR
)
799 fprintf(NetTrace
, "\" (VAR) " + noquote
);
802 fprintf(NetTrace
, "\" VALUE " + noquote
);
804 #endif /* OLD_ENVIRON */
805 fprintf(NetTrace
, "\" VAR " + noquote
);
810 fprintf(NetTrace
, "\" ESC " + noquote
);
815 fprintf(NetTrace
, "\" USERVAR " + noquote
);
820 if (isprint(pointer
[i
]) && pointer
[i
] != '"') {
825 putc(pointer
[i
], NetTrace
);
827 fprintf(NetTrace
, "\" %03o " + noquote
,
842 if (TELOPT_OK(pointer
[0]))
843 fprintf(NetTrace
, "%s (unknown)", TELOPT(pointer
[0]));
845 fprintf(NetTrace
, "%d (unknown)", pointer
[0]);
846 for (i
= 1; i
< length
; i
++)
847 fprintf(NetTrace
, " %d", pointer
[i
]);
851 if (NetTrace
== stdout
)
852 fprintf(NetTrace
, "\r\n");
854 fprintf(NetTrace
, "\n");
856 if (NetTrace
== stdout
)
861 /* EmptyTerminal - called to make sure that the terminal buffer is empty.
862 * Note that we consider the buffer to run all the
863 * way to the kernel (thus the poll).
869 struct pollfd set
[1];
872 set
[0].events
= POLLOUT
;
874 if (TTYBYTES() == 0) {
875 (void) poll(set
, 1, INFTIM
);
879 (void) poll(set
, 1, INFTIM
);
892 #else /* defined(TN3270) */
894 (void)telrcv(); /* Process any incoming data */
896 } while (ring_full_count(&netiring
)); /* While there is any */
897 #endif /* defined(TN3270) */
905 #endif /* defined(TN3270) */
907 EmptyTerminal(); /* Flush the path to the tty */
919 ExitString(char *string
, int returnCode
)
922 fwrite(string
, 1, strlen(string
), stderr
);