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.37 2002/12/15 20:02:48 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 # apparently these are harmful
169 # close ${$req->{out}};
170 # close ${$req->{err}};
172 $req->{accepted} = 0;
187 read($self->{socket}, $header, 8);
188 my ($version, $type, $id, $clen, $plen) = unpack("CCnnC", $header);
189 read($self->{socket}, $body, $clen+$plen);
190 $body = undef if $clen == 0;
195 my ($self, $rtype, $len) = @_;
196 while (length $self->{buf} < $len) {
197 my ($type, $id, $buf) = $self->read_record();
198 return undef unless defined $buf;
199 if ($type != $rtype) {
200 $self->{error} = "unexpected stream type";
203 $self->{buf} .= $buf;
205 my ($newbuf, $result) = (substr($self->{buf}, $len),
206 substr($self->{buf}, 0, $len));
207 $self->{buf} = $newbuf;
216 my ($self, $type, $content, $len) = @_;
217 return unless $len > 0;
218 $self->write_record($type, $content, $len);
222 my ($self, $type, $content, $length) = @_;
224 while ($length > 0) {
225 my $len = $length > 32*1024 ? 32*1024 : $length;
226 my $padlen = (8 - ($len % 8)) % 8;
227 my $templ = "CCnnCxa${len}x$padlen";
228 my $data = pack($templ,
229 VERSION_1, $type, $self->{id}, $len, $padlen,
230 substr($content, $offset, $len));
231 syswrite $self->{socket}, $data;
237 { package FCGI::Stream;
240 my ($class, $src, $type) = @_;
241 my $handle = do { \local *FH };
242 tie($$handle, $class, $src, $type);
247 my ($class, $src, $type) = @_;
248 bless { src => $src, type => $type }, $class;
252 my ($stream, undef, $len, $offset) = @_;
254 my $buf = $stream->{src}->read($stream->{type}, $len);
255 return undef unless defined $buf;
256 substr($$ref, $offset, 0, $buf);
261 my ($stream) = shift;
263 $stream->{src}->write($stream->{type}, $_, length($_));
269 $stream->{src}->write_record($stream->{type}, undef, 0);
275 print OUT while <DATA>;
279 # Preloaded methods go here.
281 # Autoload methods go after __END__, and are processed by the autosplit program.
283 *FAIL_ACCEPT_ON_INTR = sub() { 1 };
285 sub Request(;***$*$) {
286 my @defaults = (\*STDIN, \*STDOUT, \*STDERR, \%ENV, 0, 0);
287 $_[4] = fileno($_[4]) if defined($_[4]) && defined(fileno($_[4]));
288 splice @defaults,0,@_,@_;
293 warn "accept called as a method; you probably wanted to call Accept" if @_;
294 if (defined %FCGI::ENV) {
299 my $rc = Accept($global_request);
300 for (keys %FCGI::ENV) {
301 $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
305 $SIG{__WARN__} = $warn_handler if (tied (*STDIN));
306 $SIG{__DIE__} = $die_handler if (tied (*STDIN));
312 warn "finish called as a method; you probably wanted to call Finish" if @_;
313 %ENV = %FCGI::ENV if (defined %FCGI::ENV);
317 delete $SIG{__WARN__} if ($SIG{__WARN__} == $warn_handler);
318 delete $SIG{__DIE__} if ($SIG{__DIE__} == $die_handler);
321 Finish ($global_request);
325 warn "flush called as a method; you probably wanted to call Flush" if @_;
326 Flush($global_request);
330 warn "detach called as a method; you probably wanted to call Detach" if @_;
331 Detach($global_request);
335 warn "attach called as a method; you probably wanted to call Attach" if @_;
336 Attach($global_request);
340 sub set_exit_status {
343 sub start_filter_data() {
344 StartFilterData($global_request);
347 $global_request = Request();
348 $warn_handler = sub { print STDERR @_ };
349 $die_handler = sub { print STDERR @_ unless $^S };
351 package FCGI::Stream;
354 shift->PRINT(sprintf(shift, @_));
363 my $rs = $/ eq '' ? "\n\n" : $/;
364 my $l = substr $rs, -1;
365 my $len = length $rs;
367 $c = $stream->GETC();
370 $c = $stream->GETC();
375 last if $c eq $l and substr($s, -$len) eq $rs;
376 $c = $stream->GETC();
384 return open($_[0], $_[1]);
387 eval("$rc = open($_[0], $_[1], $_[2])");
393 # Some things (e.g. IPC::Run) use fileno to determine if a filehandle is open,
394 # so we return a defined, but meaningless value. (-1 being the error return
395 # value from the syscall in c, meaning it can never be a valid fd no)
396 # Probably a better alternative would be to return the fcgi stream fd.
405 FCGI - Fast CGI module
412 my $request = FCGI::Request();
414 while($request->Accept() >= 0) {
415 print("Content-type: text/html\r\n\r\n", ++$count);
426 Creates a request handle. It has the following optional parameters:
430 =item input perl file handle (default: \*STDIN)
432 =item output perl file handle (default: \*STDOUT)
434 =item error perl file handle (default: \*STDERR)
436 These filehandles will be setup to act as input/output/error
439 =item environment hash reference (default: \%ENV)
441 The hash will be populated with the environment.
443 =item socket (default: 0)
445 Socket to communicate with the server.
446 Can be the result of the OpenSocket function.
447 For the moment, it's the file descriptor of the socket
448 that should be passed. This may change in the future.
450 You should only use your own socket if your program
451 is not started by a process manager such as mod_fastcgi
452 (except for the FastCgiExternalServer case) or cgi-fcgi.
453 If you use the option, you have to let your FastCGI
454 server know which port (and possibly server) your program
456 See remote.pl for an example.
458 =item flags (default: 0)
464 =item FCGI::FAIL_ACCEPT_ON_INTR
466 If set, Accept will fail if interrupted.
467 It not set, it will just keep on waiting.
474 my $req = FCGI::Request;
478 my $in = new IO::Handle;
479 my $out = new IO::Handle;
480 my $err = new IO::Handle;
481 my $req = FCGI::Request($in, $out, $err, \%env);
483 =item FCGI::OpenSocket(path, backlog)
485 Creates a socket suitable to use as an argument to Request.
491 Pathname of socket or colon followed by local tcp port.
492 Note that some systems take file permissions into account
493 on Unix domain sockets, so you'll have to make sure that
494 the server can write to the created file, by changing
495 the umask before the call and/or changing permissions and/or
496 group of the file afterwards.
500 Maximum length of the queue of pending connections.
502 request arrives with the queue full the client may receive
503 an error with an indication of ECONNREFUSED.
507 =item FCGI::CloseSocket(socket)
509 Close a socket opened with OpenSocket.
513 Accepts a connection on $req, attaching the filehandles and
514 populating the environment hash.
515 Returns 0 on success.
516 If a connection has been accepted before, the old
517 one will be finished first.
519 Note that unlike with the old interface, no die and warn
520 handlers are installed by default. This means that if
521 you are not running an sfio enabled perl, any warn or
522 die message will not end up in the server's log by default.
523 It is advised you set up die and warn handlers yourself.
524 FCGI.pm contains an example of die and warn handlers.
528 Finishes accepted connection.
529 Also detaches filehandles.
533 Flushes accepted connection.
537 Temporarily detaches filehandles on an accepted connection.
541 Re-attaches filehandles on an accepted connection.
543 =item $req->LastCall()
545 Tells the library not to accept any more requests on this handle.
546 It should be safe to call this method from signal handlers.
548 Note that this method is still experimental and everything
549 about it, including its name, is subject to change.
551 =item $env = $req->GetEnvironment()
553 Returns the environment parameter passed to FCGI::Request.
555 =item ($in, $out, $err) = $req->GetHandles()
557 Returns the file handle parameters passed to FCGI::Request.
559 =item $isfcgi = $req->IsFastCGI()
561 Returns whether or not the program was run as a FastCGI.
567 Sven Verdoolaege <skimo@kotnet.org>