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