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.8 1999/07/28 00:24:15 roberts 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);
69 FCGI_FILE _fcgi_sF[3];
73 *----------------------------------------------------------------------
77 * Accepts a new request from the HTTP server and creates
78 * a conventional execution environment for the request.
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.
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).
92 * 0 for successful call, -1 for error (application should exit).
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.
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.
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.
115 *----------------------------------------------------------------------
117 static int acceptCalled = FALSE;
118 static int isCGI = FALSE;
120 int FCGI_Accept(void)
124 * First call to FCGI_Accept. Is application running
125 * as FastCGI or as CGI?
127 isCGI = FCGX_IsCGI();
129 atexit(&FCGI_Finish);
132 * Not first call to FCGI_Accept and running as CGI means
133 * application is done.
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;
145 FCGX_Stream *in, *out, *error;
146 FCGX_ParamArray envp;
147 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
148 if(acceptResult < 0) {
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;
163 *----------------------------------------------------------------------
167 * Finishes the current request from the HTTP server.
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.
176 * DO NOT use stdin, stdout, stderr, or environ between calling
177 * FCGI_Finish and calling FCGI_Accept.
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.
185 *----------------------------------------------------------------------
187 void FCGI_Finish(void)
189 if(!acceptCalled || isCGI) {
193 FCGI_stdin->fcgx_stream = NULL;
194 FCGI_stdout->fcgx_stream = NULL;
195 FCGI_stderr->fcgx_stream = NULL;
200 *----------------------------------------------------------------------
202 * FCGI_StartFilterData --
205 * The current request is for the filter role, and stdin is
206 * positioned at EOF of FCGI_STDIN. The call repositions
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.
213 * 0 for a normal return, < 0 for error
215 *----------------------------------------------------------------------
218 int FCGI_StartFilterData(void)
220 if(FCGI_stdin->stdio_stream) {
223 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
228 *----------------------------------------------------------------------
230 * FCGI_SetExitStatus --
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
239 *----------------------------------------------------------------------
242 void FCGI_SetExitStatus(int status)
244 if(FCGI_stdin->fcgx_stream) {
245 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
250 *----------------------------------------------------------------------
254 * Wrapper for function defined in H&S Section 11.2
256 *----------------------------------------------------------------------
259 void FCGI_perror(const char *str)
261 FCGI_fputs(str, FCGI_stderr);
262 FCGI_fputs(": ", FCGI_stderr);
263 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
268 *----------------------------------------------------------------------
270 * FCGI_OpenFromFILE --
272 * Constructs a new FCGI_FILE * from the FILE *stream.
275 * NULL if stream == NULL or storage could not be allocated,
276 * otherwise the new FCGI_FILE *.
278 *----------------------------------------------------------------------
281 static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
286 fp = (FCGI_FILE *)malloc(sizeof(FCGI_FILE));
289 fp->stdio_stream = stream;
290 fp->fcgx_stream = NULL;
295 *----------------------------------------------------------------------
297 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
299 * Wrappers for functions defined in H&S Section 15.2
301 *----------------------------------------------------------------------
304 FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
306 return FCGI_OpenFromFILE(fopen(path, mode));
309 int FCGI_fclose(FCGI_FILE *fp)
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;
319 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
325 int FCGI_fflush(FCGI_FILE *fp)
330 return fflush(fp->stdio_stream);
331 else if(fp->fcgx_stream)
332 return FCGX_FFlush(fp->fcgx_stream);
336 FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
339 if(fp->stdio_stream) {
340 if(freopen(path, mode, fp->stdio_stream) == NULL)
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)
350 fp->fcgx_stream = NULL;
358 *----------------------------------------------------------------------
360 * FCGI_setvbuf, FCGI_setbuf --
362 * Wrappers for functions defined in H&S Section 15.3
364 *----------------------------------------------------------------------
366 int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
369 return setvbuf(fp->stdio_stream, buf, bufmode, size);
375 void FCGI_setbuf(FCGI_FILE *fp, char *buf)
378 setbuf(fp->stdio_stream, buf);
382 *----------------------------------------------------------------------
384 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
386 * Wrappers for functions defined in H&S Section 15.5
388 *----------------------------------------------------------------------
391 int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
394 return fseek(fp->stdio_stream, offset, whence);
401 int FCGI_ftell(FCGI_FILE *fp)
404 return ftell(fp->stdio_stream);
411 void FCGI_rewind(FCGI_FILE *fp)
414 rewind(fp->stdio_stream);
420 int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
423 return fgetpos(fp->stdio_stream, pos);
430 int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
433 return fsetpos(fp->stdio_stream, pos);
442 *----------------------------------------------------------------------
444 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
446 * Wrappers for functions defined in H&S Section 15.6
448 * XXX: getc and getchar are generally defined as macros
449 * for performance reasons
451 *----------------------------------------------------------------------
454 int FCGI_fgetc(FCGI_FILE *fp)
457 return fgetc(fp->stdio_stream);
458 else if(fp->fcgx_stream)
459 return FCGX_GetChar(fp->fcgx_stream);
463 int FCGI_getchar(void)
465 return FCGI_fgetc(FCGI_stdin);
468 int FCGI_ungetc(int c, FCGI_FILE *fp)
471 return ungetc(c, fp->stdio_stream);
472 else if(fp->fcgx_stream)
473 return FCGX_UnGetChar(c, fp->fcgx_stream);
478 *----------------------------------------------------------------------
480 * FCGI_fgets, FCGI_gets --
482 * Wrappers for functions defined in H&S Section 15.7
484 *----------------------------------------------------------------------
487 char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
490 return fgets(str, size, fp->stdio_stream);
491 else if(fp->fcgx_stream)
492 return FCGX_GetLine(str, size, fp->fcgx_stream);
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.
502 char *FCGI_gets(char *str)
506 for (s = str; ((c = FCGI_getchar()) != '\n');) {
520 *----------------------------------------------------------------------
524 * Wrappers for functions defined in H&S Section 15.8
526 * XXX: missing: fscanf, scanf
528 *----------------------------------------------------------------------
533 *----------------------------------------------------------------------
535 * FCGI_fputc, FCGI_putchar --
537 * Wrappers for functions defined in H&S Section 15.9
539 * XXX: putc and putchar are generally defined as macros
540 * for performance reasons
542 *----------------------------------------------------------------------
545 int FCGI_fputc(int c, FCGI_FILE *fp)
548 return fputc(c, fp->stdio_stream);
549 else if(fp->fcgx_stream)
550 return FCGX_PutChar(c, fp->fcgx_stream);
554 int FCGI_putchar(int c)
556 return FCGI_fputc(c, FCGI_stdout);
560 *----------------------------------------------------------------------
562 * FCGI_fputs, FCGI_puts
564 * Wrappers for functions defined in H&S Section 15.10
566 *----------------------------------------------------------------------
569 int FCGI_fputs(const char *str, FCGI_FILE *fp)
572 return fputs(str, fp->stdio_stream);
573 else if(fp->fcgx_stream)
574 return FCGX_PutS(str, fp->fcgx_stream);
578 int FCGI_puts(const char *str)
581 if(FCGI_stdout->stdio_stream) {
582 n = fputs(str, FCGI_stdout->stdio_stream);
586 return fputc('\n', FCGI_stdout->stdio_stream);
587 } else if(FCGI_stdout->fcgx_stream) {
588 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
592 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
598 *----------------------------------------------------------------------
600 * FCGI_fprintf, FCGI_printf --
602 * Wrappers for functions defined in H&S Section 15.11
604 *----------------------------------------------------------------------
607 int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
611 va_start(ap, format);
613 n = vfprintf(fp->stdio_stream, format, ap);
614 else if(fp->fcgx_stream)
615 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
620 int FCGI_printf(const char *format, ...)
624 va_start(ap, format);
625 n = FCGI_vfprintf(FCGI_stdout, format, ap);
631 *----------------------------------------------------------------------
633 * FCGI_vfprintf, FCGI_vprintf --
635 * Wrappers for functions defined in H&S Section 15.12
637 *----------------------------------------------------------------------
640 int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
643 return vfprintf(fp->stdio_stream, format, ap);
644 else if(fp->fcgx_stream)
645 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
649 int FCGI_vprintf(const char *format, va_list ap)
651 if(FCGI_stdout->stdio_stream)
652 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
653 else if(FCGI_stdout->fcgx_stream)
654 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
659 *----------------------------------------------------------------------
661 * FCGI_fread, FCGI_fwrite --
663 * Wrappers for functions defined in H&S Section 15.13
665 *----------------------------------------------------------------------
668 size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
672 return fread(ptr, size, nmemb, fp->stdio_stream);
673 else if(fp->fcgx_stream) {
674 if((size * nmemb) == 0) {
677 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
683 size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
687 return fwrite(ptr, size, nmemb, fp->stdio_stream);
688 else if(fp->fcgx_stream) {
689 if((size * nmemb) == 0) {
692 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
699 *----------------------------------------------------------------------
701 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
703 * Wrappers for functions defined in H&S Section 15.14
705 *----------------------------------------------------------------------
707 int FCGI_feof(FCGI_FILE *fp)
709 if(fp->stdio_stream) {
710 return feof(fp->stdio_stream);
711 } else if (fp->fcgx_stream){
712 return FCGX_HasSeenEOF(fp->fcgx_stream);
718 int FCGI_ferror(FCGI_FILE *fp)
720 if(fp->stdio_stream) {
721 return ferror(fp->stdio_stream);
722 } else if(fp->fcgx_stream) {
723 return FCGX_GetError(fp->fcgx_stream);
728 void FCGI_clearerr(FCGI_FILE *fp)
730 if(fp->stdio_stream) {
731 clearerr(fp->stdio_stream);
732 } else if(fp->fcgx_stream) {
733 FCGX_ClearError(fp->fcgx_stream);
739 *----------------------------------------------------------------------
743 * Wrappers for function defined in H&S Section 15.16
745 *----------------------------------------------------------------------
747 FCGI_FILE *FCGI_tmpfile(void)
749 return FCGI_OpenFromFILE(tmpfile());
754 *----------------------------------------------------------------------
756 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
758 * Wrappers for POSIX, X/OPEN functions not in ISO C
760 *----------------------------------------------------------------------
763 int FCGI_fileno(FCGI_FILE *fp)
766 return fileno(fp->stdio_stream);
771 FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
774 return FCGI_OpenFromFILE(fdopen(fd, mode));
780 FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
782 return FCGI_OpenFromFILE(popen(cmd, type));
785 int FCGI_pclose(FCGI_FILE *fp)
788 if(fp->stdio_stream) {
790 n = pclose(fp->stdio_stream);
792 fp->stdio_stream = NULL;
793 } else if(fp->fcgx_stream) {
795 * The caller is deeply confused; don't free the storage.
799 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
806 *----------------------------------------------------------------------