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.4 1999/07/28 16:15:40 skimo Exp $ */
32 #define environ _environ
35 extern char **environ;
36 static char **requestEnviron = NULL;
46 sffcgiread(f, buf, n, disc)
47 Sfio_t* f; /* stream involved */
48 Void_t* buf; /* buffer to read into */
49 size_t n; /* number of bytes to read */
50 Sfdisc_t* disc; /* discipline */
52 return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);
56 sffcgiwrite(f, buf, n, disc)
57 Sfio_t* f; /* stream involved */
58 const Void_t* buf; /* buffer to read into */
59 size_t n; /* number of bytes to read */
60 Sfdisc_t* disc; /* discipline */
62 n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream);
63 FCGX_FFlush(((FCGI_Disc *)disc)->stream);
73 New(1000,disc,1,FCGI_Disc);
74 if (!disc) return (Sfdisc_t *)disc;
76 disc->disc.exceptf = (Sfexcept_f)NULL;
77 disc->disc.seekf = (Sfseek_f)NULL;
78 disc->disc.readf = sffcgiread;
79 disc->disc.writef = sffcgiwrite;
80 disc->stream = stream;
81 return (Sfdisc_t *)disc;
93 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: FCGI */
95 static FCGX_Request global_fcgx_request;
97 typedef struct FCGP_Request {
105 FCGX_Request* requestPtr;
108 static FCGP_Request global_request;
109 static SV* global_sverr;
112 FCGI_Flush(FCGP_Request* request)
114 if(!request->compat || !request->acceptCalled || isCGI) {
118 sfsync(PerlIO_stdout());
119 sfsync(PerlIO_stderr());
121 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout)));
122 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr)));
127 FCGI_Accept(FCGP_Request* request)
131 * First call to FCGI_Accept. Is application running
132 * as FastCGI or as CGI?
134 isCGI = FCGX_IsCGI();
137 * Not first call to FCGI_Accept and running as CGI means
138 * application is done.
142 if(request->compat && !request->finishCalled) {
144 sfdcdelfcgi(sfdisc(PerlIO_stdin(), SF_POPDISC));
145 sfdcdelfcgi(sfdisc(PerlIO_stdout(), SF_POPDISC));
146 sfdcdelfcgi(sfdisc(PerlIO_stderr(), SF_POPDISC));
153 FCGX_ParamArray envp;
154 FCGX_Stream *out, *error;
155 int acceptResult = FCGX_Accept_r(&request->in, &out, &error, &envp,
156 request->requestPtr);
157 if(acceptResult < 0) {
161 sfdisc(PerlIO_stdin(), sfdcnewfcgi(request->in));
162 sfdisc(PerlIO_stdout(), sfdcnewfcgi(out));
163 sfdisc(PerlIO_stderr(), sfdcnewfcgi(error));
165 if (!request->svout) {
166 newSVrv(request->svout = newSV(0), "FCGI");
167 sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO),
168 request->svout, 'q', Nullch, 0);
169 newSVrv(request->sverr = newSV(0), "FCGI");
170 sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO),
171 request->sverr, 'q', Nullch, 0);
172 newSVrv(request->svin = newSV(0), "FCGI");
173 sv_magic((SV *)gv_fetchpv("STDIN",TRUE, SVt_PVIO),
174 request->svin, 'q', Nullch, 0);
176 sv_setiv(SvRV(request->svout), (IV) out);
177 sv_setiv(SvRV(request->sverr), (IV) error);
178 sv_setiv(SvRV(request->svin), (IV) request->in);
180 if (request->compat) {
181 global_sverr = request->sverr;
182 if (PL_warnhook) SvREFCNT_dec(PL_warnhook);
183 PL_warnhook = SvREFCNT_inc(GvCV(gv_fetchmethod(Nullhv, "FCGI::WARN")));
184 if (PL_diehook) SvREFCNT_dec(PL_diehook);
185 PL_diehook = SvREFCNT_inc(GvCV(gv_fetchmethod(Nullhv, "FCGI::DIE")));
188 request->finishCalled = FALSE;
191 request->acceptCalled = TRUE;
196 FCGI_Finish(FCGP_Request* request)
198 if(!request->acceptCalled || isCGI) {
201 if (request->compat) {
203 sfdcdelfcgi(sfdisc(PerlIO_stdin(), SF_POPDISC));
204 sfdcdelfcgi(sfdisc(PerlIO_stdout(), SF_POPDISC));
205 sfdcdelfcgi(sfdisc(PerlIO_stderr(), SF_POPDISC));
211 FCGX_Finish_r(request->requestPtr);
212 request->finishCalled = TRUE;
214 if (request->compat) {
215 if (PL_warnhook == (SV*)GvCV(gv_fetchmethod(Nullhv, "FCGI::WARN"))) {
216 SvREFCNT_dec(PL_warnhook);
217 PL_warnhook = Nullsv;
219 if (PL_diehook == (SV*)GvCV(gv_fetchmethod(Nullhv, "FCGI::DIE"))) {
220 SvREFCNT_dec(PL_diehook);
228 FCGI_StartFilterData(FCGP_Request* request)
230 return request->in ? FCGX_StartFilterData(request->in) : -1;
234 FCGI_SetExitStatus(FCGP_Request* request, int status)
236 if (request->in) FCGX_SetExitStatus(status, request->in);
239 static FCGP_Request *
242 FCGX_Request* fcgx_req;
245 Newz(551, fcgx_req, 1, FCGX_Request);
246 Newz(551, req, 1, FCGP_Request);
247 req->requestPtr = fcgx_req;
253 FCGI_Release_Request(FCGP_Request *req)
255 Safefree(req->requestPtr);
260 * For each variable in the array envp, either set or unset it
261 * in the global hash %ENV.
272 hv = perl_get_hv("ENV", TRUE);
275 perl_eval_pv("%ENV = %FCGI::ENV", 0);
277 perl_eval_pv("%FCGI::ENV = %ENV", 0);
279 if((p = envp[i]) == NULL) {
285 sv = newSVpv(p1 + 1, 0);
286 /* call magic for this value ourselves */
287 hv_store(hv, p, p1 - p, sv, 0);
295 typedef FCGX_Stream * FCGI;
296 typedef FCGP_Request * FCGI__Request;
298 MODULE = FCGI PACKAGE = FCGI
302 FCGX_InitRequest(&global_fcgx_request);
303 memset(&global_request, 0, sizeof(global_request));
304 global_request.compat = 1;
305 global_request.requestPtr = &global_fcgx_request;
314 FCGX_PutS(msg, (FCGX_Stream *) SvIV((SV*) SvRV(global_sverr)));
321 FCGX_PutS(msg, (FCGX_Stream *) SvIV((SV*) SvRV(global_sverr)));
331 for (n = 1; n < items; ++n) {
333 register char *tmps = (char *)SvPV(ST(n),len);
334 FCGX_PutStr(tmps, len, stream);
336 if (SvTRUEx(perl_get_sv("|", FALSE)))
340 WRITE(stream, bufsv, len, ...)
352 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
353 buf = SvPV(bufsv, blen);
354 if (offset < 0) offset += blen;
355 if (len > blen - offset)
357 if (offset < 0 || offset >= blen ||
358 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
359 ST(0) = &PL_sv_undef;
361 ST(0) = sv_newmortal();
362 sv_setpvf(ST(0), "%c", n);
366 READ(stream, bufsv, len, ...)
376 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
378 sv_setpvn(bufsv, "", 0);
379 buf = SvGROW(bufsv, len+offset+1);
380 len = FCGX_GetStr(buf+offset, len, stream);
381 SvCUR_set(bufsv, len+offset);
382 *SvEND(bufsv) = '\0';
383 (void)SvPOK_only(bufsv);
398 if ((retval = FCGX_GetChar(stream)) != -1) {
399 ST(0) = sv_newmortal();
400 sv_setpvf(ST(0), "%c", retval);
401 } else ST(0) = &PL_sv_undef;
411 RETVAL = FCGX_FClose(stream) != -1;
423 RETVAL = Perl_sv_setref_pv(Perl_newSV(0), "FCGI::Request", FCGI_Request());
435 FCGP_Request* request = &global_request;
439 if (items != 0 && items != 5)
440 croak("Usage: FCGI::accept() or "
441 "FCGI::accept(request, IN, OUT, ERR, env)");
443 if (sv_isa(ST(0), "FCGI::Request")) {
444 request = (FCGP_Request*) SvIV((SV*)SvRV(ST(0)));
446 croak("request is not of type FCGI::Request");
447 if (SvROK(ST(1)) && isGV(SvRV(ST(1)))) {
449 croak("IN is not a GLOB reference");
455 * Unmake Perl variable settings for the request just completed.
457 if(requestEnviron != NULL) {
458 DoPerlEnv(requestEnviron, FALSE);
459 requestEnviron = NULL;
462 * Call FCGI_Accept but preserve environ.
464 savedEnviron = environ;
465 acceptStatus = FCGI_Accept(request);
466 requestEnviron = environ;
467 environ = savedEnviron;
469 * Make Perl variable settings for the new request.
471 if(acceptStatus >= 0 && !FCGX_IsCGI()) {
472 DoPerlEnv(requestEnviron, TRUE);
474 requestEnviron = NULL;
476 RETVAL = acceptStatus;
489 * Unmake Perl variable settings for the completed request.
491 if(requestEnviron != NULL) {
492 DoPerlEnv(requestEnviron, FALSE);
493 requestEnviron = NULL;
496 * Finish the request.
498 FCGI_Finish(&global_request);
507 FCGI_Flush(&global_request);
510 set_exit_status(status,...)
516 FCGI_SetExitStatus(&global_request, status);
519 start_filter_data(...)
523 RETVAL = FCGI_StartFilterData(&global_request);
528 MODULE = FCGI PACKAGE = FCGI::Request
532 FCGI::Request request;
535 FCGI_Release_Request(request);