X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FFCGI.PL;h=c615c8b0db38680140f3b22d703ef4ec1ec86505;hb=08cfa0ade2c8cbfe5bce58adbb044d9c01848800;hp=deea1f6569c5f157558178d5d04c111a086bff23;hpb=90a18d65d343c91612c14724f427519f301971a5;p=catagits%2Ffcgi2.git diff --git a/perl/FCGI.PL b/perl/FCGI.PL index deea1f6..c615c8b 100644 --- a/perl/FCGI.PL +++ b/perl/FCGI.PL @@ -1,535 +1,535 @@ use Config; -open OUT, ">FCGI.xs"; +do 'FCGI.cfg' or die "no FCGI.cfg"; -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" - } +open OUT, ">FCGI.pm"; + +print "Generating FCGI.pm\n"; +print OUT <<'EOP'; +# $Id: FCGI.PL,v 1.27 2001/09/01 13:07:28 skimo Exp $ + +package FCGI; + +require Exporter; +require DynaLoader; + +@ISA = qw(Exporter DynaLoader); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + +); + +$VERSION = '0.60'; + +EOP + +print OUT "bootstrap FCGI;\n" unless ($pure); + +print OUT <<'EOP' if ($pure); +use Symbol; +use POSIX 'ENOTCONN'; + +use constant VERSION_1 => 1; + +use constant BEGIN_REQUEST => 1; +use constant PARAMS => 4; +use constant FCGI_STDIN => 5; +use constant FCGI_STDOUT => 6; +use constant FCGI_STDERR => 7; + +use constant RESPONDER => 1; +use constant AUTHORIZER => 2; +use constant FILTER => 3; + +%FCGI::rolenames = (RESPONDER, "RESPONDER", + AUTHORIZER, "AUTHORIZER", + FILTER, "FILTER", + ); +sub IsFastCGI { + my ($req) = @_; + $req->{isfastcgi} = + (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN + unless exists $req->{isfastcgi}; + return $req->{isfastcgi}; } -print OUT while ; -close OUT; -__END__ -/* $Id: FCGI.PL,v 1.4 1999/07/28 16:15:40 skimo Exp $ */ - -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" - -#include "fcgiapp.h" - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (1) -#endif - -#ifdef WIN32 -#define environ _environ -#endif - -extern char **environ; -static char **requestEnviron = NULL; - -#ifdef USE_SFIO -typedef struct -{ - Sfdisc_t disc; - FCGX_Stream *stream; -} FCGI_Disc; - -static ssize_t -sffcgiread(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_t -sffcgiwrite(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; + +sub read_nv_len { + my ($stream) = @_; + my $buf; + return undef unless read $stream, $buf, 1, 0; + my ($len) = unpack("C", $buf); + if ($len & 0x80) { + $buf = pack("C", $len & 0x7F); + return undef unless read $stream, $buf, 3, 1; + $len = unpack("N", $buf); + } + $len; } -#endif -static int isCGI = -1; /* -1: not checked; 0: FCGI; 1: FCGI */ +sub RequestX { + my $self = { + in => shift, + out => shift, + err => shift, + env => shift, + socket => shift, + flags => shift, + }; + open $self->{listen_sock}, "<&=0"; + bless $self, "FCGI"; +} -static FCGX_Request global_fcgx_request; +my $run_once = 0; -typedef struct FCGP_Request { - int compat; - int acceptCalled; - int finishCalled; - SV* svin; - SV* svout; - SV* sverr; - FCGX_Stream* in; - FCGX_Request* requestPtr; -} FCGP_Request; +sub Accept { + my ($req) = @_; -static FCGP_Request global_request; -static SV* global_sverr; + unless ($req->IsFastCGI()) { + return -1 if $run_once; -static int -FCGI_Flush(FCGP_Request* request) -{ - if(!request->compat || !request->acceptCalled || isCGI) { - return; + $run_once = 1; + return 0; } -#ifdef USE_SFIO - sfsync(PerlIO_stdout()); - sfsync(PerlIO_stderr()); -#else - FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->svout))); - FCGX_FFlush((FCGX_Stream *) SvIV((SV*) SvRV(request->sverr))); -#endif -} - -static int -FCGI_Accept(FCGP_Request* request) -{ - if(isCGI == -1) { - /* - * First call to FCGI_Accept. Is application running - * as FastCGI or as CGI? - */ - isCGI = FCGX_IsCGI(); - } else if(isCGI) { - /* - * Not first call to FCGI_Accept and running as CGI means - * application is done. - */ - return(EOF); - } else { - if(request->compat && !request->finishCalled) { -#ifdef USE_SFIO - sfdcdelfcgi(sfdisc(PerlIO_stdin(), SF_POPDISC)); - sfdcdelfcgi(sfdisc(PerlIO_stdout(), SF_POPDISC)); - sfdcdelfcgi(sfdisc(PerlIO_stderr(), SF_POPDISC)); -#else - FCGI_Flush(request); -#endif - } + $req->Finish(); + $req->{socket} = gensym(); + if (!accept($req->{socket}, $req->{listen_sock})) { + $req->{error} = "accept"; + return -1; } - if(!isCGI) { - FCGX_ParamArray envp; - FCGX_Stream *out, *error; - int acceptResult = FCGX_Accept_r(&request->in, &out, &error, &envp, - request->requestPtr); - if(acceptResult < 0) { - return acceptResult; - } -#ifdef USE_SFIO - sfdisc(PerlIO_stdin(), sfdcnewfcgi(request->in)); - sfdisc(PerlIO_stdout(), sfdcnewfcgi(out)); - sfdisc(PerlIO_stderr(), sfdcnewfcgi(error)); -#else - if (!request->svout) { - newSVrv(request->svout = newSV(0), "FCGI"); - sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), - request->svout, 'q', Nullch, 0); - newSVrv(request->sverr = newSV(0), "FCGI"); - sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), - request->sverr, 'q', Nullch, 0); - newSVrv(request->svin = newSV(0), "FCGI"); - sv_magic((SV *)gv_fetchpv("STDIN",TRUE, SVt_PVIO), - request->svin, 'q', Nullch, 0); - } - sv_setiv(SvRV(request->svout), (IV) out); - sv_setiv(SvRV(request->sverr), (IV) error); - sv_setiv(SvRV(request->svin), (IV) request->in); - - if (request->compat) { - global_sverr = request->sverr; - if (PL_warnhook) SvREFCNT_dec(PL_warnhook); - PL_warnhook = SvREFCNT_inc(GvCV(gv_fetchmethod(Nullhv, "FCGI::WARN"))); - if (PL_diehook) SvREFCNT_dec(PL_diehook); - PL_diehook = SvREFCNT_inc(GvCV(gv_fetchmethod(Nullhv, "FCGI::DIE"))); - } -#endif - request->finishCalled = FALSE; - environ = envp; + my ($type, $id, $body) = $req->read_record(); + if ($type != BEGIN_REQUEST) { + $req->{error} = "begin request"; + return -1; } - request->acceptCalled = TRUE; + my ($role, $flags) = unpack("nC", $body); + $req->{role} = $role; + $req->{flags} = $flags; + $req->{id} = $id; + + %{$req->{env}} = (); + $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}}; + my $param = FCGI::Stream->new($req, PARAMS); + my ($nlen, $vlen); + while (defined($nlen = read_nv_len($param)) && + defined($vlen = read_nv_len($param))) { + my ($name, $val); + read $param, $name, $nlen; + read $param, $val, $vlen; + $req->{env}{$name} = $val; + } + $req->Bind; + $req->{accepted} = 1; + return 0; } -static void -FCGI_Finish(FCGP_Request* request) -{ - if(!request->acceptCalled || isCGI) { - return; - } - if (request->compat) { -#ifdef USE_SFIO - sfdcdelfcgi(sfdisc(PerlIO_stdin(), SF_POPDISC)); - sfdcdelfcgi(sfdisc(PerlIO_stdout(), SF_POPDISC)); - sfdcdelfcgi(sfdisc(PerlIO_stderr(), SF_POPDISC)); -#else - FCGI_Flush(request); -#endif +sub UndoBindings { + my ($req) = @_; + untie ${$req->{in}}; + untie ${$req->{out}}; + untie ${$req->{err}}; + $req->{bound} = 0; +} + +sub Bind { + my ($req) = @_; + tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN; + tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT; + tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR; + $req->{bound} = 1; +} + +sub Attach { + my ($req) = @_; + $req->Bind() if ($req->{accepted} && !$req->{bound}); +} + +sub Detach { + my ($req) = @_; + $req->UndoBindings() if ($req->{accepted} && $req->{bound}); +} + +sub Finish { + my ($req) = @_; + return unless $req->{accepted}; + if ($req->{bound}) { + $req->UndoBindings(); + close ${$req->{out}}; + close ${$req->{err}}; } - request->in = NULL; - FCGX_Finish_r(request->requestPtr); - request->finishCalled = TRUE; -#ifndef USE_SFIO - if (request->compat) { - if (PL_warnhook == (SV*)GvCV(gv_fetchmethod(Nullhv, "FCGI::WARN"))) { - SvREFCNT_dec(PL_warnhook); - PL_warnhook = Nullsv; - } - if (PL_diehook == (SV*)GvCV(gv_fetchmethod(Nullhv, "FCGI::DIE"))) { - SvREFCNT_dec(PL_diehook); - PL_diehook = Nullsv; + $req->{accepted} = 0; +} + +sub DESTROY { + shift->Finish(); +} + +sub read_record { + my ($self) = @_; + my ($header, $body); + + read($self->{socket}, $header, 8); + my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header); + read($self->{socket}, $body, $clen+$plen); + $body = undef if $clen == 0; + ($type, $id, $body); +} + +sub read { + my ($self, $rtype, $len) = @_; + while (length $self->{buf} < $len) { + my ($type, $id, $buf) = $self->read_record(); + return undef unless defined $buf; + if ($type != $rtype) { + $self->{error} = "unexpected stream type"; + return 0; } + $self->{buf} .= $buf; } -#endif -} - -static int -FCGI_StartFilterData(FCGP_Request* request) -{ - return request->in ? FCGX_StartFilterData(request->in) : -1; -} - -static void -FCGI_SetExitStatus(FCGP_Request* request, int status) -{ - if (request->in) FCGX_SetExitStatus(status, request->in); -} - -static FCGP_Request * -FCGI_Request() -{ - FCGX_Request* fcgx_req; - FCGP_Request* req; - - Newz(551, fcgx_req, 1, FCGX_Request); - Newz(551, req, 1, FCGP_Request); - req->requestPtr = fcgx_req; - - return req; -} - -static void -FCGI_Release_Request(FCGP_Request *req) -{ - Safefree(req->requestPtr); - Safefree(req); -} - -/* - * For each variable in the array envp, either set or unset it - * in the global hash %ENV. - */ -static void -DoPerlEnv(envp, set) -char **envp; -int set; -{ - int i; - char *p, *p1; - HV *hv; - SV *sv; - hv = perl_get_hv("ENV", TRUE); - - if (!set) - perl_eval_pv("%ENV = %FCGI::ENV", 0); - else { - perl_eval_pv("%FCGI::ENV = %ENV", 0); - for(i = 0; ; i++) { - if((p = envp[i]) == NULL) { - break; - } - p1 = strchr(p, '='); - assert(p1 != NULL); - *p1 = '\0'; - sv = newSVpv(p1 + 1, 0); - /* call magic for this value ourselves */ - hv_store(hv, p, p1 - p, sv, 0); - SvSETMAGIC(sv); - *p1 = '='; - } + my ($newbuf, $result) = (substr($self->{buf}, $len), + substr($self->{buf}, 0, $len)); + $self->{buf} = $newbuf; + $result; +} + +sub Flush { + my ($req) = @_; +} + +sub write { + my ($self, $type, $content, $len) = @_; + return unless $len > 0; + $self->write_record($type, $content, $len); +} + +sub write_record { + my ($self, $type, $content, $len) = @_; + my $padlen = (8 - ($len % 8)) % 8; + my $templ = "CCnnCxa${len}x$padlen"; + my $data = pack($templ, + VERSION_1, $type, $self->{id}, $len, $padlen, $content); + syswrite $self->{socket}, $data; +} + +{ package FCGI::Stream; + +sub new { + my ($class, $src, $type) = @_; + my $handle = do { \local *FH }; + tie($$handle, $class, $src, $type); + $handle; +} + +sub TIEHANDLE { + my ($class, $src, $type) = @_; + bless { src => $src, type => $type }, $class; +} + +sub READ { + my ($stream, undef, $len, $offset) = @_; + my ($ref) = \$_[1]; + my $buf = $stream->{src}->read($stream->{type}, $len); + return undef unless defined $buf; + substr($$ref, $offset, 0, $buf); + length $buf; +} + +sub PRINT { + my ($stream) = shift; + for (@_) { + $stream->{src}->write($stream->{type}, $_, length($_)); } } +sub CLOSE { + my ($stream) = @_; + $stream->{src}->write_record($stream->{type}, undef, 0); +} + +} + +EOP +print OUT while ; +close OUT; +__END__ -typedef FCGX_Stream * FCGI; -typedef FCGP_Request * FCGI__Request; +# Preloaded methods go here. -MODULE = FCGI PACKAGE = FCGI +# Autoload methods go after __END__, and are processed by the autosplit program. -BOOT: - FCGX_Init(); - FCGX_InitRequest(&global_fcgx_request); - memset(&global_request, 0, sizeof(global_request)); - global_request.compat = 1; - global_request.requestPtr = &global_fcgx_request; +*FAIL_ACCEPT_ON_INTR = sub() { 1 }; -#ifndef USE_SFIO -void -DIE(msg) - char * msg; +sub Request(;***$$$) { + my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0); + splice @defaults,0,@_,@_; + RequestX(@defaults); +} - CODE: - if (!PL_in_eval) - FCGX_PutS(msg, (FCGX_Stream *) SvIV((SV*) SvRV(global_sverr))); +sub accept() { + warn "accept called as a method; you probably wanted to call Accept" if @_; + if (defined %FCGI::ENV) { + %ENV = %FCGI::ENV; + } else { + %FCGI::ENV = %ENV; + } + my $rc = Accept($global_request); + for (keys %FCGI::ENV) { + $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_}; + } -void -WARN(msg) - char * msg; + # not SFIO + $SIG{__WARN__} = $warn_handler if (tied (*STDIN)); + $SIG{__DIE__} = $die_handler if (tied (*STDIN)); - CODE: - FCGX_PutS(msg, (FCGX_Stream *) SvIV((SV*) SvRV(global_sverr))); + return $rc; +} -void -PRINT(stream, ...) - FCGI stream; +sub finish() { + warn "finish called as a method; you probably wanted to call Finish" if @_; + %ENV = %FCGI::ENV if (defined %FCGI::ENV); - PREINIT: - int n; + # not SFIO + if (tied (*STDIN)) { + delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler); + delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler); + } - 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); - -int -WRITE(stream, bufsv, len, ...) - FCGI 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); - } + Finish ($global_request); +} -int -READ(stream, bufsv, len, ...) - FCGI 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: - RETVAL - -SV * -GETC(stream) - FCGI 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; - -bool -CLOSE(stream) - FCGI stream; - - ALIAS: - DESTROY = 1 - - CODE: - RETVAL = FCGX_FClose(stream) != -1; - - OUTPUT: - RETVAL - -#endif - -SV * -request() - - PROTOTYPE: - CODE: - RETVAL = Perl_sv_setref_pv(Perl_newSV(0), "FCGI::Request", FCGI_Request()); - - OUTPUT: - RETVAL - - -int -accept(...) - - PROTOTYPE: ;$***$ - - PREINIT: - FCGP_Request* request = &global_request; - SV * sv; - - CODE: - if (items != 0 && items != 5) - croak("Usage: FCGI::accept() or " - "FCGI::accept(request, IN, OUT, ERR, env)"); - if (items) { - if (sv_isa(ST(0), "FCGI::Request")) { - request = (FCGP_Request*) SvIV((SV*)SvRV(ST(0))); - } else - croak("request is not of type FCGI::Request"); - if (SvROK(ST(1)) && isGV(SvRV(ST(1)))) { - } else - croak("IN is not a GLOB reference"); +sub flush() { + warn "flush called as a method; you probably wanted to call Flush" if @_; + Flush($global_request); +} + +sub detach() { + warn "detach called as a method; you probably wanted to call Detach" if @_; + Detach($global_request); +} + +sub attach() { + warn "attach called as a method; you probably wanted to call Attach" if @_; + Attach($global_request); +} + +# deprecated +sub set_exit_status { +} + +sub start_filter_data() { + StartFilterData($global_request); +} + +$global_request = Request(); +$warn_handler = sub { print STDERR @_ }; +$die_handler = sub { print STDERR @_ unless $^S }; + +package FCGI::Stream; + +sub PRINTF { + shift->PRINT(sprintf(shift, @_)); +} + +sub BINMODE { +} + +sub READLINE { + my $stream = shift; + my ($s, $c); + my $rs = $/ eq '' ? "\n\n" : $/; + my $l = substr $rs, -1; + my $len = length $rs; + + $c = $stream->GETC(); + if ($/ eq '') { + while ($c eq "\n") { + $c = $stream->GETC(); + } } - { - char **savedEnviron; - int acceptStatus; - /* - * Unmake Perl variable settings for the request just completed. - */ - if(requestEnviron != NULL) { - DoPerlEnv(requestEnviron, FALSE); - requestEnviron = NULL; - } - /* - * Call FCGI_Accept but preserve environ. - */ - savedEnviron = environ; - acceptStatus = FCGI_Accept(request); - requestEnviron = environ; - environ = savedEnviron; - /* - * Make Perl variable settings for the new request. - */ - if(acceptStatus >= 0 && !FCGX_IsCGI()) { - DoPerlEnv(requestEnviron, TRUE); - } else { - requestEnviron = NULL; - } - RETVAL = acceptStatus; + while (defined $c) { + $s .= $c; + last if $c eq $l and substr($s, -$len) eq $rs; + $c = $stream->GETC(); + } + $s; +} + +sub OPEN { + $_[0]->CLOSE; + if (@_ == 2) { + return open($_[0], $_[1]); + } else { + my $rc; + eval("$rc = open($_[0], $_[1], $_[2])"); + die $@ if $@; + return $rc; } - OUTPUT: - RETVAL - - -void -finish(...) - - PROTOTYPE: ;$ - CODE: - { - /* - * Unmake Perl variable settings for the completed request. - */ - if(requestEnviron != NULL) { - DoPerlEnv(requestEnviron, FALSE); - requestEnviron = NULL; - } - /* - * Finish the request. - */ - FCGI_Finish(&global_request); +} + +1; + +=pod + +=head1 NAME + +FCGI - Fast CGI module + +=head1 SYNOPSIS + + use FCGI; + + my $count = 0; + my $request = FCGI::Request(); + + while($request->Accept() >= 0) { + print("Content-type: text/html\r\n\r\n", ++$count); } +=head1 DESCRIPTION + +Functions: + +=over 4 + +=item FCGI::Request + +Creates a request handle. It has the following optional parameters: + +=over 8 + +=item input perl file handle (default: \*STDIN) + +=item output perl file handle (default: \*STDOUT) + +=item error perl file handle (default: \*STDERR) -void -flush(...) +These filehandles will be setup to act as input/output/error +on succesful Accept. - PROTOTYPE: ;$ - CODE: - FCGI_Flush(&global_request); +=item environment hash reference (default: \%ENV) -void -set_exit_status(status,...) +The hash will be populated with the environment. - int status; +=item socket (default: 0) - PROTOTYPE: $;$ - CODE: - FCGI_SetExitStatus(&global_request, status); +Socket to communicate with the server. +Can be the result of the OpenSocket function. +For the moment, it's the file descriptor of the socket +that should be passed. This may change in the future. -int -start_filter_data(...) +You should only use your own socket if your program +is not started by a process manager such as mod_fastcgi +(except for the FastCgiExternalServer case) or cgi-fcgi. +If you use the option, you have to let your FastCGI +server know which port (and possibly server) your program +is listening on. +See remote.pl for an example. - PROTOTYPE: ;$ - CODE: - RETVAL = FCGI_StartFilterData(&global_request); +=item flags (default: 0) - OUTPUT: - RETVAL +Possible values: -MODULE = FCGI PACKAGE = FCGI::Request +=over 12 -void -DESTROY(request) - FCGI::Request request; +=item FCGI::FAIL_ACCEPT_ON_INTR - CODE: - FCGI_Release_Request(request); +If set, Accept will fail if interrupted. +It not set, it will just keep on waiting. + +=back + +=back + +Example usage: + my $req = FCGI::Request; + +or: + my %env; + my $in = new IO::Handle; + my $out = new IO::Handle; + my $err = new IO::Handle; + my $req = FCGI::Request($in, $out, $err, \%env); + +=item FCGI::OpenSocket(path, backlog) + +Creates a socket suitable to use as an argument to Request. + +=over 8 + +=item path + +Pathname of socket or colon followed by local tcp port. +Note that some systems take file permissions into account +on Unix domain sockets, so you'll have to make sure that +the server can write to the created file, by changing +the umask before the call and/or changing permissions and/or +group of the file afterwards. + +=item backlog + +Maximum length of the queue of pending connections. +If a connection +request arrives with the queue full the client may receive +an error with an indication of ECONNREFUSED. + +=back + +=item FCGI::CloseSocket(socket) + +Close a socket opened with OpenSocket. + +=item $req->Accept() + +Accepts a connection on $req, attaching the filehandles and +populating the environment hash. +Returns 0 on success. +If a connection has been accepted before, the old +one will be finished first. + +Note that unlike with the old interface, no die and warn +handlers are installed by default. This means that if +you are not running an sfio enabled perl, any warn or +die message will not end up in the server's log by default. +It is advised you set up die and warn handlers yourself. +FCGI.pm contains an example of die and warn handlers. + +=item $req->Finish() + +Finishes accepted connection. +Also detaches filehandles. + +=item $req->Flush() + +Flushes accepted connection. + +=item $req->Detach() + +Temporarily detaches filehandles on an accepted connection. + +=item $req->Attach() + +Re-attaches filehandles on an accepted connection. + +=item $env = $req->GetEnvironment() + +Returns the environment parameter passed to FCGI::Request. + +=item ($in, $out, $err) = $req->GetHandles() + +Returns the file handle parameters passed to FCGI::Request. + +=item $isfcgi = $req->IsFastCGI() + +Returns whether or not the program was run as a FastCGI. + +=back + +=head1 AUTHOR + +Sven Verdoolaege + +=cut + +__END__