Removed support for SFIO
[catagits/fcgi2.git] / perl / FCGI.XL
CommitLineData
0833402a 1use Config;
2
3open OUT, ">FCGI.xs";
4
5print "Generating FCGI.xs for Perl version $]\n";
6#unless (exists $Config{apiversion} && $Config{apiversion} >= 5.005)
7unless ($] >= 5.005) {
8 for (qw(sv_undef diehook warnhook in_eval)) {
5828234f 9 print OUT "#define PL_$_ $_\n"
0833402a 10 }
11}
12print OUT while <DATA>;
13close OUT;
14__END__
fdee298f 15/* $Id: FCGI.XL,v 1.10 2003/06/22 00:24:11 robs Exp $ */
0833402a 16
17#include "EXTERN.h"
18#include "perl.h"
19#include "XSUB.h"
20
21#include "fcgi_config.h"
22#include "fcgiapp.h"
23#include "fastcgi.h"
24
25#ifndef FALSE
26#define FALSE (0)
27#endif
28
29#ifndef TRUE
30#define TRUE (1)
31#endif
32
33#ifndef dTHX
34#define dTHX
35#endif
36
0c1fdec9 37#ifndef INT2PTR
38#define INT2PTR(a,b) ((a) (b))
39#endif
40
0833402a 41#if defined(USE_LOCKING) && defined(USE_THREADS)
66cfae24 42static perl_mutex accept_mutex;
0833402a 43#endif
44
45typedef struct FCGP_Request {
5828234f 46 int accepted;
47 int bound;
48 SV* svin;
49 SV* svout;
50 SV* sverr;
51 GV* gv[3];
52 HV* hvEnv;
0833402a 53 FCGX_Request* requestPtr;
0833402a 54} FCGP_Request;
55
56static void FCGI_Finish(FCGP_Request* request);
57
9b60732b 58static void
66cfae24 59FCGI_Flush(FCGP_Request* request) {
0833402a 60 dTHX;
66cfae24 61 if(!request->bound)
62 return;
9c31872c 63 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->svout))));
64 FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->sverr))));
0833402a 65}
66
67static void
66cfae24 68FCGI_UndoBinding(FCGP_Request* request) {
0833402a 69 dTHX;
d99074f3 70#ifdef USE_PERLIO
849cab1e 71 sv_unmagic((SV *)GvIOp(request->gv[0]), 'q');
72 sv_unmagic((SV *)GvIOp(request->gv[1]), 'q');
73 sv_unmagic((SV *)GvIOp(request->gv[2]), 'q');
d99074f3 74#else
0833402a 75 sv_unmagic((SV *)request->gv[0], 'q');
76 sv_unmagic((SV *)request->gv[1], 'q');
77 sv_unmagic((SV *)request->gv[2], 'q');
78#endif
79 request->bound = FALSE;
80}
81
82static void
66cfae24 83FCGI_Bind(FCGP_Request* request) {
0833402a 84 dTHX;
d99074f3 85#ifdef USE_PERLIO
6d7e3fb2 86 /* For tied filehandles, we apply tiedscalar magic to the IO
87 slot of the GP rather than the GV itself. */
88
89 if (!GvIOp(request->gv[1]))
66cfae24 90 GvIOp(request->gv[1]) = newIO();
6d7e3fb2 91 if (!GvIOp(request->gv[2]))
66cfae24 92 GvIOp(request->gv[2]) = newIO();
6d7e3fb2 93 if (!GvIOp(request->gv[0]))
66cfae24 94 GvIOp(request->gv[0]) = newIO();
6d7e3fb2 95
96 sv_magic((SV *)GvIOp(request->gv[1]), request->svout, 'q', Nullch, 0);
97 sv_magic((SV *)GvIOp(request->gv[2]), request->sverr, 'q', Nullch, 0);
98 sv_magic((SV *)GvIOp(request->gv[0]), request->svin, 'q', Nullch, 0);
d99074f3 99#else
0833402a 100 sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0);
101 sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0);
102 sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);
103#endif
104 request->bound = TRUE;
105}
106
107static void
66cfae24 108populate_env(char **envp, HV *hv) {
0833402a 109 int i;
110 char *p, *p1;
66cfae24 111 SV *sv;
0833402a 112 dTHX;
113
114 hv_clear(hv);
115 for(i = 0; ; i++) {
66cfae24 116 if((p = envp[i]) == NULL)
117 break;
118 p1 = strchr(p, '=');
119 assert(p1 != NULL);
120 sv = newSVpv(p1 + 1, 0);
121 /* call magic for this value ourselves */
122 hv_store(hv, p, p1 - p, sv, 0);
123 SvSETMAGIC(sv);
0833402a 124 }
125}
126
127static int
66cfae24 128FCGI_IsFastCGI(FCGP_Request* request) {
0833402a 129 static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: CGI */
130
131 if (request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO) {
66cfae24 132 if (isCGI == -1)
133 isCGI = FCGX_IsCGI();
134 return !isCGI;
0833402a 135 }
136
137 /* A explicit socket is being used -> assume FastCGI */
138 return 1;
139}
140
141static int
66cfae24 142FCGI_Accept(FCGP_Request* request) {
0833402a 143 dTHX;
144
145 if (!FCGI_IsFastCGI(request)) {
66cfae24 146 static int been_here = 0;
0833402a 147
148 /*
66cfae24 149 * Not first call to FCGI_Accept and running as CGI means
150 * application is done.
151 */
152 if (been_here)
153 return EOF;
154 been_here = 1;
155 }
156 else {
66cfae24 157 FCGX_Request *fcgx_req = request->requestPtr;
0833402a 158 int acceptResult;
159
66cfae24 160 FCGI_Finish(request);
0833402a 161#if defined(USE_LOCKING) && defined(USE_THREADS)
66cfae24 162 MUTEX_LOCK(&accept_mutex);
0833402a 163#endif
66cfae24 164 acceptResult = FCGX_Accept_r(fcgx_req);
0833402a 165#if defined(USE_LOCKING) && defined(USE_THREADS)
66cfae24 166 MUTEX_UNLOCK(&accept_mutex);
0833402a 167#endif
168 if(acceptResult < 0) {
169 return acceptResult;
170 }
171
66cfae24 172 populate_env(fcgx_req->envp, request->hvEnv);
0833402a 173
66cfae24 174 if (!request->svout) {
175 newSVrv(request->svout = newSV(0), "FCGI::Stream");
176 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
177 newSVrv(request->svin = newSV(0), "FCGI::Stream");
178 }
179 sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out));
180 sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err));
181 sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in));
66cfae24 182 FCGI_Bind(request);
183 request->accepted = TRUE;
0833402a 184 }
185 return 0;
186}
187
188static void
66cfae24 189FCGI_Finish(FCGP_Request* request) {
0833402a 190 int was_bound;
191 dTHX;
192
66cfae24 193 if(!request->accepted)
194 return;
0833402a 195
66cfae24 196 if (was_bound = request->bound)
197 FCGI_UndoBinding(request);
0833402a 198 if (was_bound)
66cfae24 199 FCGX_Finish_r(request->requestPtr);
0833402a 200 else
66cfae24 201 FCGX_Free(request->requestPtr, 1);
0833402a 202 request->accepted = FALSE;
203}
204
205static int
66cfae24 206FCGI_StartFilterData(FCGP_Request* request) {
0833402a 207 return request->requestPtr->in ?
5828234f 208 FCGX_StartFilterData(request->requestPtr->in) : -1;
0833402a 209}
210
211static FCGP_Request *
66cfae24 212FCGI_Request(GV *in, GV *out, GV *err, HV *env, int socket, int flags) {
0833402a 213 FCGX_Request* fcgx_req;
214 FCGP_Request* req;
215
216 Newz(551, fcgx_req, 1, FCGX_Request);
217 FCGX_InitRequest(fcgx_req, socket, flags);
218 Newz(551, req, 1, FCGP_Request);
219 req->requestPtr = fcgx_req;
a6b22a6e 220 SvREFCNT_inc(in);
0833402a 221 req->gv[0] = in;
a6b22a6e 222 SvREFCNT_inc(out);
0833402a 223 req->gv[1] = out;
a6b22a6e 224 SvREFCNT_inc(err);
0833402a 225 req->gv[2] = err;
a6b22a6e 226 SvREFCNT_inc(env);
0833402a 227 req->hvEnv = env;
228
229 return req;
230}
231
232static void
66cfae24 233FCGI_Release_Request(FCGP_Request *req) {
a6b22a6e 234 SvREFCNT_dec(req->gv[0]);
235 SvREFCNT_dec(req->gv[1]);
236 SvREFCNT_dec(req->gv[2]);
237 SvREFCNT_dec(req->hvEnv);
0833402a 238 FCGI_Finish(req);
239 Safefree(req->requestPtr);
240 Safefree(req);
241}
242
243static void
66cfae24 244FCGI_Init() {
0833402a 245#if defined(USE_LOCKING) && defined(USE_THREADS)
246 dTHX;
0833402a 247 MUTEX_INIT(&accept_mutex);
248#endif
0833402a 249 FCGX_Init();
250}
251
66cfae24 252typedef FCGX_Stream* FCGI__Stream;
253typedef FCGP_Request* FCGI;
254typedef GV* GLOBREF;
255typedef HV* HASHREF;
0833402a 256
66cfae24 257MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_
0833402a 258
259BOOT:
260 FCGI_Init();
261
262SV *
263RequestX(in, out, err, env, socket, flags)
264 GLOBREF in;
265 GLOBREF out;
266 GLOBREF err;
267 HASHREF env;
5828234f 268 int socket;
269 int flags;
66cfae24 270 PROTOTYPE: ***$$$
271 CODE:
0833402a 272 RETVAL = sv_setref_pv(newSV(0), "FCGI",
5828234f 273 FCGI_Request(in, out, err, env, socket, flags));
66cfae24 274 OUTPUT:
0833402a 275 RETVAL
276
277int
278OpenSocket(path, backlog)
279 char* path;
280 int backlog;
66cfae24 281 PROTOTYPE: $$
282 CODE:
0833402a 283 RETVAL = FCGX_OpenSocket(path, backlog);
66cfae24 284 OUTPUT:
0833402a 285 RETVAL
286
287void
288CloseSocket(socket)
289 int socket;
66cfae24 290 PROTOTYPE: $
291 CODE:
0833402a 292 close(socket);
293
294int
295FCGI_Accept(request)
0833402a 296 FCGI request;
66cfae24 297 PROTOTYPE: $
0833402a 298
299void
300FCGI_Finish(request)
66cfae24 301 FCGI request;
302 PROTOTYPE: $
0833402a 303
304void
305FCGI_Flush(request)
66cfae24 306 FCGI request;
307 PROTOTYPE: $
0833402a 308
309HV *
310GetEnvironment(request)
66cfae24 311 FCGI request;
312 PROTOTYPE: $
313 CODE:
0833402a 314 RETVAL = request->hvEnv;
66cfae24 315 OUTPUT:
0833402a 316 RETVAL
317
318void
319GetHandles(request)
66cfae24 320 FCGI request;
321 PROTOTYPE: $
322 PREINIT:
323 int i;
324 PPCODE:
0833402a 325 EXTEND(sp,3);
326 for (i = 0; i < 3; ++i)
66cfae24 327 PUSHs(sv_2mortal(newRV((SV *) request->gv[i])));
0833402a 328
329int
330FCGI_IsFastCGI(request)
66cfae24 331 FCGI request;
332 PROTOTYPE: $
0833402a 333
334void
335Detach(request)
66cfae24 336 FCGI request;
337 PROTOTYPE: $
338 CODE:
fdee298f 339 if (request->accepted && request->bound) {
340 FCGI_UndoBinding(request);
341 FCGX_Detach(request->requestPtr);
342 }
0833402a 343
344void
345Attach(request)
66cfae24 346 FCGI request;
347 PROTOTYPE: $
348 CODE:
fdee298f 349 if (request->accepted && !request->bound) {
350 FCGI_Bind(request);
351 FCGX_Attach(request->requestPtr);
352 }
0833402a 353
7fa2de73 354void
355LastCall(request)
66cfae24 356 FCGI request;
357 PROTOTYPE: $
358 CODE:
7fa2de73 359 FCGX_ShutdownPending();
0833402a 360
361int
362FCGI_StartFilterData(request)
66cfae24 363 FCGI request;
364 PROTOTYPE: $
0833402a 365
366void
367DESTROY(request)
66cfae24 368 FCGI request;
369 CODE:
0833402a 370 FCGI_Release_Request(request);
371
66cfae24 372MODULE = FCGI PACKAGE = FCGI::Stream
0833402a 373
cd90e76f 374SV *
0833402a 375PRINT(stream, ...)
66cfae24 376 FCGI::Stream stream;
377 PREINIT:
cd90e76f 378 int n;
2f33e704 379 STRLEN len;
380 register char *str;
cd90e76f 381 bool ok = TRUE;
66cfae24 382 CODE:
cd90e76f 383 for (n = 1; ok && n < items; ++n) {
c9234f83 384#ifdef DO_UTF8
c27c9505 385 if (DO_UTF8(ST(n)) && !sv_utf8_downgrade(ST(n), 1) && ckWARN_d(WARN_UTF8))
386 Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::PRINT");
c9234f83 387#endif
2f33e704 388 str = (char *)SvPV(ST(n),len);
cd90e76f 389 if (FCGX_PutStr(str, len, stream) < 0)
390 ok = FALSE;
29829dde 391 }
5828234f 392 if (ok && SvTRUEx(perl_get_sv("|", FALSE)) && FCGX_FFlush(stream) < 0)
393 ok = FALSE;
cd90e76f 394 RETVAL = ok ? &PL_sv_yes : &PL_sv_undef;
66cfae24 395 OUTPUT:
396 RETVAL
0833402a 397
398int
399WRITE(stream, bufsv, len, ...)
66cfae24 400 FCGI::Stream stream;
401 SV *bufsv;
5828234f 402 int len;
66cfae24 403 PREINIT:
5828234f 404 int offset;
66cfae24 405 char *buf;
406 STRLEN blen;
5828234f 407 int n;
66cfae24 408 CODE:
5828234f 409 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
c9234f83 410#ifdef DO_UTF8
c27c9505 411 if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8))
412 Perl_warner(aTHX_ WARN_UTF8, "Wide character in FCGI::Stream::WRITE");
c9234f83 413#endif
5828234f 414 buf = SvPV(bufsv, blen);
415 if (offset < 0) offset += blen;
416 if (len > blen - offset)
417 len = blen - offset;
418 if (offset < 0 || offset >= blen ||
419 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
420 ST(0) = &PL_sv_undef;
421 else {
422 ST(0) = sv_newmortal();
423 sv_setiv(ST(0), n);
424 }
0833402a 425
426int
427READ(stream, bufsv, len, ...)
66cfae24 428 FCGI::Stream stream;
429 SV *bufsv;
5828234f 430 int len;
66cfae24 431 PREINIT:
5828234f 432 int offset;
66cfae24 433 char *buf;
434 CODE:
5828234f 435 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
c9234f83 436#ifdef DO_UTF8
437 if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1))
438 croak("Wide character in FCGI::Stream::READ");
439#endif
66cfae24 440 if (!SvOK(bufsv))
5828234f 441 sv_setpvn(bufsv, "", 0);
442 buf = SvGROW(bufsv, len+offset+1);
443 len = FCGX_GetStr(buf+offset, len, stream);
444 SvCUR_set(bufsv, len+offset);
445 *SvEND(bufsv) = '\0';
446 (void)SvPOK_only(bufsv);
447 SvSETMAGIC(bufsv);
448 RETVAL = len;
66cfae24 449 OUTPUT:
5828234f 450 RETVAL
0833402a 451
452SV *
453GETC(stream)
66cfae24 454 FCGI::Stream stream;
455 PREINIT:
5828234f 456 int retval;
66cfae24 457 CODE:
5828234f 458 if ((retval = FCGX_GetChar(stream)) != -1) {
459 ST(0) = sv_newmortal();
460 sv_setpvf(ST(0), "%c", retval);
66cfae24 461 }
462 else
463 ST(0) = &PL_sv_undef;
0833402a 464
465bool
466CLOSE(stream)
66cfae24 467 FCGI::Stream stream;
468 CODE:
5828234f 469 RETVAL = FCGX_FClose(stream) != -1;
66cfae24 470 OUTPUT:
5828234f 471 RETVAL