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