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.6 1999/06/07 05:39:03 roberts Exp $";
19 #define DLLAPI __declspec(dllexport)
22 #define NO_FCGI_DEFINES
23 #include "fcgi_stdio.h"
24 #undef NO_FCGI_DEFINES
51 FCGI_FILE _fcgi_sF[3];
58 *----------------------------------------------------------------------
62 * Accepts a new request from the HTTP server and creates
63 * a conventional execution environment for the request.
65 * If the application was invoked as a FastCGI server,
66 * the first call to FCGI_Accept indicates that the application
67 * has completed its initialization and is ready to accept
68 * a request. Subsequent calls to FCGI_Accept indicate that
69 * the application has completed its processing of the
70 * current request and is ready to accept a new request.
72 * If the application was invoked as a CGI program, the first
73 * call to FCGI_Accept is essentially a no-op and the second
74 * call returns EOF (-1).
77 * 0 for successful call, -1 for error (application should exit).
80 * If the application was invoked as a FastCGI server,
81 * and this is not the first call to this procedure,
82 * FCGI_Accept first performs the equivalent of FCGI_Finish.
84 * On every call, FCGI_Accept accepts the new request and
85 * reads the FCGI_PARAMS stream into an environment array,
86 * i.e. a NULL-terminated array of strings of the form
87 * ``name=value''. It assigns a pointer to this array
88 * to the global variable environ, used by the standard
89 * library function getenv. It creates new FCGI_FILE *s
90 * representing input from the HTTP server, output to the HTTP
91 * server, and error output to the HTTP server, and assigns these
92 * new files to stdin, stdout, and stderr respectively.
94 * DO NOT mutate or retain pointers to environ or any values
95 * contained in it (e.g. to the result of calling getenv(3)),
96 * since these are freed by the next call to FCGI_Finish or
97 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
98 * in conjunction with FCGI_Accept.
100 *----------------------------------------------------------------------
102 static int acceptCalled = FALSE;
103 static int isCGI = FALSE;
105 extern char **environ;
108 int FCGI_Accept(void)
112 * First call to FCGI_Accept. Is application running
113 * as FastCGI or as CGI?
115 isCGI = FCGX_IsCGI();
117 atexit(&FCGI_Finish);
120 * Not first call to FCGI_Accept and running as CGI means
121 * application is done.
126 FCGI_stdin->stdio_stream = stdin;
127 FCGI_stdin->fcgx_stream = NULL;
128 FCGI_stdout->stdio_stream = stdout;
129 FCGI_stdout->fcgx_stream = NULL;
130 FCGI_stderr->stdio_stream = stderr;
131 FCGI_stderr->fcgx_stream = NULL;
133 FCGX_Stream *in, *out, *error;
134 FCGX_ParamArray envp;
135 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
136 if(acceptResult < 0) {
139 FCGI_stdin->stdio_stream = NULL;
140 FCGI_stdin->fcgx_stream = in;
141 FCGI_stdout->stdio_stream = NULL;
142 FCGI_stdout->fcgx_stream = out;
143 FCGI_stderr->stdio_stream = NULL;
144 FCGI_stderr->fcgx_stream = error;
151 *----------------------------------------------------------------------
155 * Finishes the current request from the HTTP server.
159 * Flushes any buffered output to the HTTP server. Then frees
160 * all storage allocated by the previous call, including all
161 * storage reachable from the value of environ set by the previous
162 * call to FCGI_Accept.
164 * DO NOT use stdin, stdout, stderr, or environ between calling
165 * FCGI_Finish and calling FCGI_Accept.
167 * DO NOT mutate or retain pointers to environ or any values
168 * contained in it (e.g. to the result of calling getenv(3)),
169 * since these are freed by the next call to FCGI_Finish or
170 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
171 * in conjunction with FCGI_Accept.
173 *----------------------------------------------------------------------
175 void FCGI_Finish(void)
177 if(!acceptCalled || isCGI) {
181 FCGI_stdin->fcgx_stream = NULL;
182 FCGI_stdout->fcgx_stream = NULL;
183 FCGI_stderr->fcgx_stream = NULL;
188 *----------------------------------------------------------------------
190 * FCGI_StartFilterData --
193 * The current request is for the filter role, and stdin is
194 * positioned at EOF of FCGI_STDIN. The call repositions
195 * stdin to the start of FCGI_DATA.
196 * If the preconditions are not met (e.g. FCGI_STDIN has not
197 * been read to EOF), the call sets the stream error code to
198 * FCGX_CALL_SEQ_ERROR.
201 * 0 for a normal return, < 0 for error
203 *----------------------------------------------------------------------
206 int FCGI_StartFilterData(void)
208 if(FCGI_stdin->stdio_stream) {
211 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
216 *----------------------------------------------------------------------
218 * FCGI_SetExitStatus --
220 * Sets the exit status for the current request. The exit status
221 * is the status code the request would have exited with, had
222 * the request been run as a CGI program. You can call
223 * FCGI_SetExitStatus several times during a request; the last call
224 * before the request ends (by calling FCGI_Accept) determines the
227 *----------------------------------------------------------------------
230 void FCGI_SetExitStatus(int status)
232 if(FCGI_stdin->fcgx_stream) {
233 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
238 *----------------------------------------------------------------------
242 * Wrapper for function defined in H&S Section 11.2
244 *----------------------------------------------------------------------
247 void FCGI_perror(const char *str)
249 FCGI_fputs(str, FCGI_stderr);
250 FCGI_fputs(": ", FCGI_stderr);
251 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
256 *----------------------------------------------------------------------
258 * FCGI_OpenFromFILE --
260 * Constructs a new FCGI_FILE * from the FILE *stream.
263 * NULL if stream == NULL or storage could not be allocated,
264 * otherwise the new FCGI_FILE *.
266 *----------------------------------------------------------------------
269 static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
274 fp = malloc(sizeof(FCGI_FILE));
277 fp->stdio_stream = stream;
278 fp->fcgx_stream = NULL;
283 *----------------------------------------------------------------------
285 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
287 * Wrappers for functions defined in H&S Section 15.2
289 *----------------------------------------------------------------------
292 FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
294 return FCGI_OpenFromFILE(fopen(path, mode));
297 int FCGI_fclose(FCGI_FILE *fp)
300 if(fp->stdio_stream) {
301 n = fclose(fp->stdio_stream);
302 fp->stdio_stream = NULL;
303 } else if(fp->fcgx_stream) {
304 n = FCGX_FClose(fp->fcgx_stream);
305 fp->fcgx_stream = NULL;
307 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
313 int FCGI_fflush(FCGI_FILE *fp)
318 return fflush(fp->stdio_stream);
319 else if(fp->fcgx_stream)
320 return FCGX_FFlush(fp->fcgx_stream);
324 FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
327 if(fp->stdio_stream) {
328 if(freopen(path, mode, fp->stdio_stream) == NULL)
332 } else if(fp->fcgx_stream) {
333 (void) FCGX_FClose(fp->fcgx_stream);
334 fp->stdio_stream = fopen(path, mode);
335 if(fp->stdio_stream == NULL)
338 fp->fcgx_stream = NULL;
346 *----------------------------------------------------------------------
348 * FCGI_setvbuf, FCGI_setbuf --
350 * Wrappers for functions defined in H&S Section 15.3
352 *----------------------------------------------------------------------
354 int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
357 return setvbuf(fp->stdio_stream, buf, bufmode, size);
363 void FCGI_setbuf(FCGI_FILE *fp, char *buf)
366 setbuf(fp->stdio_stream, buf);
370 *----------------------------------------------------------------------
372 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
374 * Wrappers for functions defined in H&S Section 15.5
376 *----------------------------------------------------------------------
379 int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
382 return fseek(fp->stdio_stream, offset, whence);
389 int FCGI_ftell(FCGI_FILE *fp)
392 return ftell(fp->stdio_stream);
399 void FCGI_rewind(FCGI_FILE *fp)
402 rewind(fp->stdio_stream);
408 int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
411 return fgetpos(fp->stdio_stream, pos);
418 int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
421 return fsetpos(fp->stdio_stream, pos);
430 *----------------------------------------------------------------------
432 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
434 * Wrappers for functions defined in H&S Section 15.6
436 * XXX: getc and getchar are generally defined as macros
437 * for performance reasons
439 *----------------------------------------------------------------------
442 int FCGI_fgetc(FCGI_FILE *fp)
445 return fgetc(fp->stdio_stream);
446 else if(fp->fcgx_stream)
447 return FCGX_GetChar(fp->fcgx_stream);
451 int FCGI_getchar(void)
453 return FCGI_fgetc(FCGI_stdin);
456 int FCGI_ungetc(int c, FCGI_FILE *fp)
459 return ungetc(c, fp->stdio_stream);
460 else if(fp->fcgx_stream)
461 return FCGX_UnGetChar(c, fp->fcgx_stream);
466 *----------------------------------------------------------------------
468 * FCGI_fgets, FCGI_gets --
470 * Wrappers for functions defined in H&S Section 15.7
472 *----------------------------------------------------------------------
475 char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
478 return fgets(str, size, fp->stdio_stream);
479 else if(fp->fcgx_stream)
480 return FCGX_GetLine(str, size, fp->fcgx_stream);
485 * There is no standard equivalent of gets that takes an explicit
486 * FILE * argument, so the following "wrapper" implements
487 * gets for both FILE * and FCGX_Stream * in terms of FCGI_getchar.
490 char *FCGI_gets(char *str)
494 for (s = str; ((c = FCGI_getchar()) != '\n');) {
508 *----------------------------------------------------------------------
512 * Wrappers for functions defined in H&S Section 15.8
514 * XXX: missing: fscanf, scanf
516 *----------------------------------------------------------------------
521 *----------------------------------------------------------------------
523 * FCGI_fputc, FCGI_putchar --
525 * Wrappers for functions defined in H&S Section 15.9
527 * XXX: putc and putchar are generally defined as macros
528 * for performance reasons
530 *----------------------------------------------------------------------
533 int FCGI_fputc(int c, FCGI_FILE *fp)
536 return fputc(c, fp->stdio_stream);
537 else if(fp->fcgx_stream)
538 return FCGX_PutChar(c, fp->fcgx_stream);
542 int FCGI_putchar(int c)
544 return FCGI_fputc(c, FCGI_stdout);
548 *----------------------------------------------------------------------
550 * FCGI_fputs, FCGI_puts
552 * Wrappers for functions defined in H&S Section 15.10
554 *----------------------------------------------------------------------
557 int FCGI_fputs(const char *str, FCGI_FILE *fp)
560 return fputs(str, fp->stdio_stream);
561 else if(fp->fcgx_stream)
562 return FCGX_PutS(str, fp->fcgx_stream);
566 int FCGI_puts(const char *str)
569 if(FCGI_stdout->stdio_stream) {
570 n = fputs(str, FCGI_stdout->stdio_stream);
574 return fputc('\n', FCGI_stdout->stdio_stream);
575 } else if(FCGI_stdout->fcgx_stream) {
576 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
580 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
586 *----------------------------------------------------------------------
588 * FCGI_fprintf, FCGI_printf --
590 * Wrappers for functions defined in H&S Section 15.11
592 *----------------------------------------------------------------------
595 int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
599 va_start(ap, format);
601 n = vfprintf(fp->stdio_stream, format, ap);
602 else if(fp->fcgx_stream)
603 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
608 int FCGI_printf(const char *format, ...)
612 va_start(ap, format);
613 n = FCGI_vfprintf(FCGI_stdout, format, ap);
619 *----------------------------------------------------------------------
621 * FCGI_vfprintf, FCGI_vprintf --
623 * Wrappers for functions defined in H&S Section 15.12
625 *----------------------------------------------------------------------
628 int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
631 return vfprintf(fp->stdio_stream, format, ap);
632 else if(fp->fcgx_stream)
633 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
637 int FCGI_vprintf(const char *format, va_list ap)
639 if(FCGI_stdout->stdio_stream)
640 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
641 else if(FCGI_stdout->fcgx_stream)
642 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
647 *----------------------------------------------------------------------
649 * FCGI_fread, FCGI_fwrite --
651 * Wrappers for functions defined in H&S Section 15.13
653 *----------------------------------------------------------------------
656 size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
660 return fread(ptr, size, nmemb, fp->stdio_stream);
661 else if(fp->fcgx_stream) {
662 if((size * nmemb) == 0) {
665 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
671 size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
675 return fwrite(ptr, size, nmemb, fp->stdio_stream);
676 else if(fp->fcgx_stream) {
677 if((size * nmemb) == 0) {
680 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
687 *----------------------------------------------------------------------
689 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
691 * Wrappers for functions defined in H&S Section 15.14
693 *----------------------------------------------------------------------
695 int FCGI_feof(FCGI_FILE *fp)
697 if(fp->stdio_stream) {
698 return feof(fp->stdio_stream);
699 } else if (fp->fcgx_stream){
700 return FCGX_HasSeenEOF(fp->fcgx_stream);
706 int FCGI_ferror(FCGI_FILE *fp)
708 if(fp->stdio_stream) {
709 return ferror(fp->stdio_stream);
710 } else if(fp->fcgx_stream) {
711 return FCGX_GetError(fp->fcgx_stream);
716 void FCGI_clearerr(FCGI_FILE *fp)
718 if(fp->stdio_stream) {
719 clearerr(fp->stdio_stream);
720 } else if(fp->fcgx_stream) {
721 FCGX_ClearError(fp->fcgx_stream);
727 *----------------------------------------------------------------------
731 * Wrappers for function defined in H&S Section 15.16
733 *----------------------------------------------------------------------
735 FCGI_FILE *FCGI_tmpfile(void)
737 return FCGI_OpenFromFILE(tmpfile());
742 *----------------------------------------------------------------------
744 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
746 * Wrappers for POSIX, X/OPEN functions not in ISO C
748 *----------------------------------------------------------------------
752 * These definitions should be supplied by stdio.h but for some
753 * reason they get lost on certain platforms.
756 * XXX: Need to find the right way to handle this for NT
760 extern int fileno(FILE *stream);
762 extern FILE *fdopen(int fildes, const char *type);
763 extern FILE *popen(const char *command, const char *type);
764 extern int pclose(FILE *stream);
767 int FCGI_fileno(FCGI_FILE *fp)
770 return fileno(fp->stdio_stream);
775 FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
778 return FCGI_OpenFromFILE(fdopen(fd, mode));
784 FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
786 return FCGI_OpenFromFILE(popen(cmd, type));
789 int FCGI_pclose(FCGI_FILE *fp)
792 if(fp->stdio_stream) {
794 n = pclose(fp->stdio_stream);
796 fp->stdio_stream = NULL;
797 } else if(fp->fcgx_stream) {
799 * The caller is deeply confused; don't free the storage.
803 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
810 *----------------------------------------------------------------------