2 use ExtUtils::MakeMaker;
4 do 'FCGI.cfg' or die "no FCGI.cfg";
8 print "Generating FCGI.pm\n";
10 # $Id: FCGI.PL,v 1.36 2002/12/15 20:01:46 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.
27 print OUT '$VERSION = '.MM->parse_version('version.pm').";\n\n";
29 print OUT "bootstrap FCGI;\n" unless ($pure);
31 print OUT <<'EOP' if ($pure);
35 use constant VERSION_1 => 1;
37 use constant BEGIN_REQUEST => 1;
38 use constant PARAMS => 4;
39 use constant FCGI_STDIN => 5;
40 use constant FCGI_STDOUT => 6;
41 use constant FCGI_STDERR => 7;
43 use constant RESPONDER => 1;
44 use constant AUTHORIZER => 2;
45 use constant FILTER => 3;
47 %FCGI::rolenames = (RESPONDER, "RESPONDER",
48 AUTHORIZER, "AUTHORIZER",
52 # This only works on Unix; anyone familiar with Windows is welcome
57 (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN
58 unless exists $req->{isfastcgi};
59 return $req->{isfastcgi};
63 return shift->{'env'};
69 return undef unless read $stream, $buf, 1, 0;
70 my ($len) = unpack("C", $buf);
72 $buf = pack("C", $len & 0x7F);
73 return undef unless read $stream, $buf, 3, 1;
74 $len = unpack("N", $buf);
89 open $self->{listen_sock}, "<&=0";
98 unless ($req->IsFastCGI()) {
99 return -1 if $run_once;
105 $req->{socket} = gensym();
106 if ($req->{last} || !accept($req->{socket}, $req->{listen_sock})) {
107 $req->{error} = "accept";
110 my ($type, $id, $body) = $req->read_record();
111 if ($type != BEGIN_REQUEST) {
112 $req->{error} = "begin request";
115 my ($role, $flags) = unpack("nC", $body);
116 $req->{role} = $role;
117 $req->{flags} = $flags;
121 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
122 my $param = FCGI::Stream->new($req, PARAMS);
124 while (defined($nlen = read_nv_len($param)) &&
125 defined($vlen = read_nv_len($param))) {
127 read $param, $name, $nlen;
128 read $param, $val, $vlen;
129 $req->{env}{$name} = $val;
132 $req->{accepted} = 1;
140 untie ${$req->{out}};
141 untie ${$req->{err}};
147 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
148 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
149 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
155 $req->Bind() if ($req->{accepted} && !$req->{bound});
160 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
165 return unless $req->{accepted};
167 $req->UndoBindings();
168 close ${$req->{out}};
169 close ${$req->{err}};
171 $req->{accepted} = 0;
186 read($self->{socket}, $header, 8);
187 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
188 read($self->{socket}, $body, $clen+$plen);
189 $body = undef if $clen == 0;
194 my ($self, $rtype, $len) = @_;
195 while (length $self->{buf} < $len) {
196 my ($type, $id, $buf) = $self->read_record();
197 return undef unless defined $buf;
198 if ($type != $rtype) {
199 $self->{error} = "unexpected stream type";
202 $self->{buf} .= $buf;
204 my ($newbuf, $result) = (substr($self->{buf}, $len),
205 substr($self->{buf}, 0, $len));
206 $self->{buf} = $newbuf;
215 my ($self, $type, $content, $len) = @_;
216 return unless $len > 0;
217 $self->write_record($type, $content, $len);
221 my ($self, $type, $content, $length) = @_;
223 while ($length > 0) {
224 my $len = $length > 32*1024 ? 32*1024 : $length;
225 my $padlen = (8 - ($len % 8)) % 8;
226 my $templ = "CCnnCxa${len}x$padlen";
227 my $data = pack($templ,
228 VERSION_1, $type, $self->{id}, $len, $padlen,
229 substr($content, $offset, $len));
230 syswrite $self->{socket}, $data;
236 { package FCGI::Stream;
239 my ($class, $src, $type) = @_;
240 my $handle = do { \local *FH };
241 tie($$handle, $class, $src, $type);
246 my ($class, $src, $type) = @_;
247 bless { src => $src, type => $type }, $class;
251 my ($stream, undef, $len, $offset) = @_;
253 my $buf = $stream->{src}->read($stream->{type}, $len);
254 return undef unless defined $buf;
255 substr($$ref, $offset, 0, $buf);
260 my ($stream) = shift;
262 $stream->{src}->write($stream->{type}, $_, length($_));
268 $stream->{src}->write_record($stream->{type}, undef, 0);
274 print OUT while <DATA>;
278 # Preloaded methods go here.
280 # Autoload methods go after __END__, and are processed by the autosplit program.
282 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
284 sub Request(;***$*$) {
285 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
286 $_[4] = fileno($_[4]) if defined($_[4]) && defined(fileno($_[4]));
287 splice @defaults,0,@_,@_;
292 warn "accept called as a method; you probably wanted to call Accept" if @_;
293 if (defined %FCGI::ENV) {
298 my $rc = Accept($global_request);
299 for (keys %FCGI::ENV) {
300 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
304 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
305 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
311 warn "finish called as a method; you probably wanted to call Finish" if @_;
312 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
316 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
317 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
320 Finish ($global_request);
324 warn "flush called as a method; you probably wanted to call Flush" if @_;
325 Flush($global_request);
329 warn "detach called as a method; you probably wanted to call Detach" if @_;
330 Detach($global_request);
334 warn "attach called as a method; you probably wanted to call Attach" if @_;
335 Attach($global_request);
339 sub set_exit_status {
342 sub start_filter_data() {
343 StartFilterData($global_request);
346 $global_request = Request();
347 $warn_handler = sub { print STDERR @_ };
348 $die_handler = sub { print STDERR @_ unless $^S };
350 package FCGI::Stream;
353 shift->PRINT(sprintf(shift, @_));
362 my $rs = $/ eq '' ? "\n\n" : $/;
363 my $l = substr $rs, -1;
364 my $len = length $rs;
366 $c = $stream->GETC();
369 $c = $stream->GETC();
374 last if $c eq $l and substr($s, -$len) eq $rs;
375 $c = $stream->GETC();
383 return open($_[0], $_[1]);
386 eval("$rc = open($_[0], $_[1], $_[2])");
392 # Apparently some use fileno to determine if a filehandle is open,
393 # so we might want to return a defined, but meaningless value.
394 # An alternative would be to return the fcgi stream fd.
403 FCGI - Fast CGI module
410 my $request = FCGI::Request();
412 while($request->Accept() >= 0) {
413 print("Content-type: text/html\r\n\r\n", ++$count);
424 Creates a request handle. It has the following optional parameters:
428 =item input perl file handle (default: \*STDIN)
430 =item output perl file handle (default: \*STDOUT)
432 =item error perl file handle (default: \*STDERR)
434 These filehandles will be setup to act as input/output/error
437 =item environment hash reference (default: \%ENV)
439 The hash will be populated with the environment.
441 =item socket (default: 0)
443 Socket to communicate with the server.
444 Can be the result of the OpenSocket function.
445 For the moment, it's the file descriptor of the socket
446 that should be passed. This may change in the future.
448 You should only use your own socket if your program
449 is not started by a process manager such as mod_fastcgi
450 (except for the FastCgiExternalServer case) or cgi-fcgi.
451 If you use the option, you have to let your FastCGI
452 server know which port (and possibly server) your program
454 See remote.pl for an example.
456 =item flags (default: 0)
462 =item FCGI::FAIL_ACCEPT_ON_INTR
464 If set, Accept will fail if interrupted.
465 It not set, it will just keep on waiting.
472 my $req = FCGI::Request;
476 my $in = new IO::Handle;
477 my $out = new IO::Handle;
478 my $err = new IO::Handle;
479 my $req = FCGI::Request($in, $out, $err, \%env);
481 =item FCGI::OpenSocket(path, backlog)
483 Creates a socket suitable to use as an argument to Request.
489 Pathname of socket or colon followed by local tcp port.
490 Note that some systems take file permissions into account
491 on Unix domain sockets, so you'll have to make sure that
492 the server can write to the created file, by changing
493 the umask before the call and/or changing permissions and/or
494 group of the file afterwards.
498 Maximum length of the queue of pending connections.
500 request arrives with the queue full the client may receive
501 an error with an indication of ECONNREFUSED.
505 =item FCGI::CloseSocket(socket)
507 Close a socket opened with OpenSocket.
511 Accepts a connection on $req, attaching the filehandles and
512 populating the environment hash.
513 Returns 0 on success.
514 If a connection has been accepted before, the old
515 one will be finished first.
517 Note that unlike with the old interface, no die and warn
518 handlers are installed by default. This means that if
519 you are not running an sfio enabled perl, any warn or
520 die message will not end up in the server's log by default.
521 It is advised you set up die and warn handlers yourself.
522 FCGI.pm contains an example of die and warn handlers.
526 Finishes accepted connection.
527 Also detaches filehandles.
531 Flushes accepted connection.
535 Temporarily detaches filehandles on an accepted connection.
539 Re-attaches filehandles on an accepted connection.
541 =item $req->LastCall()
543 Tells the library not to accept any more requests on this handle.
544 It should be safe to call this method from signal handlers.
546 Note that this method is still experimental and everything
547 about it, including its name, is subject to change.
549 =item $env = $req->GetEnvironment()
551 Returns the environment parameter passed to FCGI::Request.
553 =item ($in, $out, $err) = $req->GetHandles()
555 Returns the file handle parameters passed to FCGI::Request.
557 =item $isfcgi = $req->IsFastCGI()
559 Returns whether or not the program was run as a FastCGI.
565 Sven Verdoolaege <skimo@kotnet.org>