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