0.55 release
[catagits/fcgi2.git] / libfcgi / fcgi_stdio.c
CommitLineData
aadcc3c8 1/*
0198fd3c 2 * fcgi_stdio.c --
3 *
4 * FastCGI-stdio compatibility package
5 *
6 *
7 * Copyright (c) 1996 Open Market, Inc.
8 *
9 * See the file "LICENSE.TERMS" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 *
12 */
13
14#ifndef lint
6ad90ad2 15static const char rcsid[] = "$Id: fcgi_stdio.c,v 1.8 1999/07/28 00:24:15 roberts Exp $";
0198fd3c 16#endif /* not lint */
17
6ad90ad2 18#include "fcgi_config.h"
19
0198fd3c 20#ifdef _WIN32
21#define DLLAPI __declspec(dllexport)
6ad90ad2 22#include <windows.h>
0198fd3c 23#endif
24
6ad90ad2 25#include <errno.h> /* for errno */
26#include <stdarg.h> /* for va_arg */
27#include <stdlib.h> /* for malloc */
28#include <string.h> /* for strerror */
0198fd3c 29
0198fd3c 30#ifdef HAVE_UNISTD_H
31#include <unistd.h>
32#endif
33
6ad90ad2 34#define NO_FCGI_DEFINES
35#include "fcgi_stdio.h"
36#undef NO_FCGI_DEFINES
37
0198fd3c 38#include "fcgiapp.h"
39#include "fcgios.h"
40
6ad90ad2 41#ifndef _WIN32
42
43extern char **environ;
44
45/* These definitions should be supplied by stdio.h but for some
46 * reason they get lost on certain platforms. */
47#ifndef fileno
48extern int fileno(FILE *stream);
49#endif
50
51extern FILE *fdopen(int fildes, const char *type);
52extern FILE *popen(const char *command, const char *type);
53extern int pclose(FILE *stream);
54
55#else /* _WIN32 */
56
57#define popen _popen
58
59#endif /* _WIN32 */
60
0198fd3c 61#ifndef FALSE
62#define FALSE (0)
63#endif
6ad90ad2 64
0198fd3c 65#ifndef TRUE
66#define TRUE (1)
67#endif
68
0198fd3c 69FCGI_FILE _fcgi_sF[3];
0198fd3c 70
0198fd3c 71\f
72/*
73 *----------------------------------------------------------------------
74 *
75 * FCGI_Accept --
76 *
77 * Accepts a new request from the HTTP server and creates
78 * a conventional execution environment for the request.
79 *
80 * If the application was invoked as a FastCGI server,
81 * the first call to FCGI_Accept indicates that the application
82 * has completed its initialization and is ready to accept
83 * a request. Subsequent calls to FCGI_Accept indicate that
84 * the application has completed its processing of the
85 * current request and is ready to accept a new request.
86 *
87 * If the application was invoked as a CGI program, the first
88 * call to FCGI_Accept is essentially a no-op and the second
89 * call returns EOF (-1).
90 *
91 * Results:
92 * 0 for successful call, -1 for error (application should exit).
93 *
94 * Side effects:
95 * If the application was invoked as a FastCGI server,
96 * and this is not the first call to this procedure,
97 * FCGI_Accept first performs the equivalent of FCGI_Finish.
98 *
99 * On every call, FCGI_Accept accepts the new request and
100 * reads the FCGI_PARAMS stream into an environment array,
101 * i.e. a NULL-terminated array of strings of the form
102 * ``name=value''. It assigns a pointer to this array
103 * to the global variable environ, used by the standard
104 * library function getenv. It creates new FCGI_FILE *s
105 * representing input from the HTTP server, output to the HTTP
106 * server, and error output to the HTTP server, and assigns these
107 * new files to stdin, stdout, and stderr respectively.
108 *
109 * DO NOT mutate or retain pointers to environ or any values
110 * contained in it (e.g. to the result of calling getenv(3)),
111 * since these are freed by the next call to FCGI_Finish or
112 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
113 * in conjunction with FCGI_Accept.
114 *
115 *----------------------------------------------------------------------
116 */
117static int acceptCalled = FALSE;
118static int isCGI = FALSE;
0198fd3c 119
120int FCGI_Accept(void)
121{
122 if(!acceptCalled) {
123 /*
124 * First call to FCGI_Accept. Is application running
125 * as FastCGI or as CGI?
126 */
127 isCGI = FCGX_IsCGI();
128 acceptCalled = TRUE;
ac8a58ac 129 atexit(&FCGI_Finish);
0198fd3c 130 } else if(isCGI) {
131 /*
132 * Not first call to FCGI_Accept and running as CGI means
133 * application is done.
134 */
135 return(EOF);
136 }
137 if(isCGI) {
138 FCGI_stdin->stdio_stream = stdin;
139 FCGI_stdin->fcgx_stream = NULL;
140 FCGI_stdout->stdio_stream = stdout;
141 FCGI_stdout->fcgx_stream = NULL;
142 FCGI_stderr->stdio_stream = stderr;
143 FCGI_stderr->fcgx_stream = NULL;
144 } else {
145 FCGX_Stream *in, *out, *error;
146 FCGX_ParamArray envp;
147 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
148 if(acceptResult < 0) {
149 return acceptResult;
150 }
151 FCGI_stdin->stdio_stream = NULL;
152 FCGI_stdin->fcgx_stream = in;
153 FCGI_stdout->stdio_stream = NULL;
154 FCGI_stdout->fcgx_stream = out;
155 FCGI_stderr->stdio_stream = NULL;
156 FCGI_stderr->fcgx_stream = error;
157 environ = envp;
158 }
159 return 0;
160}
161\f
162/*
163 *----------------------------------------------------------------------
164 *
165 * FCGI_Finish --
166 *
167 * Finishes the current request from the HTTP server.
168 *
169 * Side effects:
170 *
171 * Flushes any buffered output to the HTTP server. Then frees
172 * all storage allocated by the previous call, including all
173 * storage reachable from the value of environ set by the previous
174 * call to FCGI_Accept.
175 *
176 * DO NOT use stdin, stdout, stderr, or environ between calling
177 * FCGI_Finish and calling FCGI_Accept.
178 *
179 * DO NOT mutate or retain pointers to environ or any values
180 * contained in it (e.g. to the result of calling getenv(3)),
181 * since these are freed by the next call to FCGI_Finish or
182 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
183 * in conjunction with FCGI_Accept.
184 *
185 *----------------------------------------------------------------------
186 */
187void FCGI_Finish(void)
188{
189 if(!acceptCalled || isCGI) {
190 return;
191 }
192 FCGX_Finish();
193 FCGI_stdin->fcgx_stream = NULL;
194 FCGI_stdout->fcgx_stream = NULL;
195 FCGI_stderr->fcgx_stream = NULL;
196 environ = NULL;
197}
198\f
199/*
200 *----------------------------------------------------------------------
201 *
202 * FCGI_StartFilterData --
203 *
aadcc3c8 204 *
0198fd3c 205 * The current request is for the filter role, and stdin is
aadcc3c8 206 * positioned at EOF of FCGI_STDIN. The call repositions
0198fd3c 207 * stdin to the start of FCGI_DATA.
208 * If the preconditions are not met (e.g. FCGI_STDIN has not
209 * been read to EOF), the call sets the stream error code to
210 * FCGX_CALL_SEQ_ERROR.
211 *
212 * Results:
aadcc3c8 213 * 0 for a normal return, < 0 for error
0198fd3c 214 *
215 *----------------------------------------------------------------------
216 */
217
218int FCGI_StartFilterData(void)
219{
220 if(FCGI_stdin->stdio_stream) {
221 return -1;
222 } else {
223 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
224 }
225}
226\f
227/*
228 *----------------------------------------------------------------------
229 *
230 * FCGI_SetExitStatus --
231 *
232 * Sets the exit status for the current request. The exit status
233 * is the status code the request would have exited with, had
234 * the request been run as a CGI program. You can call
235 * FCGI_SetExitStatus several times during a request; the last call
236 * before the request ends (by calling FCGI_Accept) determines the
237 * value.
238 *
239 *----------------------------------------------------------------------
240 */
241
242void FCGI_SetExitStatus(int status)
243{
244 if(FCGI_stdin->fcgx_stream) {
245 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
246 }
247}
248\f
249/*
250 *----------------------------------------------------------------------
251 *
252 * FCGI_perror --
253 *
254 * Wrapper for function defined in H&S Section 11.2
255 *
256 *----------------------------------------------------------------------
257 */
258
259void FCGI_perror(const char *str)
260{
261 FCGI_fputs(str, FCGI_stderr);
262 FCGI_fputs(": ", FCGI_stderr);
263 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
264 return;
265}
266\f
267/*
268 *----------------------------------------------------------------------
269 *
270 * FCGI_OpenFromFILE --
271 *
272 * Constructs a new FCGI_FILE * from the FILE *stream.
273 *
274 * Results:
275 * NULL if stream == NULL or storage could not be allocated,
276 * otherwise the new FCGI_FILE *.
277 *
278 *----------------------------------------------------------------------
aadcc3c8 279 */
0198fd3c 280
281static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
282{
283 FCGI_FILE *fp;
284 if(stream == NULL)
285 return NULL;
aadcc3c8 286 fp = (FCGI_FILE *)malloc(sizeof(FCGI_FILE));
0198fd3c 287 if(fp == NULL)
288 return NULL;
289 fp->stdio_stream = stream;
290 fp->fcgx_stream = NULL;
291 return fp;
292}
293\f
294/*
295 *----------------------------------------------------------------------
296 *
297 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
298 *
299 * Wrappers for functions defined in H&S Section 15.2
300 *
301 *----------------------------------------------------------------------
302 */
303
304FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
305{
306 return FCGI_OpenFromFILE(fopen(path, mode));
307}
308
309int FCGI_fclose(FCGI_FILE *fp)
310{
311 int n = EOF;
312 if(fp->stdio_stream) {
313 n = fclose(fp->stdio_stream);
314 fp->stdio_stream = NULL;
315 } else if(fp->fcgx_stream) {
316 n = FCGX_FClose(fp->fcgx_stream);
317 fp->fcgx_stream = NULL;
318 }
319 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
320 free(fp);
321 }
322 return n;
323}
324
325int FCGI_fflush(FCGI_FILE *fp)
326{
ed728efb 327 if(fp == NULL)
328 return fflush(NULL);
0198fd3c 329 if(fp->stdio_stream)
330 return fflush(fp->stdio_stream);
331 else if(fp->fcgx_stream)
332 return FCGX_FFlush(fp->fcgx_stream);
333 return EOF;
334}
335
336FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
337 FCGI_FILE *fp)
338{
339 if(fp->stdio_stream) {
340 if(freopen(path, mode, fp->stdio_stream) == NULL)
341 return NULL;
342 else
343 return fp;
344 } else if(fp->fcgx_stream) {
345 (void) FCGX_FClose(fp->fcgx_stream);
346 fp->stdio_stream = fopen(path, mode);
347 if(fp->stdio_stream == NULL)
348 return NULL;
349 else {
350 fp->fcgx_stream = NULL;
351 return fp;
352 }
353 }
354 return NULL;
355}
356\f
357/*
358 *----------------------------------------------------------------------
359 *
360 * FCGI_setvbuf, FCGI_setbuf --
361 *
362 * Wrappers for functions defined in H&S Section 15.3
363 *
364 *----------------------------------------------------------------------
365 */
366int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
367{
368 if(fp->stdio_stream)
369 return setvbuf(fp->stdio_stream, buf, bufmode, size);
370 else {
371 return -1;
372 }
373}
374
375void FCGI_setbuf(FCGI_FILE *fp, char *buf)
376{
377 if(fp->stdio_stream)
378 setbuf(fp->stdio_stream, buf);
379}
380\f
381/*
382 *----------------------------------------------------------------------
383 *
384 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
385 *
386 * Wrappers for functions defined in H&S Section 15.5
387 *
388 *----------------------------------------------------------------------
389 */
390
391int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
392{
393 if(fp->stdio_stream)
394 return fseek(fp->stdio_stream, offset, whence);
395 else {
396 OS_SetErrno(ESPIPE);
397 return -1;
398 }
399}
400
401int FCGI_ftell(FCGI_FILE *fp)
402{
403 if(fp->stdio_stream)
404 return ftell(fp->stdio_stream);
405 else {
406 OS_SetErrno(ESPIPE);
407 return -1;
aadcc3c8 408 }
0198fd3c 409}
410
411void FCGI_rewind(FCGI_FILE *fp)
412{
413 if(fp->stdio_stream)
414 rewind(fp->stdio_stream);
415 else
416 OS_SetErrno(ESPIPE);
417}
418
419#ifdef HAVE_FPOS
420int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
421{
422 if(fp->stdio_stream)
423 return fgetpos(fp->stdio_stream, pos);
424 else {
425 OS_SetErrno(ESPIPE);
426 return -1;
aadcc3c8 427 }
0198fd3c 428}
429
430int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
431{
432 if(fp->stdio_stream)
433 return fsetpos(fp->stdio_stream, pos);
434 else {
435 OS_SetErrno(ESPIPE);
436 return -1;
aadcc3c8 437 }
0198fd3c 438}
439#endif
440\f
441/*
442 *----------------------------------------------------------------------
443 *
444 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
445 *
446 * Wrappers for functions defined in H&S Section 15.6
447 *
448 * XXX: getc and getchar are generally defined as macros
449 * for performance reasons
450 *
451 *----------------------------------------------------------------------
452 */
453
454int FCGI_fgetc(FCGI_FILE *fp)
455{
456 if(fp->stdio_stream)
457 return fgetc(fp->stdio_stream);
458 else if(fp->fcgx_stream)
459 return FCGX_GetChar(fp->fcgx_stream);
460 return EOF;
461}
462
463int FCGI_getchar(void)
464{
465 return FCGI_fgetc(FCGI_stdin);
466}
467
468int FCGI_ungetc(int c, FCGI_FILE *fp)
469{
470 if(fp->stdio_stream)
471 return ungetc(c, fp->stdio_stream);
472 else if(fp->fcgx_stream)
473 return FCGX_UnGetChar(c, fp->fcgx_stream);
474 return EOF;
475}
476\f
477/*
478 *----------------------------------------------------------------------
479 *
480 * FCGI_fgets, FCGI_gets --
481 *
482 * Wrappers for functions defined in H&S Section 15.7
483 *
484 *----------------------------------------------------------------------
485 */
486
487char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
488{
489 if(fp->stdio_stream)
490 return fgets(str, size, fp->stdio_stream);
491 else if(fp->fcgx_stream)
492 return FCGX_GetLine(str, size, fp->fcgx_stream);
493 return NULL;
494}
495
496/*
497 * There is no standard equivalent of gets that takes an explicit
498 * FILE * argument, so the following "wrapper" implements
499 * gets for both FILE * and FCGX_Stream * in terms of FCGI_getchar.
500 */
501
502char *FCGI_gets(char *str)
503{
504 char *s;
505 int c;
506 for (s = str; ((c = FCGI_getchar()) != '\n');) {
507 if(c == EOF) {
aadcc3c8 508 if(s == str)
0198fd3c 509 return NULL;
510 else
511 break;
512 } else
513 *s++ = c;
514 }
515 *s = 0;
516 return str;
517}
518\f
519/*
520 *----------------------------------------------------------------------
521 *
522 * --
523 *
524 * Wrappers for functions defined in H&S Section 15.8
525 *
526 * XXX: missing: fscanf, scanf
527 *
528 *----------------------------------------------------------------------
529 */
530
531\f
532/*
533 *----------------------------------------------------------------------
534 *
535 * FCGI_fputc, FCGI_putchar --
536 *
537 * Wrappers for functions defined in H&S Section 15.9
538 *
539 * XXX: putc and putchar are generally defined as macros
540 * for performance reasons
541 *
542 *----------------------------------------------------------------------
543 */
544
545int FCGI_fputc(int c, FCGI_FILE *fp)
546{
aadcc3c8 547 if(fp->stdio_stream)
0198fd3c 548 return fputc(c, fp->stdio_stream);
549 else if(fp->fcgx_stream)
550 return FCGX_PutChar(c, fp->fcgx_stream);
551 else return EOF;
552}
553
554int FCGI_putchar(int c)
555{
556 return FCGI_fputc(c, FCGI_stdout);
557}
558\f
559/*
560 *----------------------------------------------------------------------
561 *
562 * FCGI_fputs, FCGI_puts
563 *
564 * Wrappers for functions defined in H&S Section 15.10
565 *
566 *----------------------------------------------------------------------
567 */
568
569int FCGI_fputs(const char *str, FCGI_FILE *fp)
570{
571 if(fp->stdio_stream)
572 return fputs(str, fp->stdio_stream);
573 else if(fp->fcgx_stream)
574 return FCGX_PutS(str, fp->fcgx_stream);
575 return EOF;
576}
577
578int FCGI_puts(const char *str)
579{
580 int n;
581 if(FCGI_stdout->stdio_stream) {
582 n = fputs(str, FCGI_stdout->stdio_stream);
583 if(n < 0)
584 return n;
585 else
586 return fputc('\n', FCGI_stdout->stdio_stream);
587 } else if(FCGI_stdout->fcgx_stream) {
588 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
589 if(n < 0)
590 return n;
591 else
592 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
593 }
594 return EOF;
595}
596\f
597/*
598 *----------------------------------------------------------------------
599 *
600 * FCGI_fprintf, FCGI_printf --
601 *
602 * Wrappers for functions defined in H&S Section 15.11
603 *
604 *----------------------------------------------------------------------
605 */
606
607int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
608{
609 va_list ap;
610 int n = 0;
611 va_start(ap, format);
612 if(fp->stdio_stream)
613 n = vfprintf(fp->stdio_stream, format, ap);
614 else if(fp->fcgx_stream)
615 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
616 va_end(ap);
617 return n;
618}
619
620int FCGI_printf(const char *format, ...)
621{
622 va_list ap;
623 int n;
624 va_start(ap, format);
625 n = FCGI_vfprintf(FCGI_stdout, format, ap);
626 va_end(ap);
627 return n;
628}
629\f
630/*
631 *----------------------------------------------------------------------
632 *
633 * FCGI_vfprintf, FCGI_vprintf --
634 *
635 * Wrappers for functions defined in H&S Section 15.12
636 *
637 *----------------------------------------------------------------------
638 */
639
640int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
641{
642 if(fp->stdio_stream)
643 return vfprintf(fp->stdio_stream, format, ap);
aadcc3c8 644 else if(fp->fcgx_stream)
0198fd3c 645 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
646 return EOF;
647}
648
649int FCGI_vprintf(const char *format, va_list ap)
650{
651 if(FCGI_stdout->stdio_stream)
652 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
aadcc3c8 653 else if(FCGI_stdout->fcgx_stream)
0198fd3c 654 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
655 return EOF;
656}
657\f
658/*
659 *----------------------------------------------------------------------
660 *
661 * FCGI_fread, FCGI_fwrite --
662 *
663 * Wrappers for functions defined in H&S Section 15.13
664 *
665 *----------------------------------------------------------------------
666 */
667
668size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
669{
670 int n;
671 if(fp->stdio_stream)
672 return fread(ptr, size, nmemb, fp->stdio_stream);
673 else if(fp->fcgx_stream) {
674 if((size * nmemb) == 0) {
675 return 0;
676 }
677 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
678 return (n/size);
679 }
680 return (size_t)EOF;
681}
682
683size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
684{
685 int n;
686 if(fp->stdio_stream)
687 return fwrite(ptr, size, nmemb, fp->stdio_stream);
688 else if(fp->fcgx_stream) {
689 if((size * nmemb) == 0) {
690 return 0;
691 }
692 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
693 return (n/size);
694 }
695 return (size_t)EOF;
696}
697\f
698/*
699 *----------------------------------------------------------------------
700 *
701 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
702 *
703 * Wrappers for functions defined in H&S Section 15.14
704 *
705 *----------------------------------------------------------------------
706 */
707int FCGI_feof(FCGI_FILE *fp)
708{
709 if(fp->stdio_stream) {
710 return feof(fp->stdio_stream);
711 } else if (fp->fcgx_stream){
712 return FCGX_HasSeenEOF(fp->fcgx_stream);
713 }
714 return -1;
715
716}
717
718int FCGI_ferror(FCGI_FILE *fp)
719{
720 if(fp->stdio_stream) {
721 return ferror(fp->stdio_stream);
722 } else if(fp->fcgx_stream) {
723 return FCGX_GetError(fp->fcgx_stream);
724 }
725 return -1;
726}
727
728void FCGI_clearerr(FCGI_FILE *fp)
729{
730 if(fp->stdio_stream) {
731 clearerr(fp->stdio_stream);
732 } else if(fp->fcgx_stream) {
733 FCGX_ClearError(fp->fcgx_stream);
734 }
735 return;
ed728efb 736}
17abbc3a 737\f
738/*
739 *----------------------------------------------------------------------
740 *
741 * FCGI_tmpfile --
742 *
743 * Wrappers for function defined in H&S Section 15.16
744 *
745 *----------------------------------------------------------------------
746 */
747FCGI_FILE *FCGI_tmpfile(void)
ed728efb 748{
749 return FCGI_OpenFromFILE(tmpfile());
0198fd3c 750}
17abbc3a 751
0198fd3c 752\f
753/*
754 *----------------------------------------------------------------------
755 *
756 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
757 *
758 * Wrappers for POSIX, X/OPEN functions not in ISO C
759 *
760 *----------------------------------------------------------------------
761 */
762
0198fd3c 763int FCGI_fileno(FCGI_FILE *fp)
764{
765 if(fp->stdio_stream)
766 return fileno(fp->stdio_stream);
767 else
768 return -1;
769}
770
771FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
772{
773#ifndef _WIN32
774 return FCGI_OpenFromFILE(fdopen(fd, mode));
775#else
776 return NULL;
777#endif
778}
779
780FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
781{
782 return FCGI_OpenFromFILE(popen(cmd, type));
783}
784
785int FCGI_pclose(FCGI_FILE *fp)
786{
787 int n = EOF;
788 if(fp->stdio_stream) {
789#ifndef _WIN32
790 n = pclose(fp->stdio_stream);
791#endif
792 fp->stdio_stream = NULL;
793 } else if(fp->fcgx_stream) {
794 /*
795 * The caller is deeply confused; don't free the storage.
796 */
797 return EOF;
798 }
799 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
800 free(fp);
801 }
802 return n;
803}
804
805/*
806 *----------------------------------------------------------------------
807 */