3 do 'FCGI.cfg' or die "no FCGI.cfg";
7 print "Generating FCGI.pm\n";
9 # $Id: FCGI.PL,v 1.32 2001/09/21 15:54:34 skimo Exp $
16 @ISA = qw(Exporter DynaLoader);
17 # Items to export into callers namespace by default. Note: do not export
18 # names by default without a very good reason. Use EXPORT_OK instead.
19 # Do not simply export all your public functions/methods/constants.
27 open VERSION, "version.pm";
33 print OUT "bootstrap FCGI;\n" unless ($pure);
35 print OUT <<'EOP' if ($pure);
39 use constant VERSION_1 => 1;
41 use constant BEGIN_REQUEST => 1;
42 use constant PARAMS => 4;
43 use constant FCGI_STDIN => 5;
44 use constant FCGI_STDOUT => 6;
45 use constant FCGI_STDERR => 7;
47 use constant RESPONDER => 1;
48 use constant AUTHORIZER => 2;
49 use constant FILTER => 3;
51 %FCGI::rolenames = (RESPONDER, "RESPONDER",
52 AUTHORIZER, "AUTHORIZER",
56 # This only works on Unix; anyone familiar with Windows is welcome
61 (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN
62 unless exists $req->{isfastcgi};
63 return $req->{isfastcgi};
67 return shift->{'env'};
73 return undef unless read $stream, $buf, 1, 0;
74 my ($len) = unpack("C", $buf);
76 $buf = pack("C", $len & 0x7F);
77 return undef unless read $stream, $buf, 3, 1;
78 $len = unpack("N", $buf);
93 open $self->{listen_sock}, "<&=0";
102 unless ($req->IsFastCGI()) {
103 return -1 if $run_once;
109 $req->{socket} = gensym();
110 if ($req->{last} || !accept($req->{socket}, $req->{listen_sock})) {
111 $req->{error} = "accept";
114 my ($type, $id, $body) = $req->read_record();
115 if ($type != BEGIN_REQUEST) {
116 $req->{error} = "begin request";
119 my ($role, $flags) = unpack("nC", $body);
120 $req->{role} = $role;
121 $req->{flags} = $flags;
125 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
126 my $param = FCGI::Stream->new($req, PARAMS);
128 while (defined($nlen = read_nv_len($param)) &&
129 defined($vlen = read_nv_len($param))) {
131 read $param, $name, $nlen;
132 read $param, $val, $vlen;
133 $req->{env}{$name} = $val;
136 $req->{accepted} = 1;
144 untie ${$req->{out}};
145 untie ${$req->{err}};
151 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
152 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
153 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
159 $req->Bind() if ($req->{accepted} && !$req->{bound});
164 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
169 return unless $req->{accepted};
171 $req->UndoBindings();
172 close ${$req->{out}};
173 close ${$req->{err}};
175 $req->{accepted} = 0;
190 read($self->{socket}, $header, 8);
191 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
192 read($self->{socket}, $body, $clen+$plen);
193 $body = undef if $clen == 0;
198 my ($self, $rtype, $len) = @_;
199 while (length $self->{buf} < $len) {
200 my ($type, $id, $buf) = $self->read_record();
201 return undef unless defined $buf;
202 if ($type != $rtype) {
203 $self->{error} = "unexpected stream type";
206 $self->{buf} .= $buf;
208 my ($newbuf, $result) = (substr($self->{buf}, $len),
209 substr($self->{buf}, 0, $len));
210 $self->{buf} = $newbuf;
219 my ($self, $type, $content, $len) = @_;
220 return unless $len > 0;
221 $self->write_record($type, $content, $len);
225 my ($self, $type, $content, $len) = @_;
226 my $padlen = (8 - ($len % 8)) % 8;
227 my $templ = "CCnnCxa${len}x$padlen";
228 my $data = pack($templ,
229 VERSION_1, $type, $self->{id}, $len, $padlen, $content);
230 syswrite $self->{socket}, $data;
233 { package FCGI::Stream;
236 my ($class, $src, $type) = @_;
237 my $handle = do { \local *FH };
238 tie($$handle, $class, $src, $type);
243 my ($class, $src, $type) = @_;
244 bless { src => $src, type => $type }, $class;
248 my ($stream, undef, $len, $offset) = @_;
250 my $buf = $stream->{src}->read($stream->{type}, $len);
251 return undef unless defined $buf;
252 substr($$ref, $offset, 0, $buf);
257 my ($stream) = shift;
259 $stream->{src}->write($stream->{type}, $_, length($_));
265 $stream->{src}->write_record($stream->{type}, undef, 0);
271 print OUT while <DATA>;
275 # Preloaded methods go here.
277 # Autoload methods go after __END__, and are processed by the autosplit program.
279 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
281 sub Request(;***$*$) {
282 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
283 $_[4] = fileno($_[4]) if defined(fileno($_[4]));
284 splice @defaults,0,@_,@_;
289 warn "accept called as a method; you probably wanted to call Accept" if @_;
290 if (defined %FCGI::ENV) {
295 my $rc = Accept($global_request);
296 for (keys %FCGI::ENV) {
297 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
301 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
302 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
308 warn "finish called as a method; you probably wanted to call Finish" if @_;
309 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
313 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
314 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
317 Finish ($global_request);
321 warn "flush called as a method; you probably wanted to call Flush" if @_;
322 Flush($global_request);
326 warn "detach called as a method; you probably wanted to call Detach" if @_;
327 Detach($global_request);
331 warn "attach called as a method; you probably wanted to call Attach" if @_;
332 Attach($global_request);
336 sub set_exit_status {
339 sub start_filter_data() {
340 StartFilterData($global_request);
343 $global_request = Request();
344 $warn_handler = sub { print STDERR @_ };
345 $die_handler = sub { print STDERR @_ unless $^S };
347 package FCGI::Stream;
350 shift->PRINT(sprintf(shift, @_));
359 my $rs = $/ eq '' ? "\n\n" : $/;
360 my $l = substr $rs, -1;
361 my $len = length $rs;
363 $c = $stream->GETC();
366 $c = $stream->GETC();
371 last if $c eq $l and substr($s, -$len) eq $rs;
372 $c = $stream->GETC();
380 return open($_[0], $_[1]);
383 eval("$rc = open($_[0], $_[1], $_[2])");
395 FCGI - Fast CGI module
402 my $request = FCGI::Request();
404 while($request->Accept() >= 0) {
405 print("Content-type: text/html\r\n\r\n", ++$count);
416 Creates a request handle. It has the following optional parameters:
420 =item input perl file handle (default: \*STDIN)
422 =item output perl file handle (default: \*STDOUT)
424 =item error perl file handle (default: \*STDERR)
426 These filehandles will be setup to act as input/output/error
429 =item environment hash reference (default: \%ENV)
431 The hash will be populated with the environment.
433 =item socket (default: 0)
435 Socket to communicate with the server.
436 Can be the result of the OpenSocket function.
437 For the moment, it's the file descriptor of the socket
438 that should be passed. This may change in the future.
440 You should only use your own socket if your program
441 is not started by a process manager such as mod_fastcgi
442 (except for the FastCgiExternalServer case) or cgi-fcgi.
443 If you use the option, you have to let your FastCGI
444 server know which port (and possibly server) your program
446 See remote.pl for an example.
448 =item flags (default: 0)
454 =item FCGI::FAIL_ACCEPT_ON_INTR
456 If set, Accept will fail if interrupted.
457 It not set, it will just keep on waiting.
464 my $req = FCGI::Request;
468 my $in = new IO::Handle;
469 my $out = new IO::Handle;
470 my $err = new IO::Handle;
471 my $req = FCGI::Request($in, $out, $err, \%env);
473 =item FCGI::OpenSocket(path, backlog)
475 Creates a socket suitable to use as an argument to Request.
481 Pathname of socket or colon followed by local tcp port.
482 Note that some systems take file permissions into account
483 on Unix domain sockets, so you'll have to make sure that
484 the server can write to the created file, by changing
485 the umask before the call and/or changing permissions and/or
486 group of the file afterwards.
490 Maximum length of the queue of pending connections.
492 request arrives with the queue full the client may receive
493 an error with an indication of ECONNREFUSED.
497 =item FCGI::CloseSocket(socket)
499 Close a socket opened with OpenSocket.
503 Accepts a connection on $req, attaching the filehandles and
504 populating the environment hash.
505 Returns 0 on success.
506 If a connection has been accepted before, the old
507 one will be finished first.
509 Note that unlike with the old interface, no die and warn
510 handlers are installed by default. This means that if
511 you are not running an sfio enabled perl, any warn or
512 die message will not end up in the server's log by default.
513 It is advised you set up die and warn handlers yourself.
514 FCGI.pm contains an example of die and warn handlers.
518 Finishes accepted connection.
519 Also detaches filehandles.
523 Flushes accepted connection.
527 Temporarily detaches filehandles on an accepted connection.
531 Re-attaches filehandles on an accepted connection.
533 =item $req->LastCall()
535 Tells the library not to accept any more requests on this handle.
536 It should be safe to call this method from signal handlers.
538 Note that this method is still experimental and everything
539 about it, including its name, is subject to change.
541 =item $env = $req->GetEnvironment()
543 Returns the environment parameter passed to FCGI::Request.
545 =item ($in, $out, $err) = $req->GetHandles()
547 Returns the file handle parameters passed to FCGI::Request.
549 =item $isfcgi = $req->IsFastCGI()
551 Returns whether or not the program was run as a FastCGI.
557 Sven Verdoolaege <skimo@kotnet.org>