3 do 'FCGI.cfg' or die "no FCGI.cfg";
7 print "Generating FCGI.pm\n";
9 # $Id: FCGI.PL,v 1.30 2001/09/20 12:00:23 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.
28 print OUT "bootstrap FCGI;\n" unless ($pure);
30 print OUT <<'EOP' if ($pure);
34 use constant VERSION_1 => 1;
36 use constant BEGIN_REQUEST => 1;
37 use constant PARAMS => 4;
38 use constant FCGI_STDIN => 5;
39 use constant FCGI_STDOUT => 6;
40 use constant FCGI_STDERR => 7;
42 use constant RESPONDER => 1;
43 use constant AUTHORIZER => 2;
44 use constant FILTER => 3;
46 %FCGI::rolenames = (RESPONDER, "RESPONDER",
47 AUTHORIZER, "AUTHORIZER",
51 # This only works on Unix; anyone familiar with Windows is welcome
56 (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN
57 unless exists $req->{isfastcgi};
58 return $req->{isfastcgi};
62 return shift->{'env'};
68 return undef unless read $stream, $buf, 1, 0;
69 my ($len) = unpack("C", $buf);
71 $buf = pack("C", $len & 0x7F);
72 return undef unless read $stream, $buf, 3, 1;
73 $len = unpack("N", $buf);
88 open $self->{listen_sock}, "<&=0";
97 unless ($req->IsFastCGI()) {
98 return -1 if $run_once;
104 $req->{socket} = gensym();
105 if ($req->{last} || !accept($req->{socket}, $req->{listen_sock})) {
106 $req->{error} = "accept";
109 my ($type, $id, $body) = $req->read_record();
110 if ($type != BEGIN_REQUEST) {
111 $req->{error} = "begin request";
114 my ($role, $flags) = unpack("nC", $body);
115 $req->{role} = $role;
116 $req->{flags} = $flags;
120 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
121 my $param = FCGI::Stream->new($req, PARAMS);
123 while (defined($nlen = read_nv_len($param)) &&
124 defined($vlen = read_nv_len($param))) {
126 read $param, $name, $nlen;
127 read $param, $val, $vlen;
128 $req->{env}{$name} = $val;
131 $req->{accepted} = 1;
139 untie ${$req->{out}};
140 untie ${$req->{err}};
146 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
147 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
148 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
154 $req->Bind() if ($req->{accepted} && !$req->{bound});
159 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
164 return unless $req->{accepted};
166 $req->UndoBindings();
167 close ${$req->{out}};
168 close ${$req->{err}};
170 $req->{accepted} = 0;
185 read($self->{socket}, $header, 8);
186 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
187 read($self->{socket}, $body, $clen+$plen);
188 $body = undef if $clen == 0;
193 my ($self, $rtype, $len) = @_;
194 while (length $self->{buf} < $len) {
195 my ($type, $id, $buf) = $self->read_record();
196 return undef unless defined $buf;
197 if ($type != $rtype) {
198 $self->{error} = "unexpected stream type";
201 $self->{buf} .= $buf;
203 my ($newbuf, $result) = (substr($self->{buf}, $len),
204 substr($self->{buf}, 0, $len));
205 $self->{buf} = $newbuf;
214 my ($self, $type, $content, $len) = @_;
215 return unless $len > 0;
216 $self->write_record($type, $content, $len);
220 my ($self, $type, $content, $len) = @_;
221 my $padlen = (8 - ($len % 8)) % 8;
222 my $templ = "CCnnCxa${len}x$padlen";
223 my $data = pack($templ,
224 VERSION_1, $type, $self->{id}, $len, $padlen, $content);
225 syswrite $self->{socket}, $data;
228 { package FCGI::Stream;
231 my ($class, $src, $type) = @_;
232 my $handle = do { \local *FH };
233 tie($$handle, $class, $src, $type);
238 my ($class, $src, $type) = @_;
239 bless { src => $src, type => $type }, $class;
243 my ($stream, undef, $len, $offset) = @_;
245 my $buf = $stream->{src}->read($stream->{type}, $len);
246 return undef unless defined $buf;
247 substr($$ref, $offset, 0, $buf);
252 my ($stream) = shift;
254 $stream->{src}->write($stream->{type}, $_, length($_));
260 $stream->{src}->write_record($stream->{type}, undef, 0);
266 print OUT while <DATA>;
270 # Preloaded methods go here.
272 # Autoload methods go after __END__, and are processed by the autosplit program.
274 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
276 sub Request(;***$*$) {
277 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
278 $_[4] = fileno($_[4]) if defined(fileno($_[4]));
279 splice @defaults,0,@_,@_;
284 warn "accept called as a method; you probably wanted to call Accept" if @_;
285 if (defined %FCGI::ENV) {
290 my $rc = Accept($global_request);
291 for (keys %FCGI::ENV) {
292 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
296 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
297 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
303 warn "finish called as a method; you probably wanted to call Finish" if @_;
304 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
308 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
309 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
312 Finish ($global_request);
316 warn "flush called as a method; you probably wanted to call Flush" if @_;
317 Flush($global_request);
321 warn "detach called as a method; you probably wanted to call Detach" if @_;
322 Detach($global_request);
326 warn "attach called as a method; you probably wanted to call Attach" if @_;
327 Attach($global_request);
331 sub set_exit_status {
334 sub start_filter_data() {
335 StartFilterData($global_request);
338 $global_request = Request();
339 $warn_handler = sub { print STDERR @_ };
340 $die_handler = sub { print STDERR @_ unless $^S };
342 package FCGI::Stream;
345 shift->PRINT(sprintf(shift, @_));
354 my $rs = $/ eq '' ? "\n\n" : $/;
355 my $l = substr $rs, -1;
356 my $len = length $rs;
358 $c = $stream->GETC();
361 $c = $stream->GETC();
366 last if $c eq $l and substr($s, -$len) eq $rs;
367 $c = $stream->GETC();
375 return open($_[0], $_[1]);
378 eval("$rc = open($_[0], $_[1], $_[2])");
390 FCGI - Fast CGI module
397 my $request = FCGI::Request();
399 while($request->Accept() >= 0) {
400 print("Content-type: text/html\r\n\r\n", ++$count);
411 Creates a request handle. It has the following optional parameters:
415 =item input perl file handle (default: \*STDIN)
417 =item output perl file handle (default: \*STDOUT)
419 =item error perl file handle (default: \*STDERR)
421 These filehandles will be setup to act as input/output/error
424 =item environment hash reference (default: \%ENV)
426 The hash will be populated with the environment.
428 =item socket (default: 0)
430 Socket to communicate with the server.
431 Can be the result of the OpenSocket function.
432 For the moment, it's the file descriptor of the socket
433 that should be passed. This may change in the future.
435 You should only use your own socket if your program
436 is not started by a process manager such as mod_fastcgi
437 (except for the FastCgiExternalServer case) or cgi-fcgi.
438 If you use the option, you have to let your FastCGI
439 server know which port (and possibly server) your program
441 See remote.pl for an example.
443 =item flags (default: 0)
449 =item FCGI::FAIL_ACCEPT_ON_INTR
451 If set, Accept will fail if interrupted.
452 It not set, it will just keep on waiting.
459 my $req = FCGI::Request;
463 my $in = new IO::Handle;
464 my $out = new IO::Handle;
465 my $err = new IO::Handle;
466 my $req = FCGI::Request($in, $out, $err, \%env);
468 =item FCGI::OpenSocket(path, backlog)
470 Creates a socket suitable to use as an argument to Request.
476 Pathname of socket or colon followed by local tcp port.
477 Note that some systems take file permissions into account
478 on Unix domain sockets, so you'll have to make sure that
479 the server can write to the created file, by changing
480 the umask before the call and/or changing permissions and/or
481 group of the file afterwards.
485 Maximum length of the queue of pending connections.
487 request arrives with the queue full the client may receive
488 an error with an indication of ECONNREFUSED.
492 =item FCGI::CloseSocket(socket)
494 Close a socket opened with OpenSocket.
498 Accepts a connection on $req, attaching the filehandles and
499 populating the environment hash.
500 Returns 0 on success.
501 If a connection has been accepted before, the old
502 one will be finished first.
504 Note that unlike with the old interface, no die and warn
505 handlers are installed by default. This means that if
506 you are not running an sfio enabled perl, any warn or
507 die message will not end up in the server's log by default.
508 It is advised you set up die and warn handlers yourself.
509 FCGI.pm contains an example of die and warn handlers.
513 Finishes accepted connection.
514 Also detaches filehandles.
518 Flushes accepted connection.
522 Temporarily detaches filehandles on an accepted connection.
526 Re-attaches filehandles on an accepted connection.
528 =item $req->LastCall()
530 Tells the library not to accept any more requests on this handle.
531 It should be safe to call this method from signal handlers.
533 Note that this method is still experimental and everything
534 about it, including its name, is subject to change.
536 =item $env = $req->GetEnvironment()
538 Returns the environment parameter passed to FCGI::Request.
540 =item ($in, $out, $err) = $req->GetHandles()
542 Returns the file handle parameters passed to FCGI::Request.
544 =item $isfcgi = $req->IsFastCGI()
546 Returns whether or not the program was run as a FastCGI.
552 Sven Verdoolaege <skimo@kotnet.org>