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