3 do 'FCGI.cfg' or die "no FCGI.cfg";
7 print "Generating FCGI.pm\n";
9 # $Id: FCGI.PL,v 1.24 2001/04/30 15:35:18 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 return undef unless read $stream, $buf, 3, 1;
65 $len = unpack("N", $buf);
79 open $self->{listen_sock}, "<&=0";
88 unless ($req->IsFastCGI()) {
89 return -1 if $run_once;
95 $req->{socket} = gensym();
96 if (!accept($req->{socket}, $req->{listen_sock})) {
97 $req->{error} = "accept";
100 my ($type, $id, $body) = $req->read_record();
101 if ($type != BEGIN_REQUEST) {
102 $req->{error} = "begin request";
105 my ($role, $flags) = unpack("nC", $body);
106 $req->{role} = $role;
107 $req->{flags} = $flags;
111 $req->{env}{FCGI_ROLE} = $FCGI::rolenames{$req->{role}};
112 my $param = FCGI::Stream->new($req, PARAMS);
114 while (defined($nlen = read_nv_len($param)) &&
115 defined($vlen = read_nv_len($param))) {
117 read $param, $name, $nlen;
118 read $param, $val, $vlen;
119 $req->{env}{$name} = $val;
122 $req->{accepted} = 1;
130 untie ${$req->{out}};
131 untie ${$req->{err}};
137 tie ${$req->{in}}, 'FCGI::Stream', $req, FCGI_STDIN;
138 tie ${$req->{out}}, 'FCGI::Stream', $req, FCGI_STDOUT;
139 tie ${$req->{err}}, 'FCGI::Stream', $req, FCGI_STDERR;
145 $req->Bind() if ($req->{accepted} && !$req->{bound});
150 $req->UndoBindings() if ($req->{accepted} && $req->{bound});
155 return unless $req->{accepted};
157 $req->UndoBindings();
158 close ${$req->{out}};
159 close ${$req->{err}};
161 $req->{accepted} = 0;
172 read($self->{socket}, $header, 8);
173 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
174 read($self->{socket}, $body, $clen+$plen);
175 $body = undef if $clen == 0;
180 my ($self, $rtype, $len) = @_;
181 while (length $self->{buf} < $len) {
182 my ($type, $id, $buf) = $self->read_record();
183 return undef unless defined $buf;
184 if ($type != $rtype) {
185 $self->{error} = "unexpected stream type";
188 $self->{buf} .= $buf;
190 my ($newbuf, $result) = (substr($self->{buf}, $len),
191 substr($self->{buf}, 0, $len));
192 $self->{buf} = $newbuf;
201 my ($self, $type, $content, $len) = @_;
202 return unless $len > 0;
203 $self->write_record($type, $content, $len);
207 my ($self, $type, $content, $len) = @_;
208 my $padlen = (8 - ($len % 8)) % 8;
209 my $templ = "CCnnCxa${len}x$padlen";
210 my $data = pack($templ,
211 VERSION_1, $type, $self->{id}, $len, $padlen, $content);
212 syswrite $self->{socket}, $data;
215 { package FCGI::Stream;
218 my ($class, $src, $type) = @_;
219 my $handle = do { \local *FH };
220 tie($$handle, $class, $src, $type);
225 my ($class, $src, $type) = @_;
226 bless { src => $src, type => $type }, $class;
230 my ($stream, undef, $len, $offset) = @_;
232 my $buf = $stream->{src}->read($stream->{type}, $len);
233 return undef unless defined $buf;
234 substr($$ref, $offset, 0, $buf);
239 my ($stream) = shift;
241 $stream->{src}->write($stream->{type}, $_, length($_));
247 $stream->{src}->write_record($stream->{type}, undef, 0);
253 print OUT while <DATA>;
257 # Preloaded methods go here.
259 # Autoload methods go after __END__, and are processed by the autosplit program.
261 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
263 sub Request(;***$$$) {
264 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
265 splice @defaults,0,@_,@_;
270 warn "accept called as a method; you probably wanted to call Accept" if @_;
271 if (defined %FCGI::ENV) {
276 my $rc = Accept($global_request);
277 for (keys %FCGI::ENV) {
278 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
282 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
283 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
289 warn "finish called as a method; you probably wanted to call Finish" if @_;
290 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
294 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
295 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
298 Finish ($global_request);
302 warn "flush called as a method; you probably wanted to call Flush" if @_;
303 Flush($global_request);
307 warn "detach called as a method; you probably wanted to call Detach" if @_;
308 Detach($global_request);
312 warn "attach called as a method; you probably wanted to call Attach" if @_;
313 Attach($global_request);
317 sub set_exit_status {
320 sub start_filter_data() {
321 StartFilterData($global_request);
324 $global_request = Request();
325 $warn_handler = sub { print STDERR @_ };
326 $die_handler = sub { print STDERR @_ unless $^S };
328 package FCGI::Stream;
331 shift->PRINT(sprintf(shift, @_));
340 my $rs = $/ eq '' ? "\n\n" : $/;
341 my $l = substr $rs, -1;
342 my $len = length $rs;
344 $c = $stream->GETC();
347 $c = $stream->GETC();
352 last if $c eq $l and substr($s, -$len) eq $rs;
353 $c = $stream->GETC();
361 return open($_[0], $_[1]);
364 eval("$rc = open($_[0], $_[1], $_[2])");
376 FCGI - Fast CGI module
383 my $request = FCGI::Request();
385 while($request->Accept() >= 0) {
386 print("Content-type: text/html\r\n\r\n", ++$count);
397 Creates a request handle. It has the following optional parameters:
401 =item input perl file handle (default: \*STDIN)
403 =item output perl file handle (default: \*STDOUT)
405 =item error perl file handle (default: \*STDERR)
407 These filehandles will be setup to act as input/output/error
410 =item environment hash reference (default: \%ENV)
412 The hash will be populated with the environment.
414 =item socket (default: 0)
416 Socket to communicate with the server.
417 Can be the result of the OpenSocket function.
418 For the moment, it's the file descriptor of the socket
419 that should be passed. This may change in the future.
421 You should only use your own socket if your program
422 is not started by a process manager such as mod_fastcgi
423 (except for the FastCgiExternalServer case) or cgi-fcgi.
424 If you use the option, you have to let your FastCGI
425 server know which port (and possibly server) your program
427 See remote.pl for an example.
429 =item flags (default: 0)
435 =item FCGI::FAIL_ACCEPT_ON_INTR
437 If set, Accept will fail if interrupted.
438 It not set, it will just keep on waiting.
445 my $req = FCGI::Request;
449 my $in = new IO::Handle;
450 my $out = new IO::Handle;
451 my $err = new IO::Handle;
452 my $req = FCGI::Request($in, $out, $err, \%env);
454 =item FCGI::OpenSocket(path, backlog)
456 Creates a socket suitable to use as an argument to Request.
462 Pathname of socket or colon followed by local tcp port.
463 Note that some systems take file permissions into account
464 on Unix domain sockets, so you'll have to make sure that
465 the server can write to the created file, by changing
466 the umask before the call and/or changing permissions and/or
467 group of the file afterwards.
471 Maximum length of the queue of pending connections.
473 request arrives with the queue full the client may receive
474 an error with an indication of ECONNREFUSED.
478 =item FCGI::CloseSocket(socket)
480 Close a socket opened with OpenSocket.
484 Accepts a connection on $req, attaching the filehandles and
485 populating the environment hash.
486 Returns 0 on success.
487 If a connection has been accepted before, the old
488 one will be finished first.
490 Note that unlike with the old interface, no die and warn
491 handlers are installed by default. This means that if
492 you are not running an sfio enabled perl, any warn or
493 die message will not end up in the server's log by default.
494 It is advised you set up die and warn handlers yourself.
495 FCGI.pm contains an example of die and warn handlers.
499 Finishes accepted connection.
500 Also detaches filehandles.
504 Flushes accepted connection.
508 Temporarily detaches filehandles on an accepted connection.
512 Re-attaches filehandles on an accepted connection.
514 =item $env = $req->GetEnvironment()
516 Returns the environment parameter passed to FCGI::Request.
518 =item ($in, $out, $err) = $req->GetHandles()
520 Returns the file handle parameters passed to FCGI::Request.
522 =item $isfcgi = $req->IsFastCGI()
524 Returns whether or not the program was run as a FastCGI.
530 Sven Verdoolaege <skimo@kotnet.org>