3 do 'FCGI.cfg' or die "no FCGI.cfg";
7 print "Generating FCGI.pm\n";
9 # $Id: FCGI.PL,v 1.26 2001/08/22 17:20:20 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",
53 (!defined getpeername shift->{listen_sock}) && $! == ENOTCONN
54 unless exists $req->{isfastcgi};
55 return $req->{isfastcgi};
61 return undef unless read $stream, $buf, 1, 0;
62 my ($len) = unpack("C", $buf);
64 $buf = pack("C", $len & 0x7F);
65 return undef unless read $stream, $buf, 3, 1;
66 $len = unpack("N", $buf);
80 open $self->{listen_sock}, "<&=0";
89 unless ($req->IsFastCGI()) {
90 return -1 if $run_once;
96 $req->{socket} = gensym();
97 if (!accept($req->{socket}, $req->{listen_sock})) {
98 $req->{error} = "accept";
101 my ($type, $id, $body) = $req->read_record();
102 if ($type != BEGIN_REQUEST) {
103 $req->{error} = "begin request";
106 my ($role, $flags) = unpack("nC", $body);
107 $req->{role} = $role;
108 $req->{flags} = $flags;
112 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
113 my $param = FCGI::Stream->new($req, PARAMS);
115 while (defined($nlen = read_nv_len($param)) &&
116 defined($vlen = read_nv_len($param))) {
118 read $param, $name, $nlen;
119 read $param, $val, $vlen;
120 $req->{env}{$name} = $val;
123 $req->{accepted} = 1;
131 untie ${$req->{out}};
132 untie ${$req->{err}};
138 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
139 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
140 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
146 $req->Bind() if ($req->{accepted} && !$req->{bound});
151 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
156 return unless $req->{accepted};
158 $req->UndoBindings();
159 close ${$req->{out}};
160 close ${$req->{err}};
162 $req->{accepted} = 0;
173 read($self->{socket}, $header, 8);
174 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
175 read($self->{socket}, $body, $clen+$plen);
176 $body = undef if $clen == 0;
181 my ($self, $rtype, $len) = @_;
182 while (length $self->{buf} < $len) {
183 my ($type, $id, $buf) = $self->read_record();
184 return undef unless defined $buf;
185 if ($type != $rtype) {
186 $self->{error} = "unexpected stream type";
189 $self->{buf} .= $buf;
191 my ($newbuf, $result) = (substr($self->{buf}, $len),
192 substr($self->{buf}, 0, $len));
193 $self->{buf} = $newbuf;
202 my ($self, $type, $content, $len) = @_;
203 return unless $len > 0;
204 $self->write_record($type, $content, $len);
208 my ($self, $type, $content, $len) = @_;
209 my $padlen = (8 - ($len % 8)) % 8;
210 my $templ = "CCnnCxa${len}x$padlen";
211 my $data = pack($templ,
212 VERSION_1, $type, $self->{id}, $len, $padlen, $content);
213 syswrite $self->{socket}, $data;
216 { package FCGI::Stream;
219 my ($class, $src, $type) = @_;
220 my $handle = do { \local *FH };
221 tie($$handle, $class, $src, $type);
226 my ($class, $src, $type) = @_;
227 bless { src => $src, type => $type }, $class;
231 my ($stream, undef, $len, $offset) = @_;
233 my $buf = $stream->{src}->read($stream->{type}, $len);
234 return undef unless defined $buf;
235 substr($$ref, $offset, 0, $buf);
240 my ($stream) = shift;
242 $stream->{src}->write($stream->{type}, $_, length($_));
248 $stream->{src}->write_record($stream->{type}, undef, 0);
254 print OUT while <DATA>;
258 # Preloaded methods go here.
260 # Autoload methods go after __END__, and are processed by the autosplit program.
262 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
264 sub Request(;***$*$) {
265 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
266 $_[4] = fileno($_[4]) if defined(fileno($_[4]));
267 splice @defaults,0,@_,@_;
272 warn "accept called as a method; you probably wanted to call Accept" if @_;
273 if (defined %FCGI::ENV) {
278 my $rc = Accept($global_request);
279 for (keys %FCGI::ENV) {
280 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
284 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
285 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
291 warn "finish called as a method; you probably wanted to call Finish" if @_;
292 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
296 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
297 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
300 Finish ($global_request);
304 warn "flush called as a method; you probably wanted to call Flush" if @_;
305 Flush($global_request);
309 warn "detach called as a method; you probably wanted to call Detach" if @_;
310 Detach($global_request);
314 warn "attach called as a method; you probably wanted to call Attach" if @_;
315 Attach($global_request);
319 sub set_exit_status {
322 sub start_filter_data() {
323 StartFilterData($global_request);
326 $global_request = Request();
327 $warn_handler = sub { print STDERR @_ };
328 $die_handler = sub { print STDERR @_ unless $^S };
330 package FCGI::Stream;
333 shift->PRINT(sprintf(shift, @_));
342 my $rs = $/ eq '' ? "\n\n" : $/;
343 my $l = substr $rs, -1;
344 my $len = length $rs;
346 $c = $stream->GETC();
349 $c = $stream->GETC();
354 last if $c eq $l and substr($s, -$len) eq $rs;
355 $c = $stream->GETC();
363 return open($_[0], $_[1]);
366 eval("$rc = open($_[0], $_[1], $_[2])");
378 FCGI - Fast CGI module
385 my $request = FCGI::Request();
387 while($request->Accept() >= 0) {
388 print("Content-type: text/html\r\n\r\n", ++$count);
399 Creates a request handle. It has the following optional parameters:
403 =item input perl file handle (default: \*STDIN)
405 =item output perl file handle (default: \*STDOUT)
407 =item error perl file handle (default: \*STDERR)
409 These filehandles will be setup to act as input/output/error
412 =item environment hash reference (default: \%ENV)
414 The hash will be populated with the environment.
416 =item socket (default: 0)
418 Socket to communicate with the server.
419 Can be the result of the OpenSocket function.
420 For the moment, it's the file descriptor of the socket
421 that should be passed. This may change in the future.
423 You should only use your own socket if your program
424 is not started by a process manager such as mod_fastcgi
425 (except for the FastCgiExternalServer case) or cgi-fcgi.
426 If you use the option, you have to let your FastCGI
427 server know which port (and possibly server) your program
429 See remote.pl for an example.
431 =item flags (default: 0)
437 =item FCGI::FAIL_ACCEPT_ON_INTR
439 If set, Accept will fail if interrupted.
440 It not set, it will just keep on waiting.
447 my $req = FCGI::Request;
451 my $in = new IO::Handle;
452 my $out = new IO::Handle;
453 my $err = new IO::Handle;
454 my $req = FCGI::Request($in, $out, $err, \%env);
456 =item FCGI::OpenSocket(path, backlog)
458 Creates a socket suitable to use as an argument to Request.
464 Pathname of socket or colon followed by local tcp port.
465 Note that some systems take file permissions into account
466 on Unix domain sockets, so you'll have to make sure that
467 the server can write to the created file, by changing
468 the umask before the call and/or changing permissions and/or
469 group of the file afterwards.
473 Maximum length of the queue of pending connections.
475 request arrives with the queue full the client may receive
476 an error with an indication of ECONNREFUSED.
480 =item FCGI::CloseSocket(socket)
482 Close a socket opened with OpenSocket.
486 Accepts a connection on $req, attaching the filehandles and
487 populating the environment hash.
488 Returns 0 on success.
489 If a connection has been accepted before, the old
490 one will be finished first.
492 Note that unlike with the old interface, no die and warn
493 handlers are installed by default. This means that if
494 you are not running an sfio enabled perl, any warn or
495 die message will not end up in the server's log by default.
496 It is advised you set up die and warn handlers yourself.
497 FCGI.pm contains an example of die and warn handlers.
501 Finishes accepted connection.
502 Also detaches filehandles.
506 Flushes accepted connection.
510 Temporarily detaches filehandles on an accepted connection.
514 Re-attaches filehandles on an accepted connection.
516 =item $env = $req->GetEnvironment()
518 Returns the environment parameter passed to FCGI::Request.
520 =item ($in, $out, $err) = $req->GetHandles()
522 Returns the file handle parameters passed to FCGI::Request.
524 =item $isfcgi = $req->IsFastCGI()
526 Returns whether or not the program was run as a FastCGI.
532 Sven Verdoolaege <skimo@kotnet.org>