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