4 * FastCGI-stdio compatibility package
7 * Copyright (c) 1996 Open Market, Inc.
9 * See the file "LICENSE.TERMS" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 static const char rcsid[] = "$Id: fcgi_stdio.c,v 1.9 2000/10/30 22:52:24 robs Exp $";
18 #include "fcgi_config.h"
21 #define DLLAPI __declspec(dllexport)
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 */
34 #define NO_FCGI_DEFINES
35 #include "fcgi_stdio.h"
36 #undef NO_FCGI_DEFINES
43 extern char **environ;
45 /* These definitions should be supplied by stdio.h but for some
46 * reason they get lost on certain platforms. */
48 extern int fileno(FILE *stream);
51 extern FILE *fdopen(int fildes, const char *type);
52 extern FILE *popen(const char *command, const char *type);
53 extern int pclose(FILE *stream);
58 #define pclose _pclose
70 FCGI_FILE _fcgi_sF[3];
74 *----------------------------------------------------------------------
78 * Accepts a new request from the HTTP server and creates
79 * a conventional execution environment for the request.
81 * If the application was invoked as a FastCGI server,
82 * the first call to FCGI_Accept indicates that the application
83 * has completed its initialization and is ready to accept
84 * a request. Subsequent calls to FCGI_Accept indicate that
85 * the application has completed its processing of the
86 * current request and is ready to accept a new request.
88 * If the application was invoked as a CGI program, the first
89 * call to FCGI_Accept is essentially a no-op and the second
90 * call returns EOF (-1).
93 * 0 for successful call, -1 for error (application should exit).
96 * If the application was invoked as a FastCGI server,
97 * and this is not the first call to this procedure,
98 * FCGI_Accept first performs the equivalent of FCGI_Finish.
100 * On every call, FCGI_Accept accepts the new request and
101 * reads the FCGI_PARAMS stream into an environment array,
102 * i.e. a NULL-terminated array of strings of the form
103 * ``name=value''. It assigns a pointer to this array
104 * to the global variable environ, used by the standard
105 * library function getenv. It creates new FCGI_FILE *s
106 * representing input from the HTTP server, output to the HTTP
107 * server, and error output to the HTTP server, and assigns these
108 * new files to stdin, stdout, and stderr respectively.
110 * DO NOT mutate or retain pointers to environ or any values
111 * contained in it (e.g. to the result of calling getenv(3)),
112 * since these are freed by the next call to FCGI_Finish or
113 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
114 * in conjunction with FCGI_Accept.
116 *----------------------------------------------------------------------
118 static int acceptCalled = FALSE;
119 static int isCGI = FALSE;
121 int FCGI_Accept(void)
125 * First call to FCGI_Accept. Is application running
126 * as FastCGI or as CGI?
128 isCGI = FCGX_IsCGI();
130 atexit(&FCGI_Finish);
133 * Not first call to FCGI_Accept and running as CGI means
134 * application is done.
139 FCGI_stdin->stdio_stream = stdin;
140 FCGI_stdin->fcgx_stream = NULL;
141 FCGI_stdout->stdio_stream = stdout;
142 FCGI_stdout->fcgx_stream = NULL;
143 FCGI_stderr->stdio_stream = stderr;
144 FCGI_stderr->fcgx_stream = NULL;
146 FCGX_Stream *in, *out, *error;
147 FCGX_ParamArray envp;
148 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
149 if(acceptResult < 0) {
152 FCGI_stdin->stdio_stream = NULL;
153 FCGI_stdin->fcgx_stream = in;
154 FCGI_stdout->stdio_stream = NULL;
155 FCGI_stdout->fcgx_stream = out;
156 FCGI_stderr->stdio_stream = NULL;
157 FCGI_stderr->fcgx_stream = error;
164 *----------------------------------------------------------------------
168 * Finishes the current request from the HTTP server.
172 * Flushes any buffered output to the HTTP server. Then frees
173 * all storage allocated by the previous call, including all
174 * storage reachable from the value of environ set by the previous
175 * call to FCGI_Accept.
177 * DO NOT use stdin, stdout, stderr, or environ between calling
178 * FCGI_Finish and calling FCGI_Accept.
180 * DO NOT mutate or retain pointers to environ or any values
181 * contained in it (e.g. to the result of calling getenv(3)),
182 * since these are freed by the next call to FCGI_Finish or
183 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
184 * in conjunction with FCGI_Accept.
186 *----------------------------------------------------------------------
188 void FCGI_Finish(void)
190 if(!acceptCalled || isCGI) {
194 FCGI_stdin->fcgx_stream = NULL;
195 FCGI_stdout->fcgx_stream = NULL;
196 FCGI_stderr->fcgx_stream = NULL;
201 *----------------------------------------------------------------------
203 * FCGI_StartFilterData --
206 * The current request is for the filter role, and stdin is
207 * positioned at EOF of FCGI_STDIN. The call repositions
208 * stdin to the start of FCGI_DATA.
209 * If the preconditions are not met (e.g. FCGI_STDIN has not
210 * been read to EOF), the call sets the stream error code to
211 * FCGX_CALL_SEQ_ERROR.
214 * 0 for a normal return, < 0 for error
216 *----------------------------------------------------------------------
219 int FCGI_StartFilterData(void)
221 if(FCGI_stdin->stdio_stream) {
224 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
229 *----------------------------------------------------------------------
231 * FCGI_SetExitStatus --
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
240 *----------------------------------------------------------------------
243 void FCGI_SetExitStatus(int status)
245 if(FCGI_stdin->fcgx_stream) {
246 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
251 *----------------------------------------------------------------------
255 * Wrapper for function defined in H&S Section 11.2
257 *----------------------------------------------------------------------
260 void FCGI_perror(const char *str)
262 FCGI_fputs(str, FCGI_stderr);
263 FCGI_fputs(": ", FCGI_stderr);
264 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
269 *----------------------------------------------------------------------
271 * FCGI_OpenFromFILE --
273 * Constructs a new FCGI_FILE * from the FILE *stream.
276 * NULL if stream == NULL or storage could not be allocated,
277 * otherwise the new FCGI_FILE *.
279 *----------------------------------------------------------------------
282 static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
289 fp = (FCGI_FILE *) malloc(sizeof(FCGI_FILE));
292 fp->stdio_stream = stream;
293 fp->fcgx_stream = NULL;
300 *----------------------------------------------------------------------
302 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
304 * Wrappers for functions defined in H&S Section 15.2
306 *----------------------------------------------------------------------
309 FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
311 FILE * file = fopen(path, mode);
312 FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file);
314 if (file && !fcgi_file)
320 int FCGI_fclose(FCGI_FILE *fp)
323 if(fp->stdio_stream) {
324 n = fclose(fp->stdio_stream);
325 fp->stdio_stream = NULL;
326 } else if(fp->fcgx_stream) {
327 n = FCGX_FClose(fp->fcgx_stream);
328 fp->fcgx_stream = NULL;
330 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
336 int FCGI_fflush(FCGI_FILE *fp)
341 return fflush(fp->stdio_stream);
342 else if(fp->fcgx_stream)
343 return FCGX_FFlush(fp->fcgx_stream);
347 FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
350 if(fp->stdio_stream) {
351 if(freopen(path, mode, fp->stdio_stream) == NULL)
355 } else if(fp->fcgx_stream) {
356 (void) FCGX_FClose(fp->fcgx_stream);
357 fp->stdio_stream = fopen(path, mode);
358 if(fp->stdio_stream == NULL)
361 fp->fcgx_stream = NULL;
369 *----------------------------------------------------------------------
371 * FCGI_setvbuf, FCGI_setbuf --
373 * Wrappers for functions defined in H&S Section 15.3
375 *----------------------------------------------------------------------
377 int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
380 return setvbuf(fp->stdio_stream, buf, bufmode, size);
386 void FCGI_setbuf(FCGI_FILE *fp, char *buf)
389 setbuf(fp->stdio_stream, buf);
393 *----------------------------------------------------------------------
395 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
397 * Wrappers for functions defined in H&S Section 15.5
399 *----------------------------------------------------------------------
402 int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
405 return fseek(fp->stdio_stream, offset, whence);
412 int FCGI_ftell(FCGI_FILE *fp)
415 return ftell(fp->stdio_stream);
422 void FCGI_rewind(FCGI_FILE *fp)
425 rewind(fp->stdio_stream);
431 int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
434 return fgetpos(fp->stdio_stream, pos);
441 int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
444 return fsetpos(fp->stdio_stream, pos);
453 *----------------------------------------------------------------------
455 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
457 * Wrappers for functions defined in H&S Section 15.6
459 * XXX: getc and getchar are generally defined as macros
460 * for performance reasons
462 *----------------------------------------------------------------------
465 int FCGI_fgetc(FCGI_FILE *fp)
468 return fgetc(fp->stdio_stream);
469 else if(fp->fcgx_stream)
470 return FCGX_GetChar(fp->fcgx_stream);
474 int FCGI_getchar(void)
476 return FCGI_fgetc(FCGI_stdin);
479 int FCGI_ungetc(int c, FCGI_FILE *fp)
482 return ungetc(c, fp->stdio_stream);
483 else if(fp->fcgx_stream)
484 return FCGX_UnGetChar(c, fp->fcgx_stream);
489 *----------------------------------------------------------------------
491 * FCGI_fgets, FCGI_gets --
493 * Wrappers for functions defined in H&S Section 15.7
495 *----------------------------------------------------------------------
498 char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
501 return fgets(str, size, fp->stdio_stream);
502 else if(fp->fcgx_stream)
503 return FCGX_GetLine(str, size, fp->fcgx_stream);
508 * There is no standard equivalent of gets that takes an explicit
509 * FILE * argument, so the following "wrapper" implements
510 * gets for both FILE * and FCGX_Stream * in terms of FCGI_getchar.
513 char *FCGI_gets(char *str)
517 for (s = str; ((c = FCGI_getchar()) != '\n');) {
531 *----------------------------------------------------------------------
535 * Wrappers for functions defined in H&S Section 15.8
537 * XXX: missing: fscanf, scanf
539 *----------------------------------------------------------------------
544 *----------------------------------------------------------------------
546 * FCGI_fputc, FCGI_putchar --
548 * Wrappers for functions defined in H&S Section 15.9
550 * XXX: putc and putchar are generally defined as macros
551 * for performance reasons
553 *----------------------------------------------------------------------
556 int FCGI_fputc(int c, FCGI_FILE *fp)
559 return fputc(c, fp->stdio_stream);
560 else if(fp->fcgx_stream)
561 return FCGX_PutChar(c, fp->fcgx_stream);
565 int FCGI_putchar(int c)
567 return FCGI_fputc(c, FCGI_stdout);
571 *----------------------------------------------------------------------
573 * FCGI_fputs, FCGI_puts
575 * Wrappers for functions defined in H&S Section 15.10
577 *----------------------------------------------------------------------
580 int FCGI_fputs(const char *str, FCGI_FILE *fp)
583 return fputs(str, fp->stdio_stream);
584 else if(fp->fcgx_stream)
585 return FCGX_PutS(str, fp->fcgx_stream);
589 int FCGI_puts(const char *str)
592 if(FCGI_stdout->stdio_stream) {
593 n = fputs(str, FCGI_stdout->stdio_stream);
597 return fputc('\n', FCGI_stdout->stdio_stream);
598 } else if(FCGI_stdout->fcgx_stream) {
599 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
603 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
609 *----------------------------------------------------------------------
611 * FCGI_fprintf, FCGI_printf --
613 * Wrappers for functions defined in H&S Section 15.11
615 *----------------------------------------------------------------------
618 int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
622 va_start(ap, format);
624 n = vfprintf(fp->stdio_stream, format, ap);
625 else if(fp->fcgx_stream)
626 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
631 int FCGI_printf(const char *format, ...)
635 va_start(ap, format);
636 n = FCGI_vfprintf(FCGI_stdout, format, ap);
642 *----------------------------------------------------------------------
644 * FCGI_vfprintf, FCGI_vprintf --
646 * Wrappers for functions defined in H&S Section 15.12
648 *----------------------------------------------------------------------
651 int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
654 return vfprintf(fp->stdio_stream, format, ap);
655 else if(fp->fcgx_stream)
656 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
660 int FCGI_vprintf(const char *format, va_list ap)
662 if(FCGI_stdout->stdio_stream)
663 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
664 else if(FCGI_stdout->fcgx_stream)
665 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
670 *----------------------------------------------------------------------
672 * FCGI_fread, FCGI_fwrite --
674 * Wrappers for functions defined in H&S Section 15.13
676 *----------------------------------------------------------------------
679 size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
683 return fread(ptr, size, nmemb, fp->stdio_stream);
684 else if(fp->fcgx_stream) {
685 if((size * nmemb) == 0) {
688 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
694 size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
698 return fwrite(ptr, size, nmemb, fp->stdio_stream);
699 else if(fp->fcgx_stream) {
700 if((size * nmemb) == 0) {
703 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
710 *----------------------------------------------------------------------
712 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
714 * Wrappers for functions defined in H&S Section 15.14
716 *----------------------------------------------------------------------
718 int FCGI_feof(FCGI_FILE *fp)
720 if(fp->stdio_stream) {
721 return feof(fp->stdio_stream);
722 } else if (fp->fcgx_stream){
723 return FCGX_HasSeenEOF(fp->fcgx_stream);
729 int FCGI_ferror(FCGI_FILE *fp)
731 if(fp->stdio_stream) {
732 return ferror(fp->stdio_stream);
733 } else if(fp->fcgx_stream) {
734 return FCGX_GetError(fp->fcgx_stream);
739 void FCGI_clearerr(FCGI_FILE *fp)
741 if(fp->stdio_stream) {
742 clearerr(fp->stdio_stream);
743 } else if(fp->fcgx_stream) {
744 FCGX_ClearError(fp->fcgx_stream);
750 *----------------------------------------------------------------------
754 * Wrappers for function defined in H&S Section 15.16
756 *----------------------------------------------------------------------
758 FCGI_FILE *FCGI_tmpfile(void)
760 FILE * file = tmpfile();
761 FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file);
763 if (file && !fcgi_file)
771 *----------------------------------------------------------------------
773 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
775 * Wrappers for POSIX, X/OPEN functions not in ISO C
777 *----------------------------------------------------------------------
780 int FCGI_fileno(FCGI_FILE *fp)
783 return fileno(fp->stdio_stream);
788 FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
790 FILE * file = fdopen(fd, mode);
791 FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file);
793 if (file && !fcgi_file)
799 FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
801 FILE * file = popen(cmd, type);
802 FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file);
804 if (file && !fcgi_file)
810 int FCGI_pclose(FCGI_FILE *fp)
813 if (fp->stdio_stream) {
814 n = pclose(fp->stdio_stream);
815 fp->stdio_stream = NULL;
816 } else if(fp->fcgx_stream) {
818 * The caller is deeply confused; don't free the storage.
822 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
829 *----------------------------------------------------------------------