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