4 do 'FCGI.cfg' or die "no FCGI.cfg";
8 print "Generating FCGI.pm\n";
10 # $Id: FCGI.PL,v 1.31 2001/09/21 15:51:29 skimo Exp $
17 @ISA = qw(Exporter DynaLoader);
18 # Items to export into callers namespace by default. Note: do not export
19 # names by default without a very good reason. Use EXPORT_OK instead.
20 # Do not simply export all your public functions/methods/constants.
28 open VERSION, "version.pm";
34 print OUT "bootstrap FCGI;\n" unless ($pure);
36 print OUT <<'EOP' if ($pure);
40 use constant VERSION_1 => 1;
42 use constant BEGIN_REQUEST => 1;
43 use constant PARAMS => 4;
44 use constant FCGI_STDIN => 5;
45 use constant FCGI_STDOUT => 6;
46 use constant FCGI_STDERR => 7;
48 use constant RESPONDER => 1;
49 use constant AUTHORIZER => 2;
50 use constant FILTER => 3;
52 %FCGI::rolenames = (RESPONDER, "RESPONDER",
53 AUTHORIZER, "AUTHORIZER",
57 # This only works on Unix; anyone familiar with Windows is welcome
62 (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN
63 unless exists $req->{isfastcgi};
64 return $req->{isfastcgi};
68 return shift->{'env'};
74 return undef unless read $stream, $buf, 1, 0;
75 my ($len) = unpack("C", $buf);
77 $buf = pack("C", $len & 0x7F);
78 return undef unless read $stream, $buf, 3, 1;
79 $len = unpack("N", $buf);
94 open $self->{listen_sock}, "<&=0";
103 unless ($req->IsFastCGI()) {
104 return -1 if $run_once;
110 $req->{socket} = gensym();
111 if ($req->{last} || !accept($req->{socket}, $req->{listen_sock})) {
112 $req->{error} = "accept";
115 my ($type, $id, $body) = $req->read_record();
116 if ($type != BEGIN_REQUEST) {
117 $req->{error} = "begin request";
120 my ($role, $flags) = unpack("nC", $body);
121 $req->{role} = $role;
122 $req->{flags} = $flags;
126 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
127 my $param = FCGI::Stream->new($req, PARAMS);
129 while (defined($nlen = read_nv_len($param)) &&
130 defined($vlen = read_nv_len($param))) {
132 read $param, $name, $nlen;
133 read $param, $val, $vlen;
134 $req->{env}{$name} = $val;
137 $req->{accepted} = 1;
145 untie ${$req->{out}};
146 untie ${$req->{err}};
152 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
153 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
154 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
160 $req->Bind() if ($req->{accepted} && !$req->{bound});
165 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
170 return unless $req->{accepted};
172 $req->UndoBindings();
173 close ${$req->{out}};
174 close ${$req->{err}};
176 $req->{accepted} = 0;
191 read($self->{socket}, $header, 8);
192 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
193 read($self->{socket}, $body, $clen+$plen);
194 $body = undef if $clen == 0;
199 my ($self, $rtype, $len) = @_;
200 while (length $self->{buf} < $len) {
201 my ($type, $id, $buf) = $self->read_record();
202 return undef unless defined $buf;
203 if ($type != $rtype) {
204 $self->{error} = "unexpected stream type";
207 $self->{buf} .= $buf;
209 my ($newbuf, $result) = (substr($self->{buf}, $len),
210 substr($self->{buf}, 0, $len));
211 $self->{buf} = $newbuf;
220 my ($self, $type, $content, $len) = @_;
221 return unless $len > 0;
222 $self->write_record($type, $content, $len);
226 my ($self, $type, $content, $len) = @_;
227 my $padlen = (8 - ($len % 8)) % 8;
228 my $templ = "CCnnCxa${len}x$padlen";
229 my $data = pack($templ,
230 VERSION_1, $type, $self->{id}, $len, $padlen, $content);
231 syswrite $self->{socket}, $data;
234 { package FCGI::Stream;
237 my ($class, $src, $type) = @_;
238 my $handle = do { \local *FH };
239 tie($$handle, $class, $src, $type);
244 my ($class, $src, $type) = @_;
245 bless { src => $src, type => $type }, $class;
249 my ($stream, undef, $len, $offset) = @_;
251 my $buf = $stream->{src}->read($stream->{type}, $len);
252 return undef unless defined $buf;
253 substr($$ref, $offset, 0, $buf);
258 my ($stream) = shift;
260 $stream->{src}->write($stream->{type}, $_, length($_));
266 $stream->{src}->write_record($stream->{type}, undef, 0);
272 print OUT while <DATA>;
276 # Preloaded methods go here.
278 # Autoload methods go after __END__, and are processed by the autosplit program.
280 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
282 sub Request(;***$*$) {
283 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
284 $_[4] = fileno($_[4]) if defined(fileno($_[4]));
285 splice @defaults,0,@_,@_;
290 warn "accept called as a method; you probably wanted to call Accept" if @_;
291 if (defined %FCGI::ENV) {
296 my $rc = Accept($global_request);
297 for (keys %FCGI::ENV) {
298 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
302 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
303 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
309 warn "finish called as a method; you probably wanted to call Finish" if @_;
310 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
314 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
315 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
318 Finish ($global_request);
322 warn "flush called as a method; you probably wanted to call Flush" if @_;
323 Flush($global_request);
327 warn "detach called as a method; you probably wanted to call Detach" if @_;
328 Detach($global_request);
332 warn "attach called as a method; you probably wanted to call Attach" if @_;
333 Attach($global_request);
337 sub set_exit_status {
340 sub start_filter_data() {
341 StartFilterData($global_request);
344 $global_request = Request();
345 $warn_handler = sub { print STDERR @_ };
346 $die_handler = sub { print STDERR @_ unless $^S };
348 package FCGI::Stream;
351 shift->PRINT(sprintf(shift, @_));
360 my $rs = $/ eq '' ? "\n\n" : $/;
361 my $l = substr $rs, -1;
362 my $len = length $rs;
364 $c = $stream->GETC();
367 $c = $stream->GETC();
372 last if $c eq $l and substr($s, -$len) eq $rs;
373 $c = $stream->GETC();
381 return open($_[0], $_[1]);
384 eval("$rc = open($_[0], $_[1], $_[2])");
396 FCGI - Fast CGI module
403 my $request = FCGI::Request();
405 while($request->Accept() >= 0) {
406 print("Content-type: text/html\r\n\r\n", ++$count);
417 Creates a request handle. It has the following optional parameters:
421 =item input perl file handle (default: \*STDIN)
423 =item output perl file handle (default: \*STDOUT)
425 =item error perl file handle (default: \*STDERR)
427 These filehandles will be setup to act as input/output/error
430 =item environment hash reference (default: \%ENV)
432 The hash will be populated with the environment.
434 =item socket (default: 0)
436 Socket to communicate with the server.
437 Can be the result of the OpenSocket function.
438 For the moment, it's the file descriptor of the socket
439 that should be passed. This may change in the future.
441 You should only use your own socket if your program
442 is not started by a process manager such as mod_fastcgi
443 (except for the FastCgiExternalServer case) or cgi-fcgi.
444 If you use the option, you have to let your FastCGI
445 server know which port (and possibly server) your program
447 See remote.pl for an example.
449 =item flags (default: 0)
455 =item FCGI::FAIL_ACCEPT_ON_INTR
457 If set, Accept will fail if interrupted.
458 It not set, it will just keep on waiting.
465 my $req = FCGI::Request;
469 my $in = new IO::Handle;
470 my $out = new IO::Handle;
471 my $err = new IO::Handle;
472 my $req = FCGI::Request($in, $out, $err, \%env);
474 =item FCGI::OpenSocket(path, backlog)
476 Creates a socket suitable to use as an argument to Request.
482 Pathname of socket or colon followed by local tcp port.
483 Note that some systems take file permissions into account
484 on Unix domain sockets, so you'll have to make sure that
485 the server can write to the created file, by changing
486 the umask before the call and/or changing permissions and/or
487 group of the file afterwards.
491 Maximum length of the queue of pending connections.
493 request arrives with the queue full the client may receive
494 an error with an indication of ECONNREFUSED.
498 =item FCGI::CloseSocket(socket)
500 Close a socket opened with OpenSocket.
504 Accepts a connection on $req, attaching the filehandles and
505 populating the environment hash.
506 Returns 0 on success.
507 If a connection has been accepted before, the old
508 one will be finished first.
510 Note that unlike with the old interface, no die and warn
511 handlers are installed by default. This means that if
512 you are not running an sfio enabled perl, any warn or
513 die message will not end up in the server's log by default.
514 It is advised you set up die and warn handlers yourself.
515 FCGI.pm contains an example of die and warn handlers.
519 Finishes accepted connection.
520 Also detaches filehandles.
524 Flushes accepted connection.
528 Temporarily detaches filehandles on an accepted connection.
532 Re-attaches filehandles on an accepted connection.
534 =item $req->LastCall()
536 Tells the library not to accept any more requests on this handle.
537 It should be safe to call this method from signal handlers.
539 Note that this method is still experimental and everything
540 about it, including its name, is subject to change.
542 =item $env = $req->GetEnvironment()
544 Returns the environment parameter passed to FCGI::Request.
546 =item ($in, $out, $err) = $req->GetHandles()
548 Returns the file handle parameters passed to FCGI::Request.
550 =item $isfcgi = $req->IsFastCGI()
552 Returns whether or not the program was run as a FastCGI.
558 Sven Verdoolaege <skimo@kotnet.org>