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