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.10 1999/08/03 15:52:53 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 {
106 FCGX_Request* requestPtr;
113 FCGI_Flush(FCGP_Request* request)
117 if(!request->bound) {
121 sfsync(IoOFP(GvIOp(request->gv[1])));
122 sfsync(IoOFP(GvIOp(request->gv[2])));
124 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout)));
125 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr)));
130 FCGI_UndoBinding(FCGP_Request* request)
139 sfdcdelfcgi(sfdisc(IoIFP(io[0] = GvIOp(request->gv[0])), SF_POPDISC));
140 sfdcdelfcgi(sfdisc(IoOFP(io[1] = GvIOp(request->gv[1])), SF_POPDISC));
141 sfdcdelfcgi(sfdisc(IoOFP(io[2] = GvIOp(request->gv[2])), SF_POPDISC));
142 for (i = 0; i < 3; ++i) {
143 if (request->sfcreated[i]) {
144 sfclose(IoIFP(io[i]));
145 IoIFP(io[i]) = IoOFP(io[i]) = Nullfp;
146 request->sfcreated[i] = FALSE;
151 sv_unmagic((SV *)request->gv[0], 'q');
152 sv_unmagic((SV *)request->gv[1], 'q');
153 sv_unmagic((SV *)request->gv[2], 'q');
156 FCGX_Finish_r(request->requestPtr);
157 request->bound = FALSE;
161 populate_env(envp, hv)
171 if((p = envp[i]) == NULL) {
176 sv = newSVpv(p1 + 1, 0);
177 /* call magic for this value ourselves */
178 hv_store(hv, p, p1 - p, sv, 0);
184 FCGI_Accept(FCGP_Request* request)
190 * First call to FCGI_Accept. Is application running
191 * as FastCGI or as CGI?
193 isCGI = FCGX_IsCGI();
196 * Not first call to FCGI_Accept and running as CGI means
197 * application is done.
206 FCGX_Stream *out, *error;
207 FCGX_ParamArray envp;
211 FCGI_UndoBinding(request);
213 #if defined(USE_LOCKING) && defined(USE_THREADS)
214 MUTEX_LOCK(&accept_mutex);
216 acceptResult = FCGX_Accept_r(&request->in, &out, &error,
217 &envp, request->requestPtr);
218 #if defined(USE_LOCKING) && defined(USE_THREADS)
219 MUTEX_UNLOCK(&accept_mutex);
221 if(acceptResult < 0) {
225 populate_env(envp, request->hvEnv);
228 for (i = 0; i < 3; ++i) {
229 io[i] = GvIOn(request->gv[i] = request->gvNew[i]);
230 if (!(i == 0 ? IoIFP(io[i]) : IoOFP(io[i]))) {
231 IoIFP(io[i]) = sftmp(0);
232 /*IoIFP(io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0,
233 SF_STRING | (i ? SF_WRITE : SF_READ));*/
234 if (i != 0) IoOFP(io[i]) = IoIFP(io[i]);
235 request->sfcreated[i] = TRUE;
238 sfdisc(IoIFP(io[0]), sfdcnewfcgi(request->in));
239 sfdisc(IoOFP(io[1]), sfdcnewfcgi(out));
240 sfdisc(IoOFP(io[2]), sfdcnewfcgi(error));
242 if (!request->svout) {
243 newSVrv(request->svout = newSV(0), "FCGI::Stream");
244 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
245 newSVrv(request->svin = newSV(0), "FCGI::Stream");
247 sv_magic((SV *)request->gv[1] = request->gvNew[1],
248 request->svout, 'q', Nullch, 0);
249 sv_magic((SV *)request->gv[2] = request->gvNew[2],
250 request->sverr, 'q', Nullch, 0);
251 sv_magic((SV *)request->gv[0] = request->gvNew[0],
252 request->svin, 'q', Nullch, 0);
253 sv_setiv(SvRV(request->svout), (IV) out);
254 sv_setiv(SvRV(request->sverr), (IV) error);
255 sv_setiv(SvRV(request->svin), (IV) request->in);
257 request->bound = TRUE;
263 FCGI_Finish(FCGP_Request* request)
267 if(!request->bound) {
270 FCGI_UndoBinding(request);
274 FCGI_StartFilterData(FCGP_Request* request)
276 return request->in ? FCGX_StartFilterData(request->in) : -1;
280 FCGI_SetExitStatus(FCGP_Request* request, int status)
282 if (request->in) FCGX_SetExitStatus(status, request->in);
285 static FCGP_Request *
288 FCGX_Request* fcgx_req;
291 Newz(551, fcgx_req, 1, FCGX_Request);
292 Newz(551, req, 1, FCGP_Request);
293 req->requestPtr = fcgx_req;
299 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
330 RETVAL = sv_setref_pv(newSV(0), "FCGI", FCGI_Request());
337 Accept(request, in, out, err, env)
348 request->gvNew[0] = in;
349 request->gvNew[1] = out;
350 request->gvNew[2] = err;
351 request->hvEnv = env;
353 RETVAL = FCGI_Accept(request);
369 * Finish the request.
371 FCGI_Finish(request);
387 StartFilterData(request)
394 RETVAL = FCGI_StartFilterData(request);
404 FCGI_Release_Request(request);
408 MODULE = FCGI PACKAGE = FCGI::Stream
420 for (n = 1; n < items; ++n) {
422 register char *tmps = (char *)SvPV(ST(n),len);
423 FCGX_PutStr(tmps, len, stream);
425 if (SvTRUEx(perl_get_sv("|", FALSE)))
429 WRITE(stream, bufsv, len, ...)
441 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
442 buf = SvPV(bufsv, blen);
443 if (offset < 0) offset += blen;
444 if (len > blen - offset)
446 if (offset < 0 || offset >= blen ||
447 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
448 ST(0) = &PL_sv_undef;
450 ST(0) = sv_newmortal();
451 sv_setpvf(ST(0), "%c", n);
455 READ(stream, bufsv, len, ...)
465 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
467 sv_setpvn(bufsv, "", 0);
468 buf = SvGROW(bufsv, len+offset+1);
469 len = FCGX_GetStr(buf+offset, len, stream);
470 SvCUR_set(bufsv, len+offset);
471 *SvEND(bufsv) = '\0';
472 (void)SvPOK_only(bufsv);
487 if ((retval = FCGX_GetChar(stream)) != -1) {
488 ST(0) = sv_newmortal();
489 sv_setpvf(ST(0), "%c", retval);
490 } else ST(0) = &PL_sv_undef;
500 RETVAL = FCGX_FClose(stream) != -1;