Remove Win #include
[catagits/fcgi2.git] / perl / FCGI.PL
CommitLineData
1b64d24d 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)) {
9 print OUT "#define PL_$_ $_\n"
10 }
11}
12print OUT while <DATA>;
13close OUT;
14__END__
6ff77aff 15/* $Id: FCGI.PL,v 1.11 1999/08/10 11:06:37 skimo Exp $ */
1b64d24d 16
17#include "EXTERN.h"
18#include "perl.h"
19#include "XSUB.h"
20
b716743a 21#include "fcgi_config.h"
1b64d24d 22#include "fcgiapp.h"
23
24#ifndef FALSE
25#define FALSE (0)
26#endif
27
28#ifndef TRUE
29#define TRUE (1)
30#endif
31
b716743a 32#ifndef dTHX
33#define dTHX
34#endif
35
1b64d24d 36#ifdef USE_SFIO
37typedef struct
38{
39 Sfdisc_t disc;
40 FCGX_Stream *stream;
41} FCGI_Disc;
42
43static ssize_t
44sffcgiread(f, buf, n, disc)
45Sfio_t* f; /* stream involved */
46Void_t* buf; /* buffer to read into */
47size_t n; /* number of bytes to read */
48Sfdisc_t* disc; /* discipline */
49{
50 return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);
51}
52
53static ssize_t
54sffcgiwrite(f, buf, n, disc)
55Sfio_t* f; /* stream involved */
56const Void_t* buf; /* buffer to read into */
57size_t n; /* number of bytes to read */
58Sfdisc_t* disc; /* discipline */
59{
60 n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream);
61 FCGX_FFlush(((FCGI_Disc *)disc)->stream);
62 return n;
63}
64
65Sfdisc_t *
66sfdcnewfcgi(stream)
67 FCGX_Stream *stream;
68{
69 FCGI_Disc* disc;
70
71 New(1000,disc,1,FCGI_Disc);
72 if (!disc) return (Sfdisc_t *)disc;
73
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;
80}
81
82Sfdisc_t *
83sfdcdelfcgi(disc)
84 Sfdisc_t* disc;
85{
86 Safefree(disc);
87 return 0;
88}
89#endif
90
90a18d65 91static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: FCGI */
92
b716743a 93#if defined(USE_LOCKING) && defined(USE_THREADS)
94static perl_mutex accept_mutex;
95#endif
96
90a18d65 97typedef struct FCGP_Request {
b716743a 98 int bound;
90a18d65 99 SV* svin;
100 SV* svout;
101 SV* sverr;
eede4b76 102 GV* gv[3];
34bfd355 103 HV* hvEnv;
90a18d65 104 FCGX_Request* requestPtr;
2c38ecd7 105#ifdef USE_SFIO
106 int sfcreated[3];
107#endif
90a18d65 108} FCGP_Request;
109
1b64d24d 110static int
90a18d65 111FCGI_Flush(FCGP_Request* request)
1b64d24d 112{
b716743a 113 dTHX;
114
115 if(!request->bound) {
1b64d24d 116 return;
117 }
118#ifdef USE_SFIO
2c38ecd7 119 sfsync(IoOFP(GvIOp(request->gv[1])));
120 sfsync(IoOFP(GvIOp(request->gv[2])));
1b64d24d 121#else
90a18d65 122 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout)));
123 FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr)));
1b64d24d 124#endif
125}
126
34bfd355 127static void
128FCGI_UndoBinding(FCGP_Request* request)
129{
130#ifdef USE_SFIO
2c38ecd7 131 IO *io[3];
132 int i;
133#endif
b716743a 134 dTHX;
2c38ecd7 135
136#ifdef USE_SFIO
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;
145 }
146 }
34bfd355 147#else
148 FCGI_Flush(request);
149 sv_unmagic((SV *)request->gv[0], 'q');
150 sv_unmagic((SV *)request->gv[1], 'q');
151 sv_unmagic((SV *)request->gv[2], 'q');
152#endif
b716743a 153 FCGX_Finish_r(request->requestPtr);
154 request->bound = FALSE;
155}
156
157static void
158populate_env(envp, hv)
159char **envp;
160HV *hv;
161{
162 int i;
163 char *p, *p1;
164 SV *sv;
165 dTHX;
166
6ff77aff 167 hv_clear(hv);
b716743a 168 for(i = 0; ; i++) {
169 if((p = envp[i]) == NULL) {
170 break;
171 }
172 p1 = strchr(p, '=');
173 assert(p1 != NULL);
174 sv = newSVpv(p1 + 1, 0);
175 /* call magic for this value ourselves */
176 hv_store(hv, p, p1 - p, sv, 0);
177 SvSETMAGIC(sv);
178 }
34bfd355 179}
180
1b64d24d 181static int
cebfd7c4 182FCGI_Accept(FCGP_Request* request)
1b64d24d 183{
b716743a 184 dTHX;
185
90a18d65 186 if(isCGI == -1) {
1b64d24d 187 /*
188 * First call to FCGI_Accept. Is application running
189 * as FastCGI or as CGI?
190 */
191 isCGI = FCGX_IsCGI();
192 } else if(isCGI) {
193 /*
194 * Not first call to FCGI_Accept and running as CGI means
195 * application is done.
196 */
197 return(EOF);
eede4b76 198 }
1b64d24d 199 if(!isCGI) {
2c38ecd7 200#ifdef USE_SFIO
201 IO *io[3];
202 int i;
203#endif
6ff77aff 204 FCGX_Request *fcgx_req = request->requestPtr;
b716743a 205 int acceptResult;
206
207 if(request->bound) {
208 FCGI_UndoBinding(request);
209 }
210#if defined(USE_LOCKING) && defined(USE_THREADS)
211 MUTEX_LOCK(&accept_mutex);
212#endif
6ff77aff 213 acceptResult = FCGX_Accept_r(fcgx_req);
b716743a 214#if defined(USE_LOCKING) && defined(USE_THREADS)
215 MUTEX_UNLOCK(&accept_mutex);
216#endif
1b64d24d 217 if(acceptResult < 0) {
218 return acceptResult;
219 }
d8cc97fb 220
6ff77aff 221 populate_env(fcgx_req->envp, request->hvEnv);
d8cc97fb 222
1b64d24d 223#ifdef USE_SFIO
2c38ecd7 224 for (i = 0; i < 3; ++i) {
6ff77aff 225 io[i] = GvIOn(request->gv[i]);
2c38ecd7 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;
232 }
233 }
6ff77aff 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));
1b64d24d 237#else
90a18d65 238 if (!request->svout) {
eede4b76 239 newSVrv(request->svout = newSV(0), "FCGI::Stream");
eede4b76 240 newSVrv(request->sverr = newSV(0), "FCGI::Stream");
eede4b76 241 newSVrv(request->svin = newSV(0), "FCGI::Stream");
1b64d24d 242 }
6ff77aff 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);
1b64d24d 249#endif
b716743a 250 request->bound = TRUE;
1b64d24d 251 }
1b64d24d 252 return 0;
253}
254
255static void
90a18d65 256FCGI_Finish(FCGP_Request* request)
1b64d24d 257{
b716743a 258 dTHX;
259
260 if(!request->bound) {
1b64d24d 261 return;
262 }
34bfd355 263 FCGI_UndoBinding(request);
1b64d24d 264}
265
266static int
90a18d65 267FCGI_StartFilterData(FCGP_Request* request)
268{
6ff77aff 269 return request->requestPtr->in ?
270 FCGX_StartFilterData(request->requestPtr->in) : -1;
90a18d65 271}
272
273static FCGP_Request *
6ff77aff 274FCGI_Request(in, out, err, env, socket, flags)
275 GV* in;
276 GV* out;
277 GV* err;
278 HV* env;
279 int socket;
280 int flags;
1b64d24d 281{
90a18d65 282 FCGX_Request* fcgx_req;
283 FCGP_Request* req;
284
285 Newz(551, fcgx_req, 1, FCGX_Request);
6ff77aff 286 FCGX_InitRequest(fcgx_req, socket, flags);
90a18d65 287 Newz(551, req, 1, FCGP_Request);
288 req->requestPtr = fcgx_req;
6ff77aff 289 req->gv[0] = in;
290 req->gv[1] = out;
291 req->gv[2] = err;
292 req->hvEnv = env;
90a18d65 293
294 return req;
1b64d24d 295}
296
297static void
90a18d65 298FCGI_Release_Request(FCGP_Request *req)
1b64d24d 299{
6ff77aff 300 FCGI_Finish(req);
90a18d65 301 Safefree(req->requestPtr);
302 Safefree(req);
1b64d24d 303}
304
34bfd355 305static void
b716743a 306FCGI_Init()
34bfd355 307{
b716743a 308#if defined(USE_LOCKING) && defined(USE_THREADS)
309 dTHX;
34bfd355 310
b716743a 311 MUTEX_INIT(&accept_mutex);
312#endif
34bfd355 313}
314
eede4b76 315typedef FCGX_Stream * FCGI__Stream;
316typedef FCGP_Request * FCGI;
d8cc97fb 317typedef GV* GLOBREF;
318typedef HV* HASHREF;
1b64d24d 319
320MODULE = FCGI PACKAGE = FCGI
321
b716743a 322BOOT:
323 FCGI_Init();
eede4b76 324
325SV *
6ff77aff 326RequestX(in, out, err, env, socket, flags)
327 GLOBREF in;
328 GLOBREF out;
329 GLOBREF err;
330 HASHREF env;
331 int socket;
332 int flags;
eede4b76 333
6ff77aff 334 PROTOTYPE: ***$$$
eede4b76 335 CODE:
6ff77aff 336 RETVAL = sv_setref_pv(newSV(0), "FCGI",
337 FCGI_Request(in, out, err, env, socket, flags));
eede4b76 338
339 OUTPUT:
340 RETVAL
341
342
343int
6ff77aff 344Accept(request)
eede4b76 345
d8cc97fb 346 FCGI request;
eede4b76 347
6ff77aff 348 PROTOTYPE: $
eede4b76 349
350 CODE:
d8cc97fb 351 RETVAL = FCGI_Accept(request);
eede4b76 352
eede4b76 353 OUTPUT:
354 RETVAL
355
356
357void
d8cc97fb 358Finish(request)
eede4b76 359
d8cc97fb 360 FCGI request;
eede4b76 361
d8cc97fb 362 PROTOTYPE: $
eede4b76 363
364 CODE:
eede4b76 365 {
366 /*
eede4b76 367 * Finish the request.
368 */
369 FCGI_Finish(request);
370 }
371
372
373void
d8cc97fb 374Flush(request)
eede4b76 375
d8cc97fb 376 FCGI request;
eede4b76 377
d8cc97fb 378 PROTOTYPE: $
eede4b76 379
380 CODE:
eede4b76 381 FCGI_Flush(request);
382
eede4b76 383
384int
d8cc97fb 385StartFilterData(request)
eede4b76 386
d8cc97fb 387 FCGI request;
eede4b76 388
d8cc97fb 389 PROTOTYPE: $
eede4b76 390
391 CODE:
eede4b76 392 RETVAL = FCGI_StartFilterData(request);
393
394 OUTPUT:
395 RETVAL
396
eede4b76 397void
398DESTROY(request)
399 FCGI request;
400
401 CODE:
402 FCGI_Release_Request(request);
403
404
405
406MODULE = FCGI PACKAGE = FCGI::Stream
90a18d65 407
1b64d24d 408#ifndef USE_SFIO
1b64d24d 409
410void
411PRINT(stream, ...)
eede4b76 412 FCGI::Stream stream;
1b64d24d 413
414 PREINIT:
415 int n;
416
417 CODE:
418 for (n = 1; n < items; ++n) {
419 STRLEN len;
420 register char *tmps = (char *)SvPV(ST(n),len);
421 FCGX_PutStr(tmps, len, stream);
422 }
423 if (SvTRUEx(perl_get_sv("|", FALSE)))
424 FCGX_FFlush(stream);
425
426int
427WRITE(stream, bufsv, len, ...)
eede4b76 428 FCGI::Stream stream;
1b64d24d 429 SV * bufsv;
430 int len;
431
432 PREINIT:
433 int offset;
434 char * buf;
435 STRLEN blen;
436 int n;
437
438 CODE:
439 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
440 buf = SvPV(bufsv, blen);
441 if (offset < 0) offset += blen;
442 if (len > blen - offset)
443 len = blen - offset;
444 if (offset < 0 || offset >= blen ||
445 (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
446 ST(0) = &PL_sv_undef;
447 else {
448 ST(0) = sv_newmortal();
449 sv_setpvf(ST(0), "%c", n);
450 }
451
452int
453READ(stream, bufsv, len, ...)
eede4b76 454 FCGI::Stream stream;
1b64d24d 455 SV * bufsv;
456 int len;
457
458 PREINIT:
459 int offset;
460 char * buf;
461
462 CODE:
463 offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
464 if (! SvOK(bufsv))
465 sv_setpvn(bufsv, "", 0);
466 buf = SvGROW(bufsv, len+offset+1);
467 len = FCGX_GetStr(buf+offset, len, stream);
468 SvCUR_set(bufsv, len+offset);
469 *SvEND(bufsv) = '\0';
470 (void)SvPOK_only(bufsv);
471 SvSETMAGIC(bufsv);
472 RETVAL = len;
473
474 OUTPUT:
475 RETVAL
476
477SV *
478GETC(stream)
eede4b76 479 FCGI::Stream stream;
1b64d24d 480
481 PREINIT:
482 int retval;
483
484 CODE:
485 if ((retval = FCGX_GetChar(stream)) != -1) {
486 ST(0) = sv_newmortal();
487 sv_setpvf(ST(0), "%c", retval);
488 } else ST(0) = &PL_sv_undef;
489
490bool
491CLOSE(stream)
eede4b76 492 FCGI::Stream stream;
1b64d24d 493
494 ALIAS:
495 DESTROY = 1
496
497 CODE:
498 RETVAL = FCGX_FClose(stream) != -1;
499
500 OUTPUT:
501 RETVAL
502
503#endif