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.PL,v 1.15 2000/07/10 09:56:49 skimo Exp $ */
21 #include "fcgi_config.h"
45 sffcgiread(f, buf, n, disc)
46 Sfio_t* f; /* stream involved */
47 Void_t* buf; /* buffer to read into */
48 size_t n; /* number of bytes to read */
49 Sfdisc_t* disc; /* discipline */
51 return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);
55 sffcgiwrite(f, buf, n, disc)
56 Sfio_t* f; /* stream involved */
57 const Void_t* buf; /* buffer to read into */
58 size_t n; /* number of bytes to read */
59 Sfdisc_t* disc; /* discipline */
61 n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream);
62 FCGX_FFlush(((FCGI_Disc *)disc)->stream);
72 New(1000,disc,1,FCGI_Disc);
73 if (!disc) return (Sfdisc_t *)disc;
75 disc->disc.exceptf = (Sfexcept_f)NULL;
76 disc->disc.seekf = (Sfseek_f)NULL;
77 disc->disc.readf = sffcgiread;
78 disc->disc.writef = sffcgiwrite;
79 disc->stream = stream;
80 return (Sfdisc_t *)disc;
92 #if defined(USE_LOCKING) && defined(USE_THREADS)
93 static perl_mutex accept_mutex;
96 typedef struct FCGP_Request {
104 FCGX_Request* requestPtr;
111 static void FCGI_Finish(FCGP_Request* request);
114 FCGI_Flush(FCGP_Request* request)
118 if(!request->bound) {
122 sfsync(IoOFP(GvIOp(request->gv[1])));
123 sfsync(IoOFP(GvIOp(request->gv[2])));
125 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout)));
126 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr)));
131 FCGI_UndoBinding(FCGP_Request* request)
136 sfdcdelfcgi(sfdisc(IoIFP(request->io[0]), SF_POPDISC));
137 sfdcdelfcgi(sfdisc(IoOFP(request->io[1]), SF_POPDISC));
138 sfdcdelfcgi(sfdisc(IoOFP(request->io[2]), SF_POPDISC));
140 sv_unmagic((SV *)request->gv[0], 'q');
141 sv_unmagic((SV *)request->gv[1], 'q');
142 sv_unmagic((SV *)request->gv[2], 'q');
144 request->bound = FALSE;
148 FCGI_Bind(FCGP_Request* request)
153 sfdisc(IoIFP(request->io[0]), sfdcnewfcgi(request->requestPtr->in));
154 sfdisc(IoOFP(request->io[1]), sfdcnewfcgi(request->requestPtr->out));
155 sfdisc(IoOFP(request->io[2]), sfdcnewfcgi(request->requestPtr->err));
157 sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0);
158 sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0);
159 sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);
161 request->bound = TRUE;
165 populate_env(envp, hv)
176 if((p = envp[i]) == NULL) {
181 sv = newSVpv(p1 + 1, 0);
182 /* call magic for this value ourselves */
183 hv_store(hv, p, p1 - p, sv, 0);
189 FCGI_Accept(FCGP_Request* request)
191 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: FCGI */
194 request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO ?
199 if(req_isCGI == -1) {
201 * First call to FCGI_Accept. Is application running
202 * as FastCGI or as CGI?
204 req_isCGI = isCGI = FCGX_IsCGI();
205 } else if(req_isCGI) {
207 * Not first call to FCGI_Accept and running as CGI means
208 * application is done.
216 FCGX_Request *fcgx_req = request->requestPtr;
219 FCGI_Finish(request);
220 #if defined(USE_LOCKING) && defined(USE_THREADS)
221 MUTEX_LOCK(&accept_mutex);
223 acceptResult = FCGX_Accept_r(fcgx_req);
224 #if defined(USE_LOCKING) && defined(USE_THREADS)
225 MUTEX_UNLOCK(&accept_mutex);
227 if(acceptResult < 0) {
231 populate_env(fcgx_req->envp, request->hvEnv);
234 for (i = 0; i < 3; ++i) {
235 request->io[i] = GvIOn(request->gv[i]);
236 if (!(i == 0 ? IoIFP(request->io[i])
237 : IoOFP(request->io[i]))) {
238 IoIFP(request->io[i]) = sftmp(0);
239 /*IoIFP(request->io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0,
240 SF_STRING | (i ? SF_WRITE : SF_READ));*/
242 IoOFP(request->io[i]) = IoIFP(request->io[i]);
243 request->sfcreated[i] = TRUE;
247 if (!request->svout) {
248 newSVrv(request->svout = newSV(0), "FCGI::Stream");
249 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
250 newSVrv(request->svin = newSV(0), "FCGI::Stream");
252 sv_setiv(SvRV(request->svout), (IV) fcgx_req->out);
253 sv_setiv(SvRV(request->sverr), (IV) fcgx_req->err);
254 sv_setiv(SvRV(request->svin), (IV) fcgx_req->in);
257 request->accepted = TRUE;
263 FCGI_Finish(FCGP_Request* request)
270 if(!request->accepted) {
274 if (request->bound) {
275 FCGI_UndoBinding(request);
278 for (i = 0; i < 3; ++i) {
279 if (request->sfcreated[i]) {
280 sfclose(IoIFP(request->io[i]));
281 IoIFP(request->io[i]) = IoOFP(request->io[i]) = Nullfp;
282 request->sfcreated[i] = FALSE;
286 FCGX_Finish_r(request->requestPtr);
287 request->accepted = FALSE;
291 FCGI_StartFilterData(FCGP_Request* request)
293 return request->requestPtr->in ?
294 FCGX_StartFilterData(request->requestPtr->in) : -1;
297 static FCGP_Request *
298 FCGI_Request(in, out, err, env, socket, flags)
306 FCGX_Request* fcgx_req;
309 Newz(551, fcgx_req, 1, FCGX_Request);
310 FCGX_InitRequest(fcgx_req, socket, flags);
311 Newz(551, req, 1, FCGP_Request);
312 req->requestPtr = fcgx_req;
322 FCGI_Release_Request(FCGP_Request *req)
325 Safefree(req->requestPtr);
332 #if defined(USE_LOCKING) && defined(USE_THREADS)
335 MUTEX_INIT(&accept_mutex);
339 typedef FCGX_Stream * FCGI__Stream;
340 typedef FCGP_Request * FCGI;
344 MODULE = FCGI PACKAGE = FCGI
350 RequestX(in, out, err, env, socket, flags)
360 RETVAL = sv_setref_pv(newSV(0), "FCGI",
361 FCGI_Request(in, out, err, env, socket, flags));
367 OpenSocket(path, backlog)
373 RETVAL = FCGX_OpenSocket(path, backlog);
393 RETVAL = FCGI_Accept(request);
409 * Finish the request.
411 FCGI_Finish(request);
433 if (request->accepted && request->bound)
434 FCGI_UndoBinding(request);
444 if (request->accepted && !request->bound)
449 StartFilterData(request)
456 RETVAL = FCGI_StartFilterData(request);
466 FCGI_Release_Request(request);
470 MODULE = FCGI PACKAGE = FCGI::Stream
482 for (n = 1; n < items; ++n) {
484 register char *tmps = (char *)SvPV(ST(n),len);
485 FCGX_PutStr(tmps, len, stream);
487 if (SvTRUEx(perl_get_sv("|", FALSE)))
491 WRITE(stream, bufsv, len, ...)
503 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
504 buf = SvPV(bufsv, blen);
505 if (offset < 0) offset += blen;
506 if (len > blen - offset)
508 if (offset < 0 || offset >= blen ||
509 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
510 ST(0) = &PL_sv_undef;
512 ST(0) = sv_newmortal();
513 sv_setpvf(ST(0), "%c", n);
517 READ(stream, bufsv, len, ...)
527 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
529 sv_setpvn(bufsv, "", 0);
530 buf = SvGROW(bufsv, len+offset+1);
531 len = FCGX_GetStr(buf+offset, len, stream);
532 SvCUR_set(bufsv, len+offset);
533 *SvEND(bufsv) = '\0';
534 (void)SvPOK_only(bufsv);
549 if ((retval = FCGX_GetChar(stream)) != -1) {
550 ST(0) = sv_newmortal();
551 sv_setpvf(ST(0), "%c", retval);
552 } else ST(0) = &PL_sv_undef;
562 RETVAL = FCGX_FClose(stream) != -1;