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.7 2001/10/11 19:36:04 skimo Exp $ */
21 #include "fcgi_config.h"
38 #define INT2PTR(a,b) ((a) (b))
49 sffcgiread(f, buf, n, disc)
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 */
55 return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);
59 sffcgiwrite(f, buf, n, disc)
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 */
65 n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream);
66 FCGX_FFlush(((FCGI_Disc *)disc)->stream);
76 New(1000,disc,1,FCGI_Disc);
77 if (!disc) return (Sfdisc_t *)disc;
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;
96 #if defined(USE_LOCKING) && defined(USE_THREADS)
97 static perl_mutex accept_mutex;
100 typedef struct FCGP_Request {
108 FCGX_Request* requestPtr;
115 static void FCGI_Finish(FCGP_Request* request);
118 FCGI_Flush(FCGP_Request* request)
122 if(!request->bound) {
126 sfsync(IoOFP(GvIOp(request->gv[1])));
127 sfsync(IoOFP(GvIOp(request->gv[2])));
129 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->svout))));
130 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->sverr))));
135 FCGI_UndoBinding(FCGP_Request* request)
140 sfdcdelfcgi(sfdisc(IoIFP(request->io[0]), SF_POPDISC));
141 sfdcdelfcgi(sfdisc(IoOFP(request->io[1]), SF_POPDISC));
142 sfdcdelfcgi(sfdisc(IoOFP(request->io[2]), SF_POPDISC));
144 sv_unmagic((SV *)request->gv[0], 'q');
145 sv_unmagic((SV *)request->gv[1], 'q');
146 sv_unmagic((SV *)request->gv[2], 'q');
148 request->bound = FALSE;
152 FCGI_Bind(FCGP_Request* request)
157 sfdisc(IoIFP(request->io[0]), sfdcnewfcgi(request->requestPtr->in));
158 sfdisc(IoOFP(request->io[1]), sfdcnewfcgi(request->requestPtr->out));
159 sfdisc(IoOFP(request->io[2]), sfdcnewfcgi(request->requestPtr->err));
161 sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0);
162 sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0);
163 sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);
165 request->bound = TRUE;
169 populate_env(envp, hv)
180 if((p = envp[i]) == NULL) {
185 sv = newSVpv(p1 + 1, 0);
186 /* call magic for this value ourselves */
187 hv_store(hv, p, p1 - p, sv, 0);
193 FCGI_IsFastCGI(FCGP_Request* request)
195 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: CGI */
197 if (request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO) {
199 isCGI = FCGX_IsCGI();
203 /* A explicit socket is being used -> assume FastCGI */
208 FCGI_Accept(FCGP_Request* request)
212 if (!FCGI_IsFastCGI(request)) {
213 static int been_here = 0;
216 * Not first call to FCGI_Accept and running as CGI means
217 * application is done.
227 FCGX_Request *fcgx_req = request->requestPtr;
230 FCGI_Finish(request);
231 #if defined(USE_LOCKING) && defined(USE_THREADS)
232 MUTEX_LOCK(&accept_mutex);
234 acceptResult = FCGX_Accept_r(fcgx_req);
235 #if defined(USE_LOCKING) && defined(USE_THREADS)
236 MUTEX_UNLOCK(&accept_mutex);
238 if(acceptResult < 0) {
242 populate_env(fcgx_req->envp, request->hvEnv);
245 for (i = 0; i < 3; ++i) {
246 request->io[i] = GvIOn(request->gv[i]);
247 if (!(i == 0 ? IoIFP(request->io[i])
248 : IoOFP(request->io[i]))) {
249 IoIFP(request->io[i]) = sftmp(0);
250 /*IoIFP(request->io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0,
251 SF_STRING | (i ? SF_WRITE : SF_READ));*/
253 IoOFP(request->io[i]) = IoIFP(request->io[i]);
254 request->sfcreated[i] = TRUE;
258 if (!request->svout) {
259 newSVrv(request->svout = newSV(0), "FCGI::Stream");
260 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
261 newSVrv(request->svin = newSV(0), "FCGI::Stream");
263 sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out));
264 sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err));
265 sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in));
268 request->accepted = TRUE;
274 FCGI_Finish(FCGP_Request* request)
282 if(!request->accepted) {
286 if (was_bound = request->bound) {
287 FCGI_UndoBinding(request);
290 for (i = 0; i < 3; ++i) {
291 if (request->sfcreated[i]) {
292 sfclose(IoIFP(request->io[i]));
293 IoIFP(request->io[i]) = IoOFP(request->io[i]) = Nullfp;
294 request->sfcreated[i] = FALSE;
299 FCGX_Finish_r(request->requestPtr);
301 FCGX_Free(request->requestPtr, 1);
302 request->accepted = FALSE;
306 FCGI_StartFilterData(FCGP_Request* request)
308 return request->requestPtr->in ?
309 FCGX_StartFilterData(request->requestPtr->in) : -1;
312 static FCGP_Request *
313 FCGI_Request(in, out, err, env, socket, flags)
321 FCGX_Request* fcgx_req;
324 Newz(551, fcgx_req, 1, FCGX_Request);
325 FCGX_InitRequest(fcgx_req, socket, flags);
326 Newz(551, req, 1, FCGP_Request);
327 req->requestPtr = fcgx_req;
341 FCGI_Release_Request(FCGP_Request *req)
343 SvREFCNT_dec(req->gv[0]);
344 SvREFCNT_dec(req->gv[1]);
345 SvREFCNT_dec(req->gv[2]);
346 SvREFCNT_dec(req->hvEnv);
348 Safefree(req->requestPtr);
355 #if defined(USE_LOCKING) && defined(USE_THREADS)
358 MUTEX_INIT(&accept_mutex);
364 typedef FCGX_Stream * FCGI__Stream;
365 typedef FCGP_Request * FCGI;
369 MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_
375 RequestX(in, out, err, env, socket, flags)
385 RETVAL = sv_setref_pv(newSV(0), "FCGI",
386 FCGI_Request(in, out, err, env, socket, flags));
392 OpenSocket(path, backlog)
398 RETVAL = FCGX_OpenSocket(path, backlog);
430 GetEnvironment(request)
436 RETVAL = request->hvEnv;
452 for (i = 0; i < 3; ++i)
453 PUSHs(sv_2mortal(newRV((SV *) request->gv[i])));
456 FCGI_IsFastCGI(request)
468 if (request->accepted && request->bound)
469 FCGI_UndoBinding(request);
478 if (request->accepted && !request->bound)
488 FCGX_ShutdownPending();
491 FCGI_StartFilterData(request)
502 FCGI_Release_Request(request);
506 MODULE = FCGI PACKAGE = FCGI::Stream
518 for (n = 1; n < items; ++n) {
520 register char *tmps = (char *)SvPV(ST(n),len);
521 FCGX_PutStr(tmps, len, stream);
523 if (SvTRUEx(perl_get_sv("|", FALSE)))
527 WRITE(stream, bufsv, len, ...)
539 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
540 buf = SvPV(bufsv, blen);
541 if (offset < 0) offset += blen;
542 if (len > blen - offset)
544 if (offset < 0 || offset >= blen ||
545 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
546 ST(0) = &PL_sv_undef;
548 ST(0) = sv_newmortal();
549 sv_setpvf(ST(0), "%c", n);
553 READ(stream, bufsv, len, ...)
563 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
565 sv_setpvn(bufsv, "", 0);
566 buf = SvGROW(bufsv, len+offset+1);
567 len = FCGX_GetStr(buf+offset, len, stream);
568 SvCUR_set(bufsv, len+offset);
569 *SvEND(bufsv) = '\0';
570 (void)SvPOK_only(bufsv);
585 if ((retval = FCGX_GetChar(stream)) != -1) {
586 ST(0) = sv_newmortal();
587 sv_setpvf(ST(0), "%c", retval);
588 } else ST(0) = &PL_sv_undef;
598 RETVAL = FCGX_FClose(stream) != -1;