Commit | Line | Data |
0833402a |
1 | use Config; |
2 | |
3 | open OUT, ">FCGI.xs"; |
4 | |
5 | print "Generating FCGI.xs for Perl version $]\n"; |
6 | #unless (exists $Config{apiversion} && $Config{apiversion} >= 5.005) |
7 | unless ($] >= 5.005) { |
8 | for (qw(sv_undef diehook warnhook in_eval)) { |
5828234f |
9 | print OUT "#define PL_$_ $_\n" |
0833402a |
10 | } |
11 | } |
12 | print OUT while <DATA>; |
13 | close OUT; |
14 | __END__ |
fdee298f |
15 | /* $Id: FCGI.XL,v 1.10 2003/06/22 00:24:11 robs Exp $ */ |
0833402a |
16 | |
17 | #include "EXTERN.h" |
18 | #include "perl.h" |
19 | #include "XSUB.h" |
20 | |
21 | #include "fcgi_config.h" |
22 | #include "fcgiapp.h" |
23 | #include "fastcgi.h" |
24 | |
25 | #ifndef FALSE |
26 | #define FALSE (0) |
27 | #endif |
28 | |
29 | #ifndef TRUE |
30 | #define TRUE (1) |
31 | #endif |
32 | |
33 | #ifndef dTHX |
34 | #define dTHX |
35 | #endif |
36 | |
0c1fdec9 |
37 | #ifndef INT2PTR |
38 | #define INT2PTR(a,b) ((a) (b)) |
39 | #endif |
40 | |
0833402a |
41 | #ifdef USE_SFIO |
42 | typedef struct |
43 | { |
5828234f |
44 | Sfdisc_t disc; |
45 | FCGX_Stream *stream; |
0833402a |
46 | } FCGI_Disc; |
47 | |
48 | static ssize_t |
49 | sffcgiread(f, buf, n, disc) |
5828234f |
50 | Sfio_t* f; /* stream involved */ |
51 | Void_t* buf; /* buffer to read into */ |
52 | size_t n; /* number of bytes to read */ |
53 | Sfdisc_t* disc; /* discipline */ |
0833402a |
54 | { |
55 | return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream); |
56 | } |
57 | |
58 | static ssize_t |
59 | sffcgiwrite(f, buf, n, disc) |
5828234f |
60 | Sfio_t* f; /* stream involved */ |
61 | const Void_t* buf; /* buffer to read into */ |
62 | size_t n; /* number of bytes to read */ |
63 | Sfdisc_t* disc; /* discipline */ |
0833402a |
64 | { |
65 | n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream); |
66 | FCGX_FFlush(((FCGI_Disc *)disc)->stream); |
67 | return n; |
68 | } |
69 | |
70 | Sfdisc_t * |
71 | sfdcnewfcgi(stream) |
5828234f |
72 | FCGX_Stream *stream; |
0833402a |
73 | { |
5828234f |
74 | FCGI_Disc* disc; |
0833402a |
75 | |
76 | New(1000,disc,1,FCGI_Disc); |
77 | if (!disc) return (Sfdisc_t *)disc; |
78 | |
79 | disc->disc.exceptf = (Sfexcept_f)NULL; |
80 | disc->disc.seekf = (Sfseek_f)NULL; |
81 | disc->disc.readf = sffcgiread; |
82 | disc->disc.writef = sffcgiwrite; |
83 | disc->stream = stream; |
84 | return (Sfdisc_t *)disc; |
85 | } |
86 | |
87 | Sfdisc_t * |
88 | sfdcdelfcgi(disc) |
5828234f |
89 | Sfdisc_t* disc; |
0833402a |
90 | { |
91 | Safefree(disc); |
92 | return 0; |
93 | } |
94 | #endif |
95 | |
96 | #if defined(USE_LOCKING) && defined(USE_THREADS) |
66cfae24 |
97 | static perl_mutex accept_mutex; |
0833402a |
98 | #endif |
99 | |
100 | typedef struct FCGP_Request { |
5828234f |
101 | int accepted; |
102 | int bound; |
103 | SV* svin; |
104 | SV* svout; |
105 | SV* sverr; |
106 | GV* gv[3]; |
107 | HV* hvEnv; |
0833402a |
108 | FCGX_Request* requestPtr; |
109 | #ifdef USE_SFIO |
5828234f |
110 | int sfcreated[3]; |
111 | IO* io[3]; |
0833402a |
112 | #endif |
113 | } FCGP_Request; |
114 | |
115 | static void FCGI_Finish(FCGP_Request* request); |
116 | |
9b60732b |
117 | static void |
66cfae24 |
118 | FCGI_Flush(FCGP_Request* request) { |
0833402a |
119 | dTHX; |
66cfae24 |
120 | if(!request->bound) |
121 | return; |
0833402a |
122 | #ifdef USE_SFIO |
123 | sfsync(IoOFP(GvIOp(request->gv[1]))); |
124 | sfsync(IoOFP(GvIOp(request->gv[2]))); |
125 | #else |
9c31872c |
126 | FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->svout)))); |
127 | FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->sverr)))); |
0833402a |
128 | #endif |
129 | } |
130 | |
131 | static void |
66cfae24 |
132 | FCGI_UndoBinding(FCGP_Request* request) { |
0833402a |
133 | dTHX; |
0833402a |
134 | #ifdef USE_SFIO |
135 | sfdcdelfcgi(sfdisc(IoIFP(request->io[0]), SF_POPDISC)); |
136 | sfdcdelfcgi(sfdisc(IoOFP(request->io[1]), SF_POPDISC)); |
137 | sfdcdelfcgi(sfdisc(IoOFP(request->io[2]), SF_POPDISC)); |
138 | #else |
849cab1e |
139 | # ifdef USE_PERLIO |
140 | sv_unmagic((SV *)GvIOp(request->gv[0]), 'q'); |
141 | sv_unmagic((SV *)GvIOp(request->gv[1]), 'q'); |
142 | sv_unmagic((SV *)GvIOp(request->gv[2]), 'q'); |
143 | # else |
0833402a |
144 | sv_unmagic((SV *)request->gv[0], 'q'); |
145 | sv_unmagic((SV *)request->gv[1], 'q'); |
146 | sv_unmagic((SV *)request->gv[2], 'q'); |
849cab1e |
147 | # endif |
0833402a |
148 | #endif |
149 | request->bound = FALSE; |
150 | } |
151 | |
152 | static void |
66cfae24 |
153 | FCGI_Bind(FCGP_Request* request) { |
0833402a |
154 | dTHX; |
0833402a |
155 | #ifdef USE_SFIO |
156 | sfdisc(IoIFP(request->io[0]), sfdcnewfcgi(request->requestPtr->in)); |
157 | sfdisc(IoOFP(request->io[1]), sfdcnewfcgi(request->requestPtr->out)); |
158 | sfdisc(IoOFP(request->io[2]), sfdcnewfcgi(request->requestPtr->err)); |
159 | #else |
6d7e3fb2 |
160 | # ifdef USE_PERLIO |
161 | /* For tied filehandles, we apply tiedscalar magic to the IO |
162 | slot of the GP rather than the GV itself. */ |
163 | |
164 | if (!GvIOp(request->gv[1])) |
66cfae24 |
165 | GvIOp(request->gv[1]) = newIO(); |
6d7e3fb2 |
166 | if (!GvIOp(request->gv[2])) |
66cfae24 |
167 | GvIOp(request->gv[2]) = newIO(); |
6d7e3fb2 |
168 | if (!GvIOp(request->gv[0])) |
66cfae24 |
169 | GvIOp(request->gv[0]) = newIO(); |
6d7e3fb2 |
170 | |
171 | sv_magic((SV *)GvIOp(request->gv[1]), request->svout, 'q', Nullch, 0); |
172 | sv_magic((SV *)GvIOp(request->gv[2]), request->sverr, 'q', Nullch, 0); |
173 | sv_magic((SV *)GvIOp(request->gv[0]), request->svin, 'q', Nullch, 0); |
174 | # else |
0833402a |
175 | sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0); |
176 | sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0); |
177 | sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0); |
6d7e3fb2 |
178 | # endif |
0833402a |
179 | #endif |
180 | request->bound = TRUE; |
181 | } |
182 | |
183 | static void |
66cfae24 |
184 | populate_env(char **envp, HV *hv) { |
0833402a |
185 | int i; |
186 | char *p, *p1; |
66cfae24 |
187 | SV *sv; |
0833402a |
188 | dTHX; |
189 | |
190 | hv_clear(hv); |
191 | for(i = 0; ; i++) { |
66cfae24 |
192 | if((p = envp[i]) == NULL) |
193 | break; |
194 | p1 = strchr(p, '='); |
195 | assert(p1 != NULL); |
196 | sv = newSVpv(p1 + 1, 0); |
197 | /* call magic for this value ourselves */ |
198 | hv_store(hv, p, p1 - p, sv, 0); |
199 | SvSETMAGIC(sv); |
0833402a |
200 | } |
201 | } |
202 | |
203 | static int |
66cfae24 |
204 | FCGI_IsFastCGI(FCGP_Request* request) { |
0833402a |
205 | static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: CGI */ |
206 | |
207 | if (request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO) { |
66cfae24 |
208 | if (isCGI == -1) |
209 | isCGI = FCGX_IsCGI(); |
210 | return !isCGI; |
0833402a |
211 | } |
212 | |
213 | /* A explicit socket is being used -> assume FastCGI */ |
214 | return 1; |
215 | } |
216 | |
217 | static int |
66cfae24 |
218 | FCGI_Accept(FCGP_Request* request) { |
0833402a |
219 | dTHX; |
220 | |
221 | if (!FCGI_IsFastCGI(request)) { |
66cfae24 |
222 | static int been_here = 0; |
0833402a |
223 | |
224 | /* |
66cfae24 |
225 | * Not first call to FCGI_Accept and running as CGI means |
226 | * application is done. |
227 | */ |
228 | if (been_here) |
229 | return EOF; |
230 | been_here = 1; |
231 | } |
232 | else { |
0833402a |
233 | #ifdef USE_SFIO |
66cfae24 |
234 | int i; |
0833402a |
235 | #endif |
66cfae24 |
236 | FCGX_Request *fcgx_req = request->requestPtr; |
0833402a |
237 | int acceptResult; |
238 | |
66cfae24 |
239 | FCGI_Finish(request); |
0833402a |
240 | #if defined(USE_LOCKING) && defined(USE_THREADS) |
66cfae24 |
241 | MUTEX_LOCK(&accept_mutex); |
0833402a |
242 | #endif |
66cfae24 |
243 | acceptResult = FCGX_Accept_r(fcgx_req); |
0833402a |
244 | #if defined(USE_LOCKING) && defined(USE_THREADS) |
66cfae24 |
245 | MUTEX_UNLOCK(&accept_mutex); |
0833402a |
246 | #endif |
247 | if(acceptResult < 0) { |
248 | return acceptResult; |
249 | } |
250 | |
66cfae24 |
251 | populate_env(fcgx_req->envp, request->hvEnv); |
0833402a |
252 | |
253 | #ifdef USE_SFIO |
66cfae24 |
254 | for (i = 0; i < 3; ++i) { |
255 | request->io[i] = GvIOn(request->gv[i]); |
256 | if (!(i == 0 ? IoIFP(request->io[i]) : IoOFP(request->io[i]))) { |
257 | IoIFP(request->io[i]) = sftmp(0); |
258 | /*IoIFP(request->io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0, |
5828234f |
259 | SF_STRING | (i ? SF_WRITE : SF_READ));*/ |
66cfae24 |
260 | if (i != 0) |
261 | IoOFP(request->io[i]) = IoIFP(request->io[i]); |
262 | request->sfcreated[i] = TRUE; |
263 | } |
5828234f |
264 | } |
0833402a |
265 | #else |
66cfae24 |
266 | if (!request->svout) { |
267 | newSVrv(request->svout = newSV(0), "FCGI::Stream"); |
268 | newSVrv(request->sverr = newSV(0), "FCGI::Stream"); |
269 | newSVrv(request->svin = newSV(0), "FCGI::Stream"); |
270 | } |
271 | sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out)); |
272 | sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err)); |
273 | sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in)); |
0833402a |
274 | #endif |
66cfae24 |
275 | FCGI_Bind(request); |
276 | request->accepted = TRUE; |
0833402a |
277 | } |
278 | return 0; |
279 | } |
280 | |
281 | static void |
66cfae24 |
282 | FCGI_Finish(FCGP_Request* request) { |
0833402a |
283 | #ifdef USE_SFIO |
284 | int i; |
285 | #endif |
286 | int was_bound; |
287 | dTHX; |
288 | |
66cfae24 |
289 | if(!request->accepted) |
290 | return; |
0833402a |
291 | |
66cfae24 |
292 | if (was_bound = request->bound) |
293 | FCGI_UndoBinding(request); |
0833402a |
294 | #ifdef USE_SFIO |
295 | for (i = 0; i < 3; ++i) { |
66cfae24 |
296 | if (request->sfcreated[i]) { |
297 | sfclose(IoIFP(request->io[i])); |
298 | IoIFP(request->io[i]) = IoOFP(request->io[i]) = Nullfp; |
299 | request->sfcreated[i] = FALSE; |
300 | } |
0833402a |
301 | } |
302 | #endif |
303 | if (was_bound) |
66cfae24 |
304 | FCGX_Finish_r(request->requestPtr); |
0833402a |
305 | else |
66cfae24 |
306 | FCGX_Free(request->requestPtr, 1); |
0833402a |
307 | request->accepted = FALSE; |
308 | } |
309 | |
310 | static int |
66cfae24 |
311 | FCGI_StartFilterData(FCGP_Request* request) { |
0833402a |
312 | return request->requestPtr->in ? |
5828234f |
313 | FCGX_StartFilterData(request->requestPtr->in) : -1; |
0833402a |
314 | } |
315 | |
316 | static FCGP_Request * |
66cfae24 |
317 | FCGI_Request(GV *in, GV *out, GV *err, HV *env, int socket, int flags) { |
0833402a |
318 | FCGX_Request* fcgx_req; |
319 | FCGP_Request* req; |
320 | |
321 | Newz(551, fcgx_req, 1, FCGX_Request); |
322 | FCGX_InitRequest(fcgx_req, socket, flags); |
323 | Newz(551, req, 1, FCGP_Request); |
324 | req->requestPtr = fcgx_req; |
a6b22a6e |
325 | SvREFCNT_inc(in); |
0833402a |
326 | req->gv[0] = in; |
a6b22a6e |
327 | SvREFCNT_inc(out); |
0833402a |
328 | req->gv[1] = out; |
a6b22a6e |
329 | SvREFCNT_inc(err); |
0833402a |
330 | req->gv[2] = err; |
a6b22a6e |
331 | SvREFCNT_inc(env); |
0833402a |
332 | req->hvEnv = env; |
333 | |
334 | return req; |
335 | } |
336 | |
337 | static void |
66cfae24 |
338 | FCGI_Release_Request(FCGP_Request *req) { |
a6b22a6e |
339 | SvREFCNT_dec(req->gv[0]); |
340 | SvREFCNT_dec(req->gv[1]); |
341 | SvREFCNT_dec(req->gv[2]); |
342 | SvREFCNT_dec(req->hvEnv); |
0833402a |
343 | FCGI_Finish(req); |
344 | Safefree(req->requestPtr); |
345 | Safefree(req); |
346 | } |
347 | |
348 | static void |
66cfae24 |
349 | FCGI_Init() { |
0833402a |
350 | #if defined(USE_LOCKING) && defined(USE_THREADS) |
351 | dTHX; |
0833402a |
352 | MUTEX_INIT(&accept_mutex); |
353 | #endif |
0833402a |
354 | FCGX_Init(); |
355 | } |
356 | |
66cfae24 |
357 | typedef FCGX_Stream* FCGI__Stream; |
358 | typedef FCGP_Request* FCGI; |
359 | typedef GV* GLOBREF; |
360 | typedef HV* HASHREF; |
0833402a |
361 | |
66cfae24 |
362 | MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_ |
0833402a |
363 | |
364 | BOOT: |
365 | FCGI_Init(); |
366 | |
367 | SV * |
368 | RequestX(in, out, err, env, socket, flags) |
369 | GLOBREF in; |
370 | GLOBREF out; |
371 | GLOBREF err; |
372 | HASHREF env; |
5828234f |
373 | int socket; |
374 | int flags; |
66cfae24 |
375 | PROTOTYPE: ***$$$ |
376 | CODE: |
0833402a |
377 | RETVAL = sv_setref_pv(newSV(0), "FCGI", |
5828234f |
378 | FCGI_Request(in, out, err, env, socket, flags)); |
66cfae24 |
379 | OUTPUT: |
0833402a |
380 | RETVAL |
381 | |
382 | int |
383 | OpenSocket(path, backlog) |
384 | char* path; |
385 | int backlog; |
66cfae24 |
386 | PROTOTYPE: $$ |
387 | CODE: |
0833402a |
388 | RETVAL = FCGX_OpenSocket(path, backlog); |
66cfae24 |
389 | OUTPUT: |
0833402a |
390 | RETVAL |
391 | |
392 | void |
393 | CloseSocket(socket) |
394 | int socket; |
66cfae24 |
395 | PROTOTYPE: $ |
396 | CODE: |
0833402a |
397 | close(socket); |
398 | |
399 | int |
400 | FCGI_Accept(request) |
0833402a |
401 | FCGI request; |
66cfae24 |
402 | PROTOTYPE: $ |
0833402a |
403 | |
404 | void |
405 | FCGI_Finish(request) |
66cfae24 |
406 | FCGI request; |
407 | PROTOTYPE: $ |
0833402a |
408 | |
409 | void |
410 | FCGI_Flush(request) |
66cfae24 |
411 | FCGI request; |
412 | PROTOTYPE: $ |
0833402a |
413 | |
414 | HV * |
415 | GetEnvironment(request) |
66cfae24 |
416 | FCGI request; |
417 | PROTOTYPE: $ |
418 | CODE: |
0833402a |
419 | RETVAL = request->hvEnv; |
66cfae24 |
420 | OUTPUT: |
0833402a |
421 | RETVAL |
422 | |
423 | void |
424 | GetHandles(request) |
66cfae24 |
425 | FCGI request; |
426 | PROTOTYPE: $ |
427 | PREINIT: |
428 | int i; |
429 | PPCODE: |
0833402a |
430 | EXTEND(sp,3); |
431 | for (i = 0; i < 3; ++i) |
66cfae24 |
432 | PUSHs(sv_2mortal(newRV((SV *) request->gv[i]))); |
0833402a |
433 | |
434 | int |
435 | FCGI_IsFastCGI(request) |
66cfae24 |
436 | FCGI request; |
437 | PROTOTYPE: $ |
0833402a |
438 | |
439 | void |
440 | Detach(request) |
66cfae24 |
441 | FCGI request; |
442 | PROTOTYPE: $ |
443 | CODE: |
fdee298f |
444 | if (request->accepted && request->bound) { |
445 | FCGI_UndoBinding(request); |
446 | FCGX_Detach(request->requestPtr); |
447 | } |
0833402a |
448 | |
449 | void |
450 | Attach(request) |
66cfae24 |
451 | FCGI request; |
452 | PROTOTYPE: $ |
453 | CODE: |
fdee298f |
454 | if (request->accepted && !request->bound) { |
455 | FCGI_Bind(request); |
456 | FCGX_Attach(request->requestPtr); |
457 | } |
0833402a |
458 | |
7fa2de73 |
459 | void |
460 | LastCall(request) |
66cfae24 |
461 | FCGI request; |
462 | PROTOTYPE: $ |
463 | CODE: |
7fa2de73 |
464 | FCGX_ShutdownPending(); |
0833402a |
465 | |
466 | int |
467 | FCGI_StartFilterData(request) |
66cfae24 |
468 | FCGI request; |
469 | PROTOTYPE: $ |
0833402a |
470 | |
471 | void |
472 | DESTROY(request) |
66cfae24 |
473 | FCGI request; |
474 | CODE: |
0833402a |
475 | FCGI_Release_Request(request); |
476 | |
66cfae24 |
477 | MODULE = FCGI PACKAGE = FCGI::Stream |
0833402a |
478 | |
479 | #ifndef USE_SFIO |
480 | |
cd90e76f |
481 | SV * |
0833402a |
482 | PRINT(stream, ...) |
66cfae24 |
483 | FCGI::Stream stream; |
484 | PREINIT: |
cd90e76f |
485 | int n; |
2f33e704 |
486 | STRLEN len; |
487 | register char *str; |
cd90e76f |
488 | bool ok = TRUE; |
66cfae24 |
489 | CODE: |
cd90e76f |
490 | for (n = 1; ok && n < items; ++n) { |
c9234f83 |
491 | #ifdef DO_UTF8 |
c27c9505 |
492 | if (DO_UTF8(ST(n)) && !sv_utf8_downgrade(ST(n), 1) && ckWARN_d(WARN_UTF8)) |
493 | Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::PRINT"); |
c9234f83 |
494 | #endif |
2f33e704 |
495 | str = (char *)SvPV(ST(n),len); |
cd90e76f |
496 | if (FCGX_PutStr(str, len, stream) < 0) |
497 | ok = FALSE; |
29829dde |
498 | } |
5828234f |
499 | if (ok && SvTRUEx(perl_get_sv("|", FALSE)) && FCGX_FFlush(stream) < 0) |
500 | ok = FALSE; |
cd90e76f |
501 | RETVAL = ok ? &PL_sv_yes : &PL_sv_undef; |
66cfae24 |
502 | OUTPUT: |
503 | RETVAL |
0833402a |
504 | |
505 | int |
506 | WRITE(stream, bufsv, len, ...) |
66cfae24 |
507 | FCGI::Stream stream; |
508 | SV *bufsv; |
5828234f |
509 | int len; |
66cfae24 |
510 | PREINIT: |
5828234f |
511 | int offset; |
66cfae24 |
512 | char *buf; |
513 | STRLEN blen; |
5828234f |
514 | int n; |
66cfae24 |
515 | CODE: |
5828234f |
516 | offset = (items == 4) ? (int)SvIV(ST(3)) : 0; |
c9234f83 |
517 | #ifdef DO_UTF8 |
c27c9505 |
518 | if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8)) |
519 | Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::WRITE"); |
c9234f83 |
520 | #endif |
5828234f |
521 | buf = SvPV(bufsv, blen); |
522 | if (offset < 0) offset += blen; |
523 | if (len > blen - offset) |
524 | len = blen - offset; |
525 | if (offset < 0 || offset >= blen || |
526 | (n = FCGX_PutStr(buf+offset, len, stream)) < 0) |
527 | ST(0) = &PL_sv_undef; |
528 | else { |
529 | ST(0) = sv_newmortal(); |
530 | sv_setiv(ST(0), n); |
531 | } |
0833402a |
532 | |
533 | int |
534 | READ(stream, bufsv, len, ...) |
66cfae24 |
535 | FCGI::Stream stream; |
536 | SV *bufsv; |
5828234f |
537 | int len; |
66cfae24 |
538 | PREINIT: |
5828234f |
539 | int offset; |
66cfae24 |
540 | char *buf; |
541 | CODE: |
5828234f |
542 | offset = (items == 4) ? (int)SvIV(ST(3)) : 0; |
c9234f83 |
543 | #ifdef DO_UTF8 |
544 | if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1)) |
545 | croak("Wide character in FCGI::Stream::READ"); |
546 | #endif |
66cfae24 |
547 | if (!SvOK(bufsv)) |
5828234f |
548 | sv_setpvn(bufsv, "", 0); |
549 | buf = SvGROW(bufsv, len+offset+1); |
550 | len = FCGX_GetStr(buf+offset, len, stream); |
551 | SvCUR_set(bufsv, len+offset); |
552 | *SvEND(bufsv) = '\0'; |
553 | (void)SvPOK_only(bufsv); |
554 | SvSETMAGIC(bufsv); |
555 | RETVAL = len; |
66cfae24 |
556 | OUTPUT: |
5828234f |
557 | RETVAL |
0833402a |
558 | |
559 | SV * |
560 | GETC(stream) |
66cfae24 |
561 | FCGI::Stream stream; |
562 | PREINIT: |
5828234f |
563 | int retval; |
66cfae24 |
564 | CODE: |
5828234f |
565 | if ((retval = FCGX_GetChar(stream)) != -1) { |
566 | ST(0) = sv_newmortal(); |
567 | sv_setpvf(ST(0), "%c", retval); |
66cfae24 |
568 | } |
569 | else |
570 | ST(0) = &PL_sv_undef; |
0833402a |
571 | |
572 | bool |
573 | CLOSE(stream) |
66cfae24 |
574 | FCGI::Stream stream; |
575 | CODE: |
5828234f |
576 | RETVAL = FCGX_FClose(stream) != -1; |
66cfae24 |
577 | OUTPUT: |
5828234f |
578 | RETVAL |
0833402a |
579 | |
580 | #endif |