Add tmpfile() support. Contributed by Michael Driscoll (fenris@frob.ml.org).
[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
17abbc3a 15static const char rcsid[] = "$Id: fcgi_stdio.c,v 1.3 1998/03/09 16:38:15 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;
121 } else if(isCGI) {
122 /*
123 * Not first call to FCGI_Accept and running as CGI means
124 * application is done.
125 */
126 return(EOF);
127 }
128 if(isCGI) {
129 FCGI_stdin->stdio_stream = stdin;
130 FCGI_stdin->fcgx_stream = NULL;
131 FCGI_stdout->stdio_stream = stdout;
132 FCGI_stdout->fcgx_stream = NULL;
133 FCGI_stderr->stdio_stream = stderr;
134 FCGI_stderr->fcgx_stream = NULL;
135 } else {
136 FCGX_Stream *in, *out, *error;
137 FCGX_ParamArray envp;
138 int acceptResult = FCGX_Accept(&in, &out, &error, &envp);
139 if(acceptResult < 0) {
140 return acceptResult;
141 }
142 FCGI_stdin->stdio_stream = NULL;
143 FCGI_stdin->fcgx_stream = in;
144 FCGI_stdout->stdio_stream = NULL;
145 FCGI_stdout->fcgx_stream = out;
146 FCGI_stderr->stdio_stream = NULL;
147 FCGI_stderr->fcgx_stream = error;
148 environ = envp;
149 }
150 return 0;
151}
152\f
153/*
154 *----------------------------------------------------------------------
155 *
156 * FCGI_Finish --
157 *
158 * Finishes the current request from the HTTP server.
159 *
160 * Side effects:
161 *
162 * Flushes any buffered output to the HTTP server. Then frees
163 * all storage allocated by the previous call, including all
164 * storage reachable from the value of environ set by the previous
165 * call to FCGI_Accept.
166 *
167 * DO NOT use stdin, stdout, stderr, or environ between calling
168 * FCGI_Finish and calling FCGI_Accept.
169 *
170 * DO NOT mutate or retain pointers to environ or any values
171 * contained in it (e.g. to the result of calling getenv(3)),
172 * since these are freed by the next call to FCGI_Finish or
173 * FCGI_Accept. In particular do not use setenv(3) or putenv(3)
174 * in conjunction with FCGI_Accept.
175 *
176 *----------------------------------------------------------------------
177 */
178void FCGI_Finish(void)
179{
180 if(!acceptCalled || isCGI) {
181 return;
182 }
183 FCGX_Finish();
184 FCGI_stdin->fcgx_stream = NULL;
185 FCGI_stdout->fcgx_stream = NULL;
186 FCGI_stderr->fcgx_stream = NULL;
187 environ = NULL;
188}
189\f
190/*
191 *----------------------------------------------------------------------
192 *
193 * FCGI_StartFilterData --
194 *
195 *
196 * The current request is for the filter role, and stdin is
197 * positioned at EOF of FCGI_STDIN. The call repositions
198 * stdin to the start of FCGI_DATA.
199 * If the preconditions are not met (e.g. FCGI_STDIN has not
200 * been read to EOF), the call sets the stream error code to
201 * FCGX_CALL_SEQ_ERROR.
202 *
203 * Results:
204 * 0 for a normal return, < 0 for error
205 *
206 *----------------------------------------------------------------------
207 */
208
209int FCGI_StartFilterData(void)
210{
211 if(FCGI_stdin->stdio_stream) {
212 return -1;
213 } else {
214 return FCGX_StartFilterData(FCGI_stdin->fcgx_stream);
215 }
216}
217\f
218/*
219 *----------------------------------------------------------------------
220 *
221 * FCGI_SetExitStatus --
222 *
223 * Sets the exit status for the current request. The exit status
224 * is the status code the request would have exited with, had
225 * the request been run as a CGI program. You can call
226 * FCGI_SetExitStatus several times during a request; the last call
227 * before the request ends (by calling FCGI_Accept) determines the
228 * value.
229 *
230 *----------------------------------------------------------------------
231 */
232
233void FCGI_SetExitStatus(int status)
234{
235 if(FCGI_stdin->fcgx_stream) {
236 FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream);
237 }
238}
239\f
240/*
241 *----------------------------------------------------------------------
242 *
243 * FCGI_perror --
244 *
245 * Wrapper for function defined in H&S Section 11.2
246 *
247 *----------------------------------------------------------------------
248 */
249
250void FCGI_perror(const char *str)
251{
252 FCGI_fputs(str, FCGI_stderr);
253 FCGI_fputs(": ", FCGI_stderr);
254 FCGI_fputs(strerror(OS_Errno), FCGI_stderr);
255 return;
256}
257\f
258/*
259 *----------------------------------------------------------------------
260 *
261 * FCGI_OpenFromFILE --
262 *
263 * Constructs a new FCGI_FILE * from the FILE *stream.
264 *
265 * Results:
266 * NULL if stream == NULL or storage could not be allocated,
267 * otherwise the new FCGI_FILE *.
268 *
269 *----------------------------------------------------------------------
270 */
271
272static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream)
273{
274 FCGI_FILE *fp;
275 if(stream == NULL)
276 return NULL;
277 fp = malloc(sizeof(FCGI_FILE));
278 if(fp == NULL)
279 return NULL;
280 fp->stdio_stream = stream;
281 fp->fcgx_stream = NULL;
282 return fp;
283}
284\f
285/*
286 *----------------------------------------------------------------------
287 *
288 * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen --
289 *
290 * Wrappers for functions defined in H&S Section 15.2
291 *
292 *----------------------------------------------------------------------
293 */
294
295FCGI_FILE *FCGI_fopen(const char *path, const char *mode)
296{
297 return FCGI_OpenFromFILE(fopen(path, mode));
298}
299
300int FCGI_fclose(FCGI_FILE *fp)
301{
302 int n = EOF;
303 if(fp->stdio_stream) {
304 n = fclose(fp->stdio_stream);
305 fp->stdio_stream = NULL;
306 } else if(fp->fcgx_stream) {
307 n = FCGX_FClose(fp->fcgx_stream);
308 fp->fcgx_stream = NULL;
309 }
310 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
311 free(fp);
312 }
313 return n;
314}
315
316int FCGI_fflush(FCGI_FILE *fp)
317{
966a5771 318 if(fp == null)\r
319 return fflush(NULL);\r
0198fd3c 320 if(fp->stdio_stream)
321 return fflush(fp->stdio_stream);
322 else if(fp->fcgx_stream)
323 return FCGX_FFlush(fp->fcgx_stream);
324 return EOF;
325}
326
327FCGI_FILE *FCGI_freopen(const char *path, const char *mode,
328 FCGI_FILE *fp)
329{
330 if(fp->stdio_stream) {
331 if(freopen(path, mode, fp->stdio_stream) == NULL)
332 return NULL;
333 else
334 return fp;
335 } else if(fp->fcgx_stream) {
336 (void) FCGX_FClose(fp->fcgx_stream);
337 fp->stdio_stream = fopen(path, mode);
338 if(fp->stdio_stream == NULL)
339 return NULL;
340 else {
341 fp->fcgx_stream = NULL;
342 return fp;
343 }
344 }
345 return NULL;
346}
347\f
348/*
349 *----------------------------------------------------------------------
350 *
351 * FCGI_setvbuf, FCGI_setbuf --
352 *
353 * Wrappers for functions defined in H&S Section 15.3
354 *
355 *----------------------------------------------------------------------
356 */
357int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size)
358{
359 if(fp->stdio_stream)
360 return setvbuf(fp->stdio_stream, buf, bufmode, size);
361 else {
362 return -1;
363 }
364}
365
366void FCGI_setbuf(FCGI_FILE *fp, char *buf)
367{
368 if(fp->stdio_stream)
369 setbuf(fp->stdio_stream, buf);
370}
371\f
372/*
373 *----------------------------------------------------------------------
374 *
375 * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos --
376 *
377 * Wrappers for functions defined in H&S Section 15.5
378 *
379 *----------------------------------------------------------------------
380 */
381
382int FCGI_fseek(FCGI_FILE *fp, long offset, int whence)
383{
384 if(fp->stdio_stream)
385 return fseek(fp->stdio_stream, offset, whence);
386 else {
387 OS_SetErrno(ESPIPE);
388 return -1;
389 }
390}
391
392int FCGI_ftell(FCGI_FILE *fp)
393{
394 if(fp->stdio_stream)
395 return ftell(fp->stdio_stream);
396 else {
397 OS_SetErrno(ESPIPE);
398 return -1;
399 }
400}
401
402void FCGI_rewind(FCGI_FILE *fp)
403{
404 if(fp->stdio_stream)
405 rewind(fp->stdio_stream);
406 else
407 OS_SetErrno(ESPIPE);
408}
409
410#ifdef HAVE_FPOS
411int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos)
412{
413 if(fp->stdio_stream)
414 return fgetpos(fp->stdio_stream, pos);
415 else {
416 OS_SetErrno(ESPIPE);
417 return -1;
418 }
419}
420
421int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos)
422{
423 if(fp->stdio_stream)
424 return fsetpos(fp->stdio_stream, pos);
425 else {
426 OS_SetErrno(ESPIPE);
427 return -1;
428 }
429}
430#endif
431\f
432/*
433 *----------------------------------------------------------------------
434 *
435 * FCGI_fgetc, FCGI_getchar, FCGI_ungetc --
436 *
437 * Wrappers for functions defined in H&S Section 15.6
438 *
439 * XXX: getc and getchar are generally defined as macros
440 * for performance reasons
441 *
442 *----------------------------------------------------------------------
443 */
444
445int FCGI_fgetc(FCGI_FILE *fp)
446{
447 if(fp->stdio_stream)
448 return fgetc(fp->stdio_stream);
449 else if(fp->fcgx_stream)
450 return FCGX_GetChar(fp->fcgx_stream);
451 return EOF;
452}
453
454int FCGI_getchar(void)
455{
456 return FCGI_fgetc(FCGI_stdin);
457}
458
459int FCGI_ungetc(int c, FCGI_FILE *fp)
460{
461 if(fp->stdio_stream)
462 return ungetc(c, fp->stdio_stream);
463 else if(fp->fcgx_stream)
464 return FCGX_UnGetChar(c, fp->fcgx_stream);
465 return EOF;
466}
467\f
468/*
469 *----------------------------------------------------------------------
470 *
471 * FCGI_fgets, FCGI_gets --
472 *
473 * Wrappers for functions defined in H&S Section 15.7
474 *
475 *----------------------------------------------------------------------
476 */
477
478char *FCGI_fgets(char *str, int size, FCGI_FILE *fp)
479{
480 if(fp->stdio_stream)
481 return fgets(str, size, fp->stdio_stream);
482 else if(fp->fcgx_stream)
483 return FCGX_GetLine(str, size, fp->fcgx_stream);
484 return NULL;
485}
486
487/*
488 * There is no standard equivalent of gets that takes an explicit
489 * FILE * argument, so the following "wrapper" implements
490 * gets for both FILE * and FCGX_Stream * in terms of FCGI_getchar.
491 */
492
493char *FCGI_gets(char *str)
494{
495 char *s;
496 int c;
497 for (s = str; ((c = FCGI_getchar()) != '\n');) {
498 if(c == EOF) {
499 if(s == str)
500 return NULL;
501 else
502 break;
503 } else
504 *s++ = c;
505 }
506 *s = 0;
507 return str;
508}
509\f
510/*
511 *----------------------------------------------------------------------
512 *
513 * --
514 *
515 * Wrappers for functions defined in H&S Section 15.8
516 *
517 * XXX: missing: fscanf, scanf
518 *
519 *----------------------------------------------------------------------
520 */
521
522\f
523/*
524 *----------------------------------------------------------------------
525 *
526 * FCGI_fputc, FCGI_putchar --
527 *
528 * Wrappers for functions defined in H&S Section 15.9
529 *
530 * XXX: putc and putchar are generally defined as macros
531 * for performance reasons
532 *
533 *----------------------------------------------------------------------
534 */
535
536int FCGI_fputc(int c, FCGI_FILE *fp)
537{
538 if(fp->stdio_stream)
539 return fputc(c, fp->stdio_stream);
540 else if(fp->fcgx_stream)
541 return FCGX_PutChar(c, fp->fcgx_stream);
542 else return EOF;
543}
544
545int FCGI_putchar(int c)
546{
547 return FCGI_fputc(c, FCGI_stdout);
548}
549\f
550/*
551 *----------------------------------------------------------------------
552 *
553 * FCGI_fputs, FCGI_puts
554 *
555 * Wrappers for functions defined in H&S Section 15.10
556 *
557 *----------------------------------------------------------------------
558 */
559
560int FCGI_fputs(const char *str, FCGI_FILE *fp)
561{
562 if(fp->stdio_stream)
563 return fputs(str, fp->stdio_stream);
564 else if(fp->fcgx_stream)
565 return FCGX_PutS(str, fp->fcgx_stream);
566 return EOF;
567}
568
569int FCGI_puts(const char *str)
570{
571 int n;
572 if(FCGI_stdout->stdio_stream) {
573 n = fputs(str, FCGI_stdout->stdio_stream);
574 if(n < 0)
575 return n;
576 else
577 return fputc('\n', FCGI_stdout->stdio_stream);
578 } else if(FCGI_stdout->fcgx_stream) {
579 n = FCGX_PutS(str, FCGI_stdout->fcgx_stream);
580 if(n < 0)
581 return n;
582 else
583 return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream);
584 }
585 return EOF;
586}
587\f
588/*
589 *----------------------------------------------------------------------
590 *
591 * FCGI_fprintf, FCGI_printf --
592 *
593 * Wrappers for functions defined in H&S Section 15.11
594 *
595 *----------------------------------------------------------------------
596 */
597
598int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
599{
600 va_list ap;
601 int n = 0;
602 va_start(ap, format);
603 if(fp->stdio_stream)
604 n = vfprintf(fp->stdio_stream, format, ap);
605 else if(fp->fcgx_stream)
606 n = FCGX_VFPrintF(fp->fcgx_stream, format, ap);
607 va_end(ap);
608 return n;
609}
610
611int FCGI_printf(const char *format, ...)
612{
613 va_list ap;
614 int n;
615 va_start(ap, format);
616 n = FCGI_vfprintf(FCGI_stdout, format, ap);
617 va_end(ap);
618 return n;
619}
620\f
621/*
622 *----------------------------------------------------------------------
623 *
624 * FCGI_vfprintf, FCGI_vprintf --
625 *
626 * Wrappers for functions defined in H&S Section 15.12
627 *
628 *----------------------------------------------------------------------
629 */
630
631int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap)
632{
633 if(fp->stdio_stream)
634 return vfprintf(fp->stdio_stream, format, ap);
635 else if(fp->fcgx_stream)
636 return FCGX_VFPrintF(fp->fcgx_stream, format, ap);
637 return EOF;
638}
639
640int FCGI_vprintf(const char *format, va_list ap)
641{
642 if(FCGI_stdout->stdio_stream)
643 return vfprintf(FCGI_stdout->stdio_stream, format, ap);
644 else if(FCGI_stdout->fcgx_stream)
645 return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap);
646 return EOF;
647}
648\f
649/*
650 *----------------------------------------------------------------------
651 *
652 * FCGI_fread, FCGI_fwrite --
653 *
654 * Wrappers for functions defined in H&S Section 15.13
655 *
656 *----------------------------------------------------------------------
657 */
658
659size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
660{
661 int n;
662 if(fp->stdio_stream)
663 return fread(ptr, size, nmemb, fp->stdio_stream);
664 else if(fp->fcgx_stream) {
665 if((size * nmemb) == 0) {
666 return 0;
667 }
668 n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream);
669 return (n/size);
670 }
671 return (size_t)EOF;
672}
673
674size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp)
675{
676 int n;
677 if(fp->stdio_stream)
678 return fwrite(ptr, size, nmemb, fp->stdio_stream);
679 else if(fp->fcgx_stream) {
680 if((size * nmemb) == 0) {
681 return 0;
682 }
683 n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream);
684 return (n/size);
685 }
686 return (size_t)EOF;
687}
688\f
689/*
690 *----------------------------------------------------------------------
691 *
692 * FCGI_feof, FCGI_ferror, FCGI_clearerr --
693 *
694 * Wrappers for functions defined in H&S Section 15.14
695 *
696 *----------------------------------------------------------------------
697 */
698int FCGI_feof(FCGI_FILE *fp)
699{
700 if(fp->stdio_stream) {
701 return feof(fp->stdio_stream);
702 } else if (fp->fcgx_stream){
703 return FCGX_HasSeenEOF(fp->fcgx_stream);
704 }
705 return -1;
706
707}
708
709int FCGI_ferror(FCGI_FILE *fp)
710{
711 if(fp->stdio_stream) {
712 return ferror(fp->stdio_stream);
713 } else if(fp->fcgx_stream) {
714 return FCGX_GetError(fp->fcgx_stream);
715 }
716 return -1;
717}
718
719void FCGI_clearerr(FCGI_FILE *fp)
720{
721 if(fp->stdio_stream) {
722 clearerr(fp->stdio_stream);
723 } else if(fp->fcgx_stream) {
724 FCGX_ClearError(fp->fcgx_stream);
725 }
726 return;
17abbc3a 727}\r
728\f
729/*
730 *----------------------------------------------------------------------
731 *
732 * FCGI_tmpfile --
733 *
734 * Wrappers for function defined in H&S Section 15.16
735 *
736 *----------------------------------------------------------------------
737 */
738FCGI_FILE *FCGI_tmpfile(void)
739{\r
740 return FCGI_OpenFromFile(tmpfile());
0198fd3c 741}
17abbc3a 742
0198fd3c 743\f
744/*
745 *----------------------------------------------------------------------
746 *
747 * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose --
748 *
749 * Wrappers for POSIX, X/OPEN functions not in ISO C
750 *
751 *----------------------------------------------------------------------
752 */
753
754/*
755 * These definitions should be supplied by stdio.h but for some
756 * reason they get lost on certain platforms.
757 */
758/*
759 * XXX: Need to find the right way to handle this for NT
760 */
761#ifndef _WIN32
762#ifndef fileno
763extern int fileno(FILE *stream);
764#endif
765extern FILE *fdopen(int fildes, const char *type);
766extern FILE *popen(const char *command, const char *type);
767extern int pclose(FILE *stream);
768#endif
769
770int FCGI_fileno(FCGI_FILE *fp)
771{
772 if(fp->stdio_stream)
773 return fileno(fp->stdio_stream);
774 else
775 return -1;
776}
777
778FCGI_FILE *FCGI_fdopen(int fd, const char *mode)
779{
780#ifndef _WIN32
781 return FCGI_OpenFromFILE(fdopen(fd, mode));
782#else
783 return NULL;
784#endif
785}
786
787FCGI_FILE *FCGI_popen(const char *cmd, const char *type)
788{
789 return FCGI_OpenFromFILE(popen(cmd, type));
790}
791
792int FCGI_pclose(FCGI_FILE *fp)
793{
794 int n = EOF;
795 if(fp->stdio_stream) {
796#ifndef _WIN32
797 n = pclose(fp->stdio_stream);
798#endif
799 fp->stdio_stream = NULL;
800 } else if(fp->fcgx_stream) {
801 /*
802 * The caller is deeply confused; don't free the storage.
803 */
804 return EOF;
805 }
806 if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) {
807 free(fp);
808 }
809 return n;
810}
811
812/*
813 *----------------------------------------------------------------------
814 */