5 print "Generating FCGI.xs for Perl version $]\n";
6 #unless (exists $Config{apiversion} && $Config{apiversion} >= 5.005)
8 for (qw(sv_undef diehook warnhook in_eval)) {
9 print OUT "#define PL_$_ $_\n"
12 print OUT while <DATA>;
15 /* $Id: FCGI.XL,v 1.10 2003/06/22 00:24:11 robs Exp $ */
21 #include "fcgi_config.h"
38 #define INT2PTR(a,b) ((a) (b))
41 #if defined(USE_LOCKING) && defined(USE_THREADS)
42 static perl_mutex accept_mutex;
45 typedef struct FCGP_Request {
53 FCGX_Request* requestPtr;
56 static void FCGI_Finish(FCGP_Request* request);
59 FCGI_Flush(FCGP_Request* request) {
63 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->svout))));
64 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->sverr))));
68 FCGI_UndoBinding(FCGP_Request* request) {
71 sv_unmagic((SV *)GvIOp(request->gv[0]), 'q');
72 sv_unmagic((SV *)GvIOp(request->gv[1]), 'q');
73 sv_unmagic((SV *)GvIOp(request->gv[2]), 'q');
75 sv_unmagic((SV *)request->gv[0], 'q');
76 sv_unmagic((SV *)request->gv[1], 'q');
77 sv_unmagic((SV *)request->gv[2], 'q');
79 request->bound = FALSE;
83 FCGI_Bind(FCGP_Request* request) {
86 /* For tied filehandles, we apply tiedscalar magic to the IO
87 slot of the GP rather than the GV itself. */
89 if (!GvIOp(request->gv[1]))
90 GvIOp(request->gv[1]) = newIO();
91 if (!GvIOp(request->gv[2]))
92 GvIOp(request->gv[2]) = newIO();
93 if (!GvIOp(request->gv[0]))
94 GvIOp(request->gv[0]) = newIO();
96 sv_magic((SV *)GvIOp(request->gv[1]), request->svout, 'q', Nullch, 0);
97 sv_magic((SV *)GvIOp(request->gv[2]), request->sverr, 'q', Nullch, 0);
98 sv_magic((SV *)GvIOp(request->gv[0]), request->svin, 'q', Nullch, 0);
100 sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0);
101 sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0);
102 sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);
104 request->bound = TRUE;
108 populate_env(char **envp, HV *hv) {
116 if((p = envp[i]) == NULL)
120 sv = newSVpv(p1 + 1, 0);
121 /* call magic for this value ourselves */
122 hv_store(hv, p, p1 - p, sv, 0);
128 FCGI_IsFastCGI(FCGP_Request* request) {
129 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: CGI */
131 if (request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO) {
133 isCGI = FCGX_IsCGI();
137 /* A explicit socket is being used -> assume FastCGI */
142 FCGI_Accept(FCGP_Request* request) {
145 if (!FCGI_IsFastCGI(request)) {
146 static int been_here = 0;
149 * Not first call to FCGI_Accept and running as CGI means
150 * application is done.
157 FCGX_Request *fcgx_req = request->requestPtr;
160 FCGI_Finish(request);
161 #if defined(USE_LOCKING) && defined(USE_THREADS)
162 MUTEX_LOCK(&accept_mutex);
164 acceptResult = FCGX_Accept_r(fcgx_req);
165 #if defined(USE_LOCKING) && defined(USE_THREADS)
166 MUTEX_UNLOCK(&accept_mutex);
168 if(acceptResult < 0) {
172 populate_env(fcgx_req->envp, request->hvEnv);
174 if (!request->svout) {
175 newSVrv(request->svout = newSV(0), "FCGI::Stream");
176 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
177 newSVrv(request->svin = newSV(0), "FCGI::Stream");
179 sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out));
180 sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err));
181 sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in));
183 request->accepted = TRUE;
189 FCGI_Finish(FCGP_Request* request) {
193 if(!request->accepted)
196 if (was_bound = request->bound)
197 FCGI_UndoBinding(request);
199 FCGX_Finish_r(request->requestPtr);
201 FCGX_Free(request->requestPtr, 1);
202 request->accepted = FALSE;
206 FCGI_StartFilterData(FCGP_Request* request) {
207 return request->requestPtr->in ?
208 FCGX_StartFilterData(request->requestPtr->in) : -1;
211 static FCGP_Request *
212 FCGI_Request(GV *in, GV *out, GV *err, HV *env, int socket, int flags) {
213 FCGX_Request* fcgx_req;
216 Newz(551, fcgx_req, 1, FCGX_Request);
217 FCGX_InitRequest(fcgx_req, socket, flags);
218 Newz(551, req, 1, FCGP_Request);
219 req->requestPtr = fcgx_req;
233 FCGI_Release_Request(FCGP_Request *req) {
234 SvREFCNT_dec(req->gv[0]);
235 SvREFCNT_dec(req->gv[1]);
236 SvREFCNT_dec(req->gv[2]);
237 SvREFCNT_dec(req->hvEnv);
239 Safefree(req->requestPtr);
245 #if defined(USE_LOCKING) && defined(USE_THREADS)
247 MUTEX_INIT(&accept_mutex);
252 typedef FCGX_Stream* FCGI__Stream;
253 typedef FCGP_Request* FCGI;
257 MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_
263 RequestX(in, out, err, env, socket, flags)
272 RETVAL = sv_setref_pv(newSV(0), "FCGI",
273 FCGI_Request(in, out, err, env, socket, flags));
278 OpenSocket(path, backlog)
283 RETVAL = FCGX_OpenSocket(path, backlog);
310 GetEnvironment(request)
314 RETVAL = request->hvEnv;
326 for (i = 0; i < 3; ++i)
327 PUSHs(sv_2mortal(newRV((SV *) request->gv[i])));
330 FCGI_IsFastCGI(request)
339 if (request->accepted && request->bound) {
340 FCGI_UndoBinding(request);
341 FCGX_Detach(request->requestPtr);
349 if (request->accepted && !request->bound) {
351 FCGX_Attach(request->requestPtr);
359 FCGX_ShutdownPending();
362 FCGI_StartFilterData(request)
370 FCGI_Release_Request(request);
372 MODULE = FCGI PACKAGE = FCGI::Stream
383 for (n = 1; ok && n < items; ++n) {
385 if (DO_UTF8(ST(n)) && !sv_utf8_downgrade(ST(n), 1) && ckWARN_d(WARN_UTF8))
386 Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::PRINT");
388 str = (char *)SvPV(ST(n),len);
389 if (FCGX_PutStr(str, len, stream) < 0)
392 if (ok && SvTRUEx(perl_get_sv("|", FALSE)) && FCGX_FFlush(stream) < 0)
394 RETVAL = ok ? &PL_sv_yes : &PL_sv_undef;
399 WRITE(stream, bufsv, len, ...)
409 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
411 if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8))
412 Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::WRITE");
414 buf = SvPV(bufsv, blen);
415 if (offset < 0) offset += blen;
416 if (len > blen - offset)
418 if (offset < 0 || offset >= blen ||
419 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
420 ST(0) = &PL_sv_undef;
422 ST(0) = sv_newmortal();
427 READ(stream, bufsv, len, ...)
435 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
437 if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8))
438 Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::READ");
441 sv_setpvn(bufsv, "", 0);
442 buf = SvGROW(bufsv, len+offset+1);
443 len = FCGX_GetStr(buf+offset, len, stream);
444 SvCUR_set(bufsv, len+offset);
445 *SvEND(bufsv) = '\0';
446 (void)SvPOK_only(bufsv);
458 if ((retval = FCGX_GetChar(stream)) != -1) {
459 ST(0) = sv_newmortal();
460 sv_setpvf(ST(0), "%c", retval);
463 ST(0) = &PL_sv_undef;
469 RETVAL = FCGX_FClose(stream) != -1;