Flush FastCGI buffers at application exit. <eichin@fastengines.com>
[catagits/fcgi2.git] / libfcgi / fcgi_stdio.c
CommitLineData
0198fd3c 1/*
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
ac8a58ac 15static const char rcsid[] = "$Id: fcgi_stdio.c,v 1.5 1999/06/07 05:03:48 roberts Exp $";
0198fd3c 16#endif /* not lint */
17
18#ifdef _WIN32
19#define DLLAPI __declspec(dllexport)
20#endif
21
22#define NO_FCGI_DEFINES
23#include "fcgi_stdio.h"
24#undef NO_FCGI_DEFINES
25
26#ifdef _WIN32
27#include <windows.h>
28#endif
29#include <errno.h>
30 /* for errno */
31#include <stdarg.h>
32 /* for va_arg */
33#include <stdlib.h>
34 /* for malloc */
35#include <string.h>
36 /* for strerror */
37#ifdef HAVE_UNISTD_H
38#include <unistd.h>
39#endif
40
41#include "fcgiapp.h"
42#include "fcgios.h"
43
44#ifndef FALSE
45#define FALSE (0)
46#endif
47#ifndef TRUE
48#define TRUE (1)
49#endif
50
51#ifdef _WIN32
52FCGI_FILE _fcgi_sF[3];
53#else
54FCGI_FILE _fcgi_sF[3] = {{stdin, NULL}, {stdout, NULL}, {stderr, NULL}};
55#endif
56
57#ifdef _WIN32
58#define popen _popen
59#endif
60\f
61/*
62 *----------------------------------------------------------------------
63 *
64 * FCGI_Accept --
65 *
66 * Accepts a new request from the HTTP server and creates
67 * a conventional execution environment for the request.
68 *
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.
75 *
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).
79 *
80 * Results:
81 * 0 for successful call, -1 for error (application should exit).
82 *
83 * Side effects:
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.
87 *
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.
97 *
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.
103 *
104 *----------------------------------------------------------------------
105 */
106static int acceptCalled = FALSE;
107static int isCGI = FALSE;
108#ifndef _WIN32
109extern char **environ;
110#endif
111
112int FCGI_Accept(void)
113{
114 if(!acceptCalled) {
115 /*
116 * First call to FCGI_Accept. Is application running
117 * as FastCGI or as CGI?
118 */
119 isCGI = FCGX_IsCGI();
120 acceptCalled = TRUE;
ac8a58ac 121 atexit(&FCGI_Finish);
0198fd3c 122 } else if(isCGI) {
123 /*
124 * Not first call to FCGI_Accept and running as CGI means
125 * application is done.
126 */
127 return(EOF);
128 }
129 if(isCGI) {
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;
136 } else {
137 FCGX_Stream *in, *out, *error;
138 FCGX_ParamArray envp;
139 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
140 if(acceptResult < 0) {
141 return acceptResult;
142 }
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;
149 environ = envp;
150 }
151 return 0;
152}
153\f
154/*
155 *----------------------------------------------------------------------
156 *
157 * FCGI_Finish --
158 *
159 * Finishes the current request from the HTTP server.
160 *
161 * Side effects:
162 *
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.
167 *
168 * DO NOT use stdin, stdout, stderr, or environ between calling
169 * FCGI_Finish and calling FCGI_Accept.
170 *
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.
176 *
177 *----------------------------------------------------------------------
178 */
179void FCGI_Finish(void)
180{
181 if(!acceptCalled || isCGI) {
182 return;
183 }
184 FCGX_Finish();
185 FCGI_stdin->fcgx_stream = NULL;
186 FCGI_stdout->fcgx_stream = NULL;
187 FCGI_stderr->fcgx_stream = NULL;
188 environ = NULL;
189}
190\f
191/*
192 *----------------------------------------------------------------------
193 *
194 * FCGI_StartFilterData --
195 *
196 *
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.
203 *
204 * Results:
205 * 0 for a normal return, < 0 for error
206 *
207 *----------------------------------------------------------------------
208 */
209
210int FCGI_StartFilterData(void)
211{
212 if(FCGI_stdin->stdio_stream) {
213 return -1;
214 } else {
215 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
216 }
217}
218\f
219/*
220 *----------------------------------------------------------------------
221 *
222 * FCGI_SetExitStatus --
223 *
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
229 * value.
230 *
231 *----------------------------------------------------------------------
232 */
233
234void FCGI_SetExitStatus(int status)
235{
236 if(FCGI_stdin->fcgx_stream) {
237 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
238 }
239}
240\f
241/*
242 *----------------------------------------------------------------------
243 *
244 * FCGI_perror --
245 *
246 * Wrapper for function defined in H&S Section 11.2
247 *
248 *----------------------------------------------------------------------
249 */
250
251void FCGI_perror(const char *str)
252{
253 FCGI_fputs(str, FCGI_stderr);
254 FCGI_fputs(": ", FCGI_stderr);
255 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
256 return;
257}
258\f
259/*
260 *----------------------------------------------------------------------
261 *
262 * FCGI_OpenFromFILE --
263 *
264 * Constructs a new FCGI_FILE * from the FILE *stream.
265 *
266 * Results:
267 * NULL if stream == NULL or storage could not be allocated,
268 * otherwise the new FCGI_FILE *.
269 *
270 *----------------------------------------------------------------------
271 */
272
273static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
274{
275 FCGI_FILE *fp;
276 if(stream == NULL)
277 return NULL;
278 fp = malloc(sizeof(FCGI_FILE));
279 if(fp == NULL)
280 return NULL;
281 fp->stdio_stream = stream;
282 fp->fcgx_stream = NULL;
283 return fp;
284}
285\f
286/*
287 *----------------------------------------------------------------------
288 *
289 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
290 *
291 * Wrappers for functions defined in H&S Section 15.2
292 *
293 *----------------------------------------------------------------------
294 */
295
296FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
297{
298 return FCGI_OpenFromFILE(fopen(path, mode));
299}
300
301int FCGI_fclose(FCGI_FILE *fp)
302{
303 int n = EOF;
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;
310 }
311 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
312 free(fp);
313 }
314 return n;
315}
316
317int FCGI_fflush(FCGI_FILE *fp)
318{
ed728efb 319 if(fp == NULL)
320 return fflush(NULL);
0198fd3c 321 if(fp->stdio_stream)
322 return fflush(fp->stdio_stream);
323 else if(fp->fcgx_stream)
324 return FCGX_FFlush(fp->fcgx_stream);
325 return EOF;
326}
327
328FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
329 FCGI_FILE *fp)
330{
331 if(fp->stdio_stream) {
332 if(freopen(path, mode, fp->stdio_stream) == NULL)
333 return NULL;
334 else
335 return fp;
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)
340 return NULL;
341 else {
342 fp->fcgx_stream = NULL;
343 return fp;
344 }
345 }
346 return NULL;
347}
348\f
349/*
350 *----------------------------------------------------------------------
351 *
352 * FCGI_setvbuf, FCGI_setbuf --
353 *
354 * Wrappers for functions defined in H&S Section 15.3
355 *
356 *----------------------------------------------------------------------
357 */
358int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
359{
360 if(fp->stdio_stream)
361 return setvbuf(fp->stdio_stream, buf, bufmode, size);
362 else {
363 return -1;
364 }
365}
366
367void FCGI_setbuf(FCGI_FILE *fp, char *buf)
368{
369 if(fp->stdio_stream)
370 setbuf(fp->stdio_stream, buf);
371}
372\f
373/*
374 *----------------------------------------------------------------------
375 *
376 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
377 *
378 * Wrappers for functions defined in H&S Section 15.5
379 *
380 *----------------------------------------------------------------------
381 */
382
383int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
384{
385 if(fp->stdio_stream)
386 return fseek(fp->stdio_stream, offset, whence);
387 else {
388 OS_SetErrno(ESPIPE);
389 return -1;
390 }
391}
392
393int FCGI_ftell(FCGI_FILE *fp)
394{
395 if(fp->stdio_stream)
396 return ftell(fp->stdio_stream);
397 else {
398 OS_SetErrno(ESPIPE);
399 return -1;
400 }
401}
402
403void FCGI_rewind(FCGI_FILE *fp)
404{
405 if(fp->stdio_stream)
406 rewind(fp->stdio_stream);
407 else
408 OS_SetErrno(ESPIPE);
409}
410
411#ifdef HAVE_FPOS
412int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
413{
414 if(fp->stdio_stream)
415 return fgetpos(fp->stdio_stream, pos);
416 else {
417 OS_SetErrno(ESPIPE);
418 return -1;
419 }
420}
421
422int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
423{
424 if(fp->stdio_stream)
425 return fsetpos(fp->stdio_stream, pos);
426 else {
427 OS_SetErrno(ESPIPE);
428 return -1;
429 }
430}
431#endif
432\f
433/*
434 *----------------------------------------------------------------------
435 *
436 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
437 *
438 * Wrappers for functions defined in H&S Section 15.6
439 *
440 * XXX: getc and getchar are generally defined as macros
441 * for performance reasons
442 *
443 *----------------------------------------------------------------------
444 */
445
446int FCGI_fgetc(FCGI_FILE *fp)
447{
448 if(fp->stdio_stream)
449 return fgetc(fp->stdio_stream);
450 else if(fp->fcgx_stream)
451 return FCGX_GetChar(fp->fcgx_stream);
452 return EOF;
453}
454
455int FCGI_getchar(void)
456{
457 return FCGI_fgetc(FCGI_stdin);
458}
459
460int FCGI_ungetc(int c, FCGI_FILE *fp)
461{
462 if(fp->stdio_stream)
463 return ungetc(c, fp->stdio_stream);
464 else if(fp->fcgx_stream)
465 return FCGX_UnGetChar(c, fp->fcgx_stream);
466 return EOF;
467}
468\f
469/*
470 *----------------------------------------------------------------------
471 *
472 * FCGI_fgets, FCGI_gets --
473 *
474 * Wrappers for functions defined in H&S Section 15.7
475 *
476 *----------------------------------------------------------------------
477 */
478
479char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
480{
481 if(fp->stdio_stream)
482 return fgets(str, size, fp->stdio_stream);
483 else if(fp->fcgx_stream)
484 return FCGX_GetLine(str, size, fp->fcgx_stream);
485 return NULL;
486}
487
488/*
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.
492 */
493
494char *FCGI_gets(char *str)
495{
496 char *s;
497 int c;
498 for (s = str; ((c = FCGI_getchar()) != '\n');) {
499 if(c == EOF) {
500 if(s == str)
501 return NULL;
502 else
503 break;
504 } else
505 *s++ = c;
506 }
507 *s = 0;
508 return str;
509}
510\f
511/*
512 *----------------------------------------------------------------------
513 *
514 * --
515 *
516 * Wrappers for functions defined in H&S Section 15.8
517 *
518 * XXX: missing: fscanf, scanf
519 *
520 *----------------------------------------------------------------------
521 */
522
523\f
524/*
525 *----------------------------------------------------------------------
526 *
527 * FCGI_fputc, FCGI_putchar --
528 *
529 * Wrappers for functions defined in H&S Section 15.9
530 *
531 * XXX: putc and putchar are generally defined as macros
532 * for performance reasons
533 *
534 *----------------------------------------------------------------------
535 */
536
537int FCGI_fputc(int c, FCGI_FILE *fp)
538{
539 if(fp->stdio_stream)
540 return fputc(c, fp->stdio_stream);
541 else if(fp->fcgx_stream)
542 return FCGX_PutChar(c, fp->fcgx_stream);
543 else return EOF;
544}
545
546int FCGI_putchar(int c)
547{
548 return FCGI_fputc(c, FCGI_stdout);
549}
550\f
551/*
552 *----------------------------------------------------------------------
553 *
554 * FCGI_fputs, FCGI_puts
555 *
556 * Wrappers for functions defined in H&S Section 15.10
557 *
558 *----------------------------------------------------------------------
559 */
560
561int FCGI_fputs(const char *str, FCGI_FILE *fp)
562{
563 if(fp->stdio_stream)
564 return fputs(str, fp->stdio_stream);
565 else if(fp->fcgx_stream)
566 return FCGX_PutS(str, fp->fcgx_stream);
567 return EOF;
568}
569
570int FCGI_puts(const char *str)
571{
572 int n;
573 if(FCGI_stdout->stdio_stream) {
574 n = fputs(str, FCGI_stdout->stdio_stream);
575 if(n < 0)
576 return n;
577 else
578 return fputc('\n', FCGI_stdout->stdio_stream);
579 } else if(FCGI_stdout->fcgx_stream) {
580 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
581 if(n < 0)
582 return n;
583 else
584 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
585 }
586 return EOF;
587}
588\f
589/*
590 *----------------------------------------------------------------------
591 *
592 * FCGI_fprintf, FCGI_printf --
593 *
594 * Wrappers for functions defined in H&S Section 15.11
595 *
596 *----------------------------------------------------------------------
597 */
598
599int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
600{
601 va_list ap;
602 int n = 0;
603 va_start(ap, format);
604 if(fp->stdio_stream)
605 n = vfprintf(fp->stdio_stream, format, ap);
606 else if(fp->fcgx_stream)
607 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
608 va_end(ap);
609 return n;
610}
611
612int FCGI_printf(const char *format, ...)
613{
614 va_list ap;
615 int n;
616 va_start(ap, format);
617 n = FCGI_vfprintf(FCGI_stdout, format, ap);
618 va_end(ap);
619 return n;
620}
621\f
622/*
623 *----------------------------------------------------------------------
624 *
625 * FCGI_vfprintf, FCGI_vprintf --
626 *
627 * Wrappers for functions defined in H&S Section 15.12
628 *
629 *----------------------------------------------------------------------
630 */
631
632int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
633{
634 if(fp->stdio_stream)
635 return vfprintf(fp->stdio_stream, format, ap);
636 else if(fp->fcgx_stream)
637 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
638 return EOF;
639}
640
641int FCGI_vprintf(const char *format, va_list ap)
642{
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);
647 return EOF;
648}
649\f
650/*
651 *----------------------------------------------------------------------
652 *
653 * FCGI_fread, FCGI_fwrite --
654 *
655 * Wrappers for functions defined in H&S Section 15.13
656 *
657 *----------------------------------------------------------------------
658 */
659
660size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
661{
662 int n;
663 if(fp->stdio_stream)
664 return fread(ptr, size, nmemb, fp->stdio_stream);
665 else if(fp->fcgx_stream) {
666 if((size * nmemb) == 0) {
667 return 0;
668 }
669 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
670 return (n/size);
671 }
672 return (size_t)EOF;
673}
674
675size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
676{
677 int n;
678 if(fp->stdio_stream)
679 return fwrite(ptr, size, nmemb, fp->stdio_stream);
680 else if(fp->fcgx_stream) {
681 if((size * nmemb) == 0) {
682 return 0;
683 }
684 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
685 return (n/size);
686 }
687 return (size_t)EOF;
688}
689\f
690/*
691 *----------------------------------------------------------------------
692 *
693 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
694 *
695 * Wrappers for functions defined in H&S Section 15.14
696 *
697 *----------------------------------------------------------------------
698 */
699int FCGI_feof(FCGI_FILE *fp)
700{
701 if(fp->stdio_stream) {
702 return feof(fp->stdio_stream);
703 } else if (fp->fcgx_stream){
704 return FCGX_HasSeenEOF(fp->fcgx_stream);
705 }
706 return -1;
707
708}
709
710int FCGI_ferror(FCGI_FILE *fp)
711{
712 if(fp->stdio_stream) {
713 return ferror(fp->stdio_stream);
714 } else if(fp->fcgx_stream) {
715 return FCGX_GetError(fp->fcgx_stream);
716 }
717 return -1;
718}
719
720void FCGI_clearerr(FCGI_FILE *fp)
721{
722 if(fp->stdio_stream) {
723 clearerr(fp->stdio_stream);
724 } else if(fp->fcgx_stream) {
725 FCGX_ClearError(fp->fcgx_stream);
726 }
727 return;
ed728efb 728}
17abbc3a 729\f
730/*
731 *----------------------------------------------------------------------
732 *
733 * FCGI_tmpfile --
734 *
735 * Wrappers for function defined in H&S Section 15.16
736 *
737 *----------------------------------------------------------------------
738 */
739FCGI_FILE *FCGI_tmpfile(void)
ed728efb 740{
741 return FCGI_OpenFromFILE(tmpfile());
0198fd3c 742}
17abbc3a 743
0198fd3c 744\f
745/*
746 *----------------------------------------------------------------------
747 *
748 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
749 *
750 * Wrappers for POSIX, X/OPEN functions not in ISO C
751 *
752 *----------------------------------------------------------------------
753 */
754
755/*
756 * These definitions should be supplied by stdio.h but for some
757 * reason they get lost on certain platforms.
758 */
759/*
760 * XXX: Need to find the right way to handle this for NT
761 */
762#ifndef _WIN32
763#ifndef fileno
764extern int fileno(FILE *stream);
765#endif
766extern FILE *fdopen(int fildes, const char *type);
767extern FILE *popen(const char *command, const char *type);
768extern int pclose(FILE *stream);
769#endif
770
771int FCGI_fileno(FCGI_FILE *fp)
772{
773 if(fp->stdio_stream)
774 return fileno(fp->stdio_stream);
775 else
776 return -1;
777}
778
779FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
780{
781#ifndef _WIN32
782 return FCGI_OpenFromFILE(fdopen(fd, mode));
783#else
784 return NULL;
785#endif
786}
787
788FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
789{
790 return FCGI_OpenFromFILE(popen(cmd, type));
791}
792
793int FCGI_pclose(FCGI_FILE *fp)
794{
795 int n = EOF;
796 if(fp->stdio_stream) {
797#ifndef _WIN32
798 n = pclose(fp->stdio_stream);
799#endif
800 fp->stdio_stream = NULL;
801 } else if(fp->fcgx_stream) {
802 /*
803 * The caller is deeply confused; don't free the storage.
804 */
805 return EOF;
806 }
807 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
808 free(fp);
809 }
810 return n;
811}
812
813/*
814 *----------------------------------------------------------------------
815 */