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.12 1999/08/27 13:28:47 skimo Exp $ */
21 #include "fcgi_config.h"
44 sffcgiread(f, buf, n, disc)
45 Sfio_t* f; /* stream involved */
46 Void_t* buf; /* buffer to read into */
47 size_t n; /* number of bytes to read */
48 Sfdisc_t* disc; /* discipline */
50 return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);
54 sffcgiwrite(f, buf, n, disc)
55 Sfio_t* f; /* stream involved */
56 const Void_t* buf; /* buffer to read into */
57 size_t n; /* number of bytes to read */
58 Sfdisc_t* disc; /* discipline */
60 n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream);
61 FCGX_FFlush(((FCGI_Disc *)disc)->stream);
71 New(1000,disc,1,FCGI_Disc);
72 if (!disc) return (Sfdisc_t *)disc;
74 disc->disc.exceptf = (Sfexcept_f)NULL;
75 disc->disc.seekf = (Sfseek_f)NULL;
76 disc->disc.readf = sffcgiread;
77 disc->disc.writef = sffcgiwrite;
78 disc->stream = stream;
79 return (Sfdisc_t *)disc;
91 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: FCGI */
93 #if defined(USE_LOCKING) && defined(USE_THREADS)
94 static perl_mutex accept_mutex;
97 typedef struct FCGP_Request {
104 FCGX_Request* requestPtr;
111 FCGI_Flush(FCGP_Request* request)
115 if(!request->bound) {
119 sfsync(IoOFP(GvIOp(request->gv[1])));
120 sfsync(IoOFP(GvIOp(request->gv[2])));
122 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout)));
123 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr)));
128 FCGI_UndoBinding(FCGP_Request* request)
137 sfdcdelfcgi(sfdisc(IoIFP(io[0] = GvIOp(request->gv[0])), SF_POPDISC));
138 sfdcdelfcgi(sfdisc(IoOFP(io[1] = GvIOp(request->gv[1])), SF_POPDISC));
139 sfdcdelfcgi(sfdisc(IoOFP(io[2] = GvIOp(request->gv[2])), SF_POPDISC));
140 for (i = 0; i < 3; ++i) {
141 if (request->sfcreated[i]) {
142 sfclose(IoIFP(io[i]));
143 IoIFP(io[i]) = IoOFP(io[i]) = Nullfp;
144 request->sfcreated[i] = FALSE;
149 sv_unmagic((SV *)request->gv[0], 'q');
150 sv_unmagic((SV *)request->gv[1], 'q');
151 sv_unmagic((SV *)request->gv[2], 'q');
153 FCGX_Finish_r(request->requestPtr);
154 request->bound = FALSE;
158 populate_env(envp, hv)
169 if((p = envp[i]) == NULL) {
174 sv = newSVpv(p1 + 1, 0);
175 /* call magic for this value ourselves */
176 hv_store(hv, p, p1 - p, sv, 0);
182 FCGI_Accept(FCGP_Request* request)
188 * First call to FCGI_Accept. Is application running
189 * as FastCGI or as CGI?
191 isCGI = FCGX_IsCGI();
194 * Not first call to FCGI_Accept and running as CGI means
195 * application is done.
204 FCGX_Request *fcgx_req = request->requestPtr;
208 FCGI_UndoBinding(request);
210 #if defined(USE_LOCKING) && defined(USE_THREADS)
211 MUTEX_LOCK(&accept_mutex);
213 acceptResult = FCGX_Accept_r(fcgx_req);
214 #if defined(USE_LOCKING) && defined(USE_THREADS)
215 MUTEX_UNLOCK(&accept_mutex);
217 if(acceptResult < 0) {
221 populate_env(fcgx_req->envp, request->hvEnv);
224 for (i = 0; i < 3; ++i) {
225 io[i] = GvIOn(request->gv[i]);
226 if (!(i == 0 ? IoIFP(io[i]) : IoOFP(io[i]))) {
227 IoIFP(io[i]) = sftmp(0);
228 /*IoIFP(io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0,
229 SF_STRING | (i ? SF_WRITE : SF_READ));*/
230 if (i != 0) IoOFP(io[i]) = IoIFP(io[i]);
231 request->sfcreated[i] = TRUE;
234 sfdisc(IoIFP(io[0]), sfdcnewfcgi(fcgx_req->in));
235 sfdisc(IoOFP(io[1]), sfdcnewfcgi(fcgx_req->out));
236 sfdisc(IoOFP(io[2]), sfdcnewfcgi(fcgx_req->err));
238 if (!request->svout) {
239 newSVrv(request->svout = newSV(0), "FCGI::Stream");
240 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
241 newSVrv(request->svin = newSV(0), "FCGI::Stream");
243 sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0);
244 sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0);
245 sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);
246 sv_setiv(SvRV(request->svout), (IV) fcgx_req->out);
247 sv_setiv(SvRV(request->sverr), (IV) fcgx_req->err);
248 sv_setiv(SvRV(request->svin), (IV) fcgx_req->in);
250 request->bound = TRUE;
256 FCGI_Finish(FCGP_Request* request)
260 if(!request->bound) {
263 FCGI_UndoBinding(request);
267 FCGI_StartFilterData(FCGP_Request* request)
269 return request->requestPtr->in ?
270 FCGX_StartFilterData(request->requestPtr->in) : -1;
273 static FCGP_Request *
274 FCGI_Request(in, out, err, env, socket, flags)
282 FCGX_Request* fcgx_req;
285 Newz(551, fcgx_req, 1, FCGX_Request);
286 FCGX_InitRequest(fcgx_req, socket, flags);
287 Newz(551, req, 1, FCGP_Request);
288 req->requestPtr = fcgx_req;
298 FCGI_Release_Request(FCGP_Request *req)
301 Safefree(req->requestPtr);
308 #if defined(USE_LOCKING) && defined(USE_THREADS)
311 MUTEX_INIT(&accept_mutex);
315 typedef FCGX_Stream * FCGI__Stream;
316 typedef FCGP_Request * FCGI;
320 MODULE = FCGI PACKAGE = FCGI
326 RequestX(in, out, err, env, socket, flags)
336 RETVAL = sv_setref_pv(newSV(0), "FCGI",
337 FCGI_Request(in, out, err, env, socket, flags));
343 OpenSocket(path, backlog)
349 RETVAL = FCGX_OpenSocket(path, backlog);
369 RETVAL = FCGI_Accept(request);
385 * Finish the request.
387 FCGI_Finish(request);
403 StartFilterData(request)
410 RETVAL = FCGI_StartFilterData(request);
420 FCGI_Release_Request(request);
424 MODULE = FCGI PACKAGE = FCGI::Stream
436 for (n = 1; n < items; ++n) {
438 register char *tmps = (char *)SvPV(ST(n),len);
439 FCGX_PutStr(tmps, len, stream);
441 if (SvTRUEx(perl_get_sv("|", FALSE)))
445 WRITE(stream, bufsv, len, ...)
457 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
458 buf = SvPV(bufsv, blen);
459 if (offset < 0) offset += blen;
460 if (len > blen - offset)
462 if (offset < 0 || offset >= blen ||
463 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
464 ST(0) = &PL_sv_undef;
466 ST(0) = sv_newmortal();
467 sv_setpvf(ST(0), "%c", n);
471 READ(stream, bufsv, len, ...)
481 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
483 sv_setpvn(bufsv, "", 0);
484 buf = SvGROW(bufsv, len+offset+1);
485 len = FCGX_GetStr(buf+offset, len, stream);
486 SvCUR_set(bufsv, len+offset);
487 *SvEND(bufsv) = '\0';
488 (void)SvPOK_only(bufsv);
503 if ((retval = FCGX_GetChar(stream)) != -1) {
504 ST(0) = sv_newmortal();
505 sv_setpvf(ST(0), "%c", retval);
506 } else ST(0) = &PL_sv_undef;
516 RETVAL = FCGX_FClose(stream) != -1;