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.5 1999/06/07 05:03:48 roberts Exp $";
19 #define DLLAPI __declspec(dllexport)
22 #define NO_FCGI_DEFINES
23 #include "fcgi_stdio.h"
24 #undef NO_FCGI_DEFINES
52 FCGI_FILE _fcgi_sF[3];
54 FCGI_FILE _fcgi_sF[3] = {{stdin, NULL}, {stdout, NULL}, {stderr, NULL}};
62 *----------------------------------------------------------------------
66 * Accepts a new request from the HTTP server and creates
67 * a conventional execution environment for the request.
69 * If the application was invoked as a FastCGI server,
70 * the first call to FCGI_Accept indicates that the application
71 * has completed its initialization and is ready to accept
72 * a request. Subsequent calls to FCGI_Accept indicate that
73 * the application has completed its processing of the
74 * current request and is ready to accept a new request.
76 * If the application was invoked as a CGI program, the first
77 * call to FCGI_Accept is essentially a no-op and the second
78 * call returns EOF (-1).
81 * 0 for successful call, -1 for error (application should exit).
84 * If the application was invoked as a FastCGI server,
85 * and this is not the first call to this procedure,
86 * FCGI_Accept first performs the equivalent of FCGI_Finish.
88 * On every call, FCGI_Accept accepts the new request and
89 * reads the FCGI_PARAMS stream into an environment array,
90 * i.e. a NULL-terminated array of strings of the form
91 * ``name=value''. It assigns a pointer to this array
92 * to the global variable environ, used by the standard
93 * library function getenv. It creates new FCGI_FILE *s
94 * representing input from the HTTP server, output to the HTTP
95 * server, and error output to the HTTP server, and assigns these
96 * new files to stdin, stdout, and stderr respectively.
98 * DO NOT mutate or retain pointers to environ or any values
99 * contained in it (e.g. to the result of calling getenv(3)),
100 * since these are freed by the next call to FCGI_Finish or
101 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
102 * in conjunction with FCGI_Accept.
104 *----------------------------------------------------------------------
106 static int acceptCalled = FALSE;
107 static int isCGI = FALSE;
109 extern char **environ;
112 int FCGI_Accept(void)
116 * First call to FCGI_Accept. Is application running
117 * as FastCGI or as CGI?
119 isCGI = FCGX_IsCGI();
121 atexit(&FCGI_Finish);
124 * Not first call to FCGI_Accept and running as CGI means
125 * application is done.
130 FCGI_stdin->stdio_stream = stdin;
131 FCGI_stdin->fcgx_stream = NULL;
132 FCGI_stdout->stdio_stream = stdout;
133 FCGI_stdout->fcgx_stream = NULL;
134 FCGI_stderr->stdio_stream = stderr;
135 FCGI_stderr->fcgx_stream = NULL;
137 FCGX_Stream *in, *out, *error;
138 FCGX_ParamArray envp;
139 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
140 if(acceptResult < 0) {
143 FCGI_stdin->stdio_stream = NULL;
144 FCGI_stdin->fcgx_stream = in;
145 FCGI_stdout->stdio_stream = NULL;
146 FCGI_stdout->fcgx_stream = out;
147 FCGI_stderr->stdio_stream = NULL;
148 FCGI_stderr->fcgx_stream = error;
155 *----------------------------------------------------------------------
159 * Finishes the current request from the HTTP server.
163 * Flushes any buffered output to the HTTP server. Then frees
164 * all storage allocated by the previous call, including all
165 * storage reachable from the value of environ set by the previous
166 * call to FCGI_Accept.
168 * DO NOT use stdin, stdout, stderr, or environ between calling
169 * FCGI_Finish and calling FCGI_Accept.
171 * DO NOT mutate or retain pointers to environ or any values
172 * contained in it (e.g. to the result of calling getenv(3)),
173 * since these are freed by the next call to FCGI_Finish or
174 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
175 * in conjunction with FCGI_Accept.
177 *----------------------------------------------------------------------
179 void FCGI_Finish(void)
181 if(!acceptCalled || isCGI) {
185 FCGI_stdin->fcgx_stream = NULL;
186 FCGI_stdout->fcgx_stream = NULL;
187 FCGI_stderr->fcgx_stream = NULL;
192 *----------------------------------------------------------------------
194 * FCGI_StartFilterData --
197 * The current request is for the filter role, and stdin is
198 * positioned at EOF of FCGI_STDIN. The call repositions
199 * stdin to the start of FCGI_DATA.
200 * If the preconditions are not met (e.g. FCGI_STDIN has not
201 * been read to EOF), the call sets the stream error code to
202 * FCGX_CALL_SEQ_ERROR.
205 * 0 for a normal return, < 0 for error
207 *----------------------------------------------------------------------
210 int FCGI_StartFilterData(void)
212 if(FCGI_stdin->stdio_stream) {
215 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
220 *----------------------------------------------------------------------
222 * FCGI_SetExitStatus --
224 * Sets the exit status for the current request. The exit status
225 * is the status code the request would have exited with, had
226 * the request been run as a CGI program. You can call
227 * FCGI_SetExitStatus several times during a request; the last call
228 * before the request ends (by calling FCGI_Accept) determines the
231 *----------------------------------------------------------------------
234 void FCGI_SetExitStatus(int status)
236 if(FCGI_stdin->fcgx_stream) {
237 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
242 *----------------------------------------------------------------------
246 * Wrapper for function defined in H&S Section 11.2
248 *----------------------------------------------------------------------
251 void FCGI_perror(const char *str)
253 FCGI_fputs(str, FCGI_stderr);
254 FCGI_fputs(": ", FCGI_stderr);
255 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
260 *----------------------------------------------------------------------
262 * FCGI_OpenFromFILE --
264 * Constructs a new FCGI_FILE * from the FILE *stream.
267 * NULL if stream == NULL or storage could not be allocated,
268 * otherwise the new FCGI_FILE *.
270 *----------------------------------------------------------------------
273 static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
278 fp = malloc(sizeof(FCGI_FILE));
281 fp->stdio_stream = stream;
282 fp->fcgx_stream = NULL;
287 *----------------------------------------------------------------------
289 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
291 * Wrappers for functions defined in H&S Section 15.2
293 *----------------------------------------------------------------------
296 FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
298 return FCGI_OpenFromFILE(fopen(path, mode));
301 int FCGI_fclose(FCGI_FILE *fp)
304 if(fp->stdio_stream) {
305 n = fclose(fp->stdio_stream);
306 fp->stdio_stream = NULL;
307 } else if(fp->fcgx_stream) {
308 n = FCGX_FClose(fp->fcgx_stream);
309 fp->fcgx_stream = NULL;
311 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
317 int FCGI_fflush(FCGI_FILE *fp)
322 return fflush(fp->stdio_stream);
323 else if(fp->fcgx_stream)
324 return FCGX_FFlush(fp->fcgx_stream);
328 FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
331 if(fp->stdio_stream) {
332 if(freopen(path, mode, fp->stdio_stream) == NULL)
336 } else if(fp->fcgx_stream) {
337 (void) FCGX_FClose(fp->fcgx_stream);
338 fp->stdio_stream = fopen(path, mode);
339 if(fp->stdio_stream == NULL)
342 fp->fcgx_stream = NULL;
350 *----------------------------------------------------------------------
352 * FCGI_setvbuf, FCGI_setbuf --
354 * Wrappers for functions defined in H&S Section 15.3
356 *----------------------------------------------------------------------
358 int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
361 return setvbuf(fp->stdio_stream, buf, bufmode, size);
367 void FCGI_setbuf(FCGI_FILE *fp, char *buf)
370 setbuf(fp->stdio_stream, buf);
374 *----------------------------------------------------------------------
376 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
378 * Wrappers for functions defined in H&S Section 15.5
380 *----------------------------------------------------------------------
383 int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
386 return fseek(fp->stdio_stream, offset, whence);
393 int FCGI_ftell(FCGI_FILE *fp)
396 return ftell(fp->stdio_stream);
403 void FCGI_rewind(FCGI_FILE *fp)
406 rewind(fp->stdio_stream);
412 int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
415 return fgetpos(fp->stdio_stream, pos);
422 int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
425 return fsetpos(fp->stdio_stream, pos);
434 *----------------------------------------------------------------------
436 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
438 * Wrappers for functions defined in H&S Section 15.6
440 * XXX: getc and getchar are generally defined as macros
441 * for performance reasons
443 *----------------------------------------------------------------------
446 int FCGI_fgetc(FCGI_FILE *fp)
449 return fgetc(fp->stdio_stream);
450 else if(fp->fcgx_stream)
451 return FCGX_GetChar(fp->fcgx_stream);
455 int FCGI_getchar(void)
457 return FCGI_fgetc(FCGI_stdin);
460 int FCGI_ungetc(int c, FCGI_FILE *fp)
463 return ungetc(c, fp->stdio_stream);
464 else if(fp->fcgx_stream)
465 return FCGX_UnGetChar(c, fp->fcgx_stream);
470 *----------------------------------------------------------------------
472 * FCGI_fgets, FCGI_gets --
474 * Wrappers for functions defined in H&S Section 15.7
476 *----------------------------------------------------------------------
479 char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
482 return fgets(str, size, fp->stdio_stream);
483 else if(fp->fcgx_stream)
484 return FCGX_GetLine(str, size, fp->fcgx_stream);
489 * There is no standard equivalent of gets that takes an explicit
490 * FILE * argument, so the following "wrapper" implements
491 * gets for both FILE * and FCGX_Stream * in terms of FCGI_getchar.
494 char *FCGI_gets(char *str)
498 for (s = str; ((c = FCGI_getchar()) != '\n');) {
512 *----------------------------------------------------------------------
516 * Wrappers for functions defined in H&S Section 15.8
518 * XXX: missing: fscanf, scanf
520 *----------------------------------------------------------------------
525 *----------------------------------------------------------------------
527 * FCGI_fputc, FCGI_putchar --
529 * Wrappers for functions defined in H&S Section 15.9
531 * XXX: putc and putchar are generally defined as macros
532 * for performance reasons
534 *----------------------------------------------------------------------
537 int FCGI_fputc(int c, FCGI_FILE *fp)
540 return fputc(c, fp->stdio_stream);
541 else if(fp->fcgx_stream)
542 return FCGX_PutChar(c, fp->fcgx_stream);
546 int FCGI_putchar(int c)
548 return FCGI_fputc(c, FCGI_stdout);
552 *----------------------------------------------------------------------
554 * FCGI_fputs, FCGI_puts
556 * Wrappers for functions defined in H&S Section 15.10
558 *----------------------------------------------------------------------
561 int FCGI_fputs(const char *str, FCGI_FILE *fp)
564 return fputs(str, fp->stdio_stream);
565 else if(fp->fcgx_stream)
566 return FCGX_PutS(str, fp->fcgx_stream);
570 int FCGI_puts(const char *str)
573 if(FCGI_stdout->stdio_stream) {
574 n = fputs(str, FCGI_stdout->stdio_stream);
578 return fputc('\n', FCGI_stdout->stdio_stream);
579 } else if(FCGI_stdout->fcgx_stream) {
580 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
584 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
590 *----------------------------------------------------------------------
592 * FCGI_fprintf, FCGI_printf --
594 * Wrappers for functions defined in H&S Section 15.11
596 *----------------------------------------------------------------------
599 int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
603 va_start(ap, format);
605 n = vfprintf(fp->stdio_stream, format, ap);
606 else if(fp->fcgx_stream)
607 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
612 int FCGI_printf(const char *format, ...)
616 va_start(ap, format);
617 n = FCGI_vfprintf(FCGI_stdout, format, ap);
623 *----------------------------------------------------------------------
625 * FCGI_vfprintf, FCGI_vprintf --
627 * Wrappers for functions defined in H&S Section 15.12
629 *----------------------------------------------------------------------
632 int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
635 return vfprintf(fp->stdio_stream, format, ap);
636 else if(fp->fcgx_stream)
637 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
641 int FCGI_vprintf(const char *format, va_list ap)
643 if(FCGI_stdout->stdio_stream)
644 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
645 else if(FCGI_stdout->fcgx_stream)
646 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
651 *----------------------------------------------------------------------
653 * FCGI_fread, FCGI_fwrite --
655 * Wrappers for functions defined in H&S Section 15.13
657 *----------------------------------------------------------------------
660 size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
664 return fread(ptr, size, nmemb, fp->stdio_stream);
665 else if(fp->fcgx_stream) {
666 if((size * nmemb) == 0) {
669 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
675 size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
679 return fwrite(ptr, size, nmemb, fp->stdio_stream);
680 else if(fp->fcgx_stream) {
681 if((size * nmemb) == 0) {
684 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
691 *----------------------------------------------------------------------
693 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
695 * Wrappers for functions defined in H&S Section 15.14
697 *----------------------------------------------------------------------
699 int FCGI_feof(FCGI_FILE *fp)
701 if(fp->stdio_stream) {
702 return feof(fp->stdio_stream);
703 } else if (fp->fcgx_stream){
704 return FCGX_HasSeenEOF(fp->fcgx_stream);
710 int FCGI_ferror(FCGI_FILE *fp)
712 if(fp->stdio_stream) {
713 return ferror(fp->stdio_stream);
714 } else if(fp->fcgx_stream) {
715 return FCGX_GetError(fp->fcgx_stream);
720 void FCGI_clearerr(FCGI_FILE *fp)
722 if(fp->stdio_stream) {
723 clearerr(fp->stdio_stream);
724 } else if(fp->fcgx_stream) {
725 FCGX_ClearError(fp->fcgx_stream);
731 *----------------------------------------------------------------------
735 * Wrappers for function defined in H&S Section 15.16
737 *----------------------------------------------------------------------
739 FCGI_FILE *FCGI_tmpfile(void)
741 return FCGI_OpenFromFILE(tmpfile());
746 *----------------------------------------------------------------------
748 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
750 * Wrappers for POSIX, X/OPEN functions not in ISO C
752 *----------------------------------------------------------------------
756 * These definitions should be supplied by stdio.h but for some
757 * reason they get lost on certain platforms.
760 * XXX: Need to find the right way to handle this for NT
764 extern int fileno(FILE *stream);
766 extern FILE *fdopen(int fildes, const char *type);
767 extern FILE *popen(const char *command, const char *type);
768 extern int pclose(FILE *stream);
771 int FCGI_fileno(FCGI_FILE *fp)
774 return fileno(fp->stdio_stream);
779 FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
782 return FCGI_OpenFromFILE(fdopen(fd, mode));
788 FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
790 return FCGI_OpenFromFILE(popen(cmd, type));
793 int FCGI_pclose(FCGI_FILE *fp)
796 if(fp->stdio_stream) {
798 n = pclose(fp->stdio_stream);
800 fp->stdio_stream = NULL;
801 } else if(fp->fcgx_stream) {
803 * The caller is deeply confused; don't free the storage.
807 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
814 *----------------------------------------------------------------------