📄 fcgi.xl
字号:
use Config;open OUT, ">FCGI.xs";print "Generating FCGI.xs for Perl version $]\n";#unless (exists $Config{apiversion} && $Config{apiversion} >= 5.005) unless ($] >= 5.005) { for (qw(sv_undef diehook warnhook in_eval)) { print OUT "#define PL_$_ $_\n" }}print OUT while <DATA>;close OUT;__END__/* $Id: FCGI.XL,v 1.9 2002/11/11 13:51:20 skimo Exp $ */#include "EXTERN.h"#include "perl.h"#include "XSUB.h"#include "fcgi_config.h"#include "fcgiapp.h"#include "fastcgi.h"#ifndef FALSE#define FALSE (0)#endif#ifndef TRUE#define TRUE (1)#endif#ifndef dTHX#define dTHX#endif#ifndef INT2PTR#define INT2PTR(a,b) ((a) (b))#endif#ifdef USE_SFIOtypedef struct{ Sfdisc_t disc; FCGX_Stream *stream;} FCGI_Disc;static ssize_tsffcgiread(f, buf, n, disc)Sfio_t* f; /* stream involved */Void_t* buf; /* buffer to read into */size_t n; /* number of bytes to read */Sfdisc_t* disc; /* discipline */{ return FCGX_GetStr(buf, n, ((FCGI_Disc *)disc)->stream);}static ssize_tsffcgiwrite(f, buf, n, disc)Sfio_t* f; /* stream involved */const Void_t* buf; /* buffer to read into */size_t n; /* number of bytes to read */Sfdisc_t* disc; /* discipline */{ n = FCGX_PutStr(buf, n, ((FCGI_Disc *)disc)->stream); FCGX_FFlush(((FCGI_Disc *)disc)->stream); return n;}Sfdisc_t *sfdcnewfcgi(stream) FCGX_Stream *stream;{ FCGI_Disc* disc; New(1000,disc,1,FCGI_Disc); if (!disc) return (Sfdisc_t *)disc; disc->disc.exceptf = (Sfexcept_f)NULL; disc->disc.seekf = (Sfseek_f)NULL; disc->disc.readf = sffcgiread; disc->disc.writef = sffcgiwrite; disc->stream = stream; return (Sfdisc_t *)disc;}Sfdisc_t *sfdcdelfcgi(disc) Sfdisc_t* disc;{ Safefree(disc); return 0;}#endif#if defined(USE_LOCKING) && defined(USE_THREADS)static perl_mutex accept_mutex;#endiftypedef struct FCGP_Request { int accepted; int bound; SV* svin; SV* svout; SV* sverr; GV* gv[3]; HV* hvEnv; FCGX_Request* requestPtr;#ifdef USE_SFIO int sfcreated[3]; IO* io[3];#endif} FCGP_Request;static void FCGI_Finish(FCGP_Request* request);static void FCGI_Flush(FCGP_Request* request){ dTHX; if(!request->bound) { return; }#ifdef USE_SFIO sfsync(IoOFP(GvIOp(request->gv[1]))); sfsync(IoOFP(GvIOp(request->gv[2])));#else FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->svout)))); FCGX_FFlush(INT2PTR(FCGX_Stream *, SvIV((SV*) SvRV(request->sverr))));#endif}static voidFCGI_UndoBinding(FCGP_Request* request){ dTHX;#ifdef USE_SFIO sfdcdelfcgi(sfdisc(IoIFP(request->io[0]), SF_POPDISC)); sfdcdelfcgi(sfdisc(IoOFP(request->io[1]), SF_POPDISC)); sfdcdelfcgi(sfdisc(IoOFP(request->io[2]), SF_POPDISC));#else# ifdef USE_PERLIO sv_unmagic((SV *)GvIOp(request->gv[0]), 'q'); sv_unmagic((SV *)GvIOp(request->gv[1]), 'q'); sv_unmagic((SV *)GvIOp(request->gv[2]), 'q');# else sv_unmagic((SV *)request->gv[0], 'q'); sv_unmagic((SV *)request->gv[1], 'q'); sv_unmagic((SV *)request->gv[2], 'q');# endif#endif request->bound = FALSE;}static voidFCGI_Bind(FCGP_Request* request){ dTHX;#ifdef USE_SFIO sfdisc(IoIFP(request->io[0]), sfdcnewfcgi(request->requestPtr->in)); sfdisc(IoOFP(request->io[1]), sfdcnewfcgi(request->requestPtr->out)); sfdisc(IoOFP(request->io[2]), sfdcnewfcgi(request->requestPtr->err));#else# ifdef USE_PERLIO /* For tied filehandles, we apply tiedscalar magic to the IO slot of the GP rather than the GV itself. */ if (!GvIOp(request->gv[1])) GvIOp(request->gv[1]) = newIO(); if (!GvIOp(request->gv[2])) GvIOp(request->gv[2]) = newIO(); if (!GvIOp(request->gv[0])) GvIOp(request->gv[0]) = newIO(); sv_magic((SV *)GvIOp(request->gv[1]), request->svout, 'q', Nullch, 0); sv_magic((SV *)GvIOp(request->gv[2]), request->sverr, 'q', Nullch, 0); sv_magic((SV *)GvIOp(request->gv[0]), request->svin, 'q', Nullch, 0);# else sv_magic((SV *)request->gv[1], request->svout, 'q', Nullch, 0); sv_magic((SV *)request->gv[2], request->sverr, 'q', Nullch, 0); sv_magic((SV *)request->gv[0], request->svin, 'q', Nullch, 0);# endif#endif request->bound = TRUE;}static voidpopulate_env(envp, hv)char **envp;HV *hv;{ int i; char *p, *p1; SV *sv; dTHX; hv_clear(hv); for(i = 0; ; i++) { if((p = envp[i]) == NULL) { break; } p1 = strchr(p, '='); assert(p1 != NULL); sv = newSVpv(p1 + 1, 0); /* call magic for this value ourselves */ hv_store(hv, p, p1 - p, sv, 0); SvSETMAGIC(sv); }}static intFCGI_IsFastCGI(FCGP_Request* request){ static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: CGI */ if (request->requestPtr->listen_sock == FCGI_LISTENSOCK_FILENO) { if (isCGI == -1) isCGI = FCGX_IsCGI(); return !isCGI; } /* A explicit socket is being used -> assume FastCGI */ return 1;}static int FCGI_Accept(FCGP_Request* request){ dTHX; if (!FCGI_IsFastCGI(request)) { static int been_here = 0; /* * Not first call to FCGI_Accept and running as CGI means * application is done. */ if (been_here) return EOF; been_here = 1; } else {#ifdef USE_SFIO int i;#endif FCGX_Request *fcgx_req = request->requestPtr; int acceptResult; FCGI_Finish(request);#if defined(USE_LOCKING) && defined(USE_THREADS) MUTEX_LOCK(&accept_mutex);#endif acceptResult = FCGX_Accept_r(fcgx_req);#if defined(USE_LOCKING) && defined(USE_THREADS) MUTEX_UNLOCK(&accept_mutex);#endif if(acceptResult < 0) { return acceptResult; } populate_env(fcgx_req->envp, request->hvEnv);#ifdef USE_SFIO for (i = 0; i < 3; ++i) { request->io[i] = GvIOn(request->gv[i]); if (!(i == 0 ? IoIFP(request->io[i]) : IoOFP(request->io[i]))) { IoIFP(request->io[i]) = sftmp(0); /*IoIFP(request->io[i]) = sfnew(NULL, NULL, SF_UNBOUND, 0, SF_STRING | (i ? SF_WRITE : SF_READ));*/ if (i != 0) IoOFP(request->io[i]) = IoIFP(request->io[i]); request->sfcreated[i] = TRUE; } }#else if (!request->svout) { newSVrv(request->svout = newSV(0), "FCGI::Stream"); newSVrv(request->sverr = newSV(0), "FCGI::Stream"); newSVrv(request->svin = newSV(0), "FCGI::Stream"); } sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out)); sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err)); sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in));#endif FCGI_Bind(request); request->accepted = TRUE; } return 0;}static void FCGI_Finish(FCGP_Request* request){#ifdef USE_SFIO int i;#endif int was_bound; dTHX; if(!request->accepted) { return; } if (was_bound = request->bound) { FCGI_UndoBinding(request); }#ifdef USE_SFIO for (i = 0; i < 3; ++i) { if (request->sfcreated[i]) { sfclose(IoIFP(request->io[i])); IoIFP(request->io[i]) = IoOFP(request->io[i]) = Nullfp; request->sfcreated[i] = FALSE; } }#endif if (was_bound) FCGX_Finish_r(request->requestPtr); else FCGX_Free(request->requestPtr, 1); request->accepted = FALSE;}static int FCGI_StartFilterData(FCGP_Request* request){ return request->requestPtr->in ? FCGX_StartFilterData(request->requestPtr->in) : -1;}static FCGP_Request *FCGI_Request(in, out, err, env, socket, flags) GV* in; GV* out; GV* err; HV* env; int socket; int flags;{ FCGX_Request* fcgx_req; FCGP_Request* req; Newz(551, fcgx_req, 1, FCGX_Request); FCGX_InitRequest(fcgx_req, socket, flags); Newz(551, req, 1, FCGP_Request); req->requestPtr = fcgx_req; SvREFCNT_inc(in); req->gv[0] = in; SvREFCNT_inc(out); req->gv[1] = out; SvREFCNT_inc(err); req->gv[2] = err; SvREFCNT_inc(env); req->hvEnv = env; return req;}static voidFCGI_Release_Request(FCGP_Request *req){ SvREFCNT_dec(req->gv[0]); SvREFCNT_dec(req->gv[1]); SvREFCNT_dec(req->gv[2]); SvREFCNT_dec(req->hvEnv); FCGI_Finish(req); Safefree(req->requestPtr); Safefree(req);}static voidFCGI_Init(){#if defined(USE_LOCKING) && defined(USE_THREADS) dTHX; MUTEX_INIT(&accept_mutex);#endif FCGX_Init();}typedef FCGX_Stream * FCGI__Stream;typedef FCGP_Request * FCGI;typedef GV* GLOBREF;typedef HV* HASHREF;MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_BOOT: FCGI_Init();SV *RequestX(in, out, err, env, socket, flags) GLOBREF in; GLOBREF out; GLOBREF err; HASHREF env; int socket; int flags; PROTOTYPE: ***$$$ CODE: RETVAL = sv_setref_pv(newSV(0), "FCGI", FCGI_Request(in, out, err, env, socket, flags)); OUTPUT: RETVALintOpenSocket(path, backlog) char* path; int backlog; PROTOTYPE: $$ CODE: RETVAL = FCGX_OpenSocket(path, backlog); OUTPUT: RETVALvoidCloseSocket(socket) int socket; PROTOTYPE: $ CODE: close(socket);intFCGI_Accept(request) FCGI request; PROTOTYPE: $voidFCGI_Finish(request) FCGI request; PROTOTYPE: $voidFCGI_Flush(request) FCGI request; PROTOTYPE: $HV *GetEnvironment(request) FCGI request; PROTOTYPE: $ CODE: RETVAL = request->hvEnv; OUTPUT: RETVALvoidGetHandles(request) FCGI request; PROTOTYPE: $ PREINIT: int i; PPCODE: EXTEND(sp,3); for (i = 0; i < 3; ++i) PUSHs(sv_2mortal(newRV((SV *) request->gv[i])));intFCGI_IsFastCGI(request) FCGI request; PROTOTYPE: $voidDetach(request) FCGI request; PROTOTYPE: $ CODE: if (request->accepted && request->bound) FCGI_UndoBinding(request);voidAttach(request) FCGI request; PROTOTYPE: $ CODE: if (request->accepted && !request->bound) FCGI_Bind(request);voidLastCall(request) FCGI request; PROTOTYPE: $ CODE: FCGX_ShutdownPending();intFCGI_StartFilterData(request) FCGI request; PROTOTYPE: $voidDESTROY(request) FCGI request; CODE: FCGI_Release_Request(request);MODULE = FCGI PACKAGE = FCGI::Stream#ifndef USE_SFIOvoidPRINT(stream, ...) FCGI::Stream stream; PREINIT: int n; CODE: for (n = 1; n < items; ++n) { STRLEN len; register char *tmps = (char *)SvPV(ST(n),len); FCGX_PutStr(tmps, len, stream); } if (SvTRUEx(perl_get_sv("|", FALSE))) FCGX_FFlush(stream);intWRITE(stream, bufsv, len, ...) FCGI::Stream stream; SV * bufsv; int len; PREINIT: int offset; char * buf; STRLEN blen; int n; CODE: offset = (items == 4) ? (int)SvIV(ST(3)) : 0; buf = SvPV(bufsv, blen); if (offset < 0) offset += blen; if (len > blen - offset) len = blen - offset; if (offset < 0 || offset >= blen || (n = FCGX_PutStr(buf+offset, len, stream)) < 0) ST(0) = &PL_sv_undef; else { ST(0) = sv_newmortal(); sv_setpvf(ST(0), "%c", n); }intREAD(stream, bufsv, len, ...) FCGI::Stream stream; SV * bufsv; int len; PREINIT: int offset; char * buf; CODE: offset = (items == 4) ? (int)SvIV(ST(3)) : 0; if (! SvOK(bufsv)) sv_setpvn(bufsv, "", 0); buf = SvGROW(bufsv, len+offset+1); len = FCGX_GetStr(buf+offset, len, stream); SvCUR_set(bufsv, len+offset); *SvEND(bufsv) = '\0'; (void)SvPOK_only(bufsv); SvSETMAGIC(bufsv); RETVAL = len; OUTPUT: RETVALSV *GETC(stream) FCGI::Stream stream; PREINIT: int retval; CODE: if ((retval = FCGX_GetChar(stream)) != -1) { ST(0) = sv_newmortal(); sv_setpvf(ST(0), "%c", retval); } else ST(0) = &PL_sv_undef;boolCLOSE(stream) FCGI::Stream stream;# ALIAS:# DESTROY = 1 CODE: RETVAL = FCGX_FClose(stream) != -1; OUTPUT: RETVAL#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -