#!/usr/bin/env perl

use Plack::Runner;
use strict;
use warnings;
use POSIX;
use Getopt::Std;

our %opts;
my %_apps;

getopts( 'Fn:p:s:u:g:f:e:', \%opts );

$SIG{'PIPE'} = 'IGNORE';

$opts{e} ||= $ENV{ENGINE} || 'FCGI';
$opts{n} ||= $ENV{NPROC}  || 7;
$opts{p} ||= $ENV{PID}    || '__FASTCGISOCKDIR__/llng-fastcgi.pid';
$opts{s} ||= $ENV{SOCKET} || '__FASTCGISOCKDIR__/llng-fastcgi.sock';
$opts{u} ||= $ENV{USER};
$opts{g} ||= $ENV{GROUP};
$opts{f} ||= $ENV{CUSTOM_FUNCTIONS_FILE};

if ( $opts{g} ) {
    my $grp = getgrnam( $opts{g} ) or warn "Can't change uid to $opts{g}";
    POSIX::setgid($grp);
}

if ( $opts{u} ) {
    my $uid = getpwnam( $opts{u} ) or warn "Can't change uid to $opts{u}";
    POSIX::setuid($uid);
}

if ( $opts{f} ) {
    eval { require $opts{f} };
    die $@ if ($@);
}

my %builder = (
    handler => sub {
        require Lemonldap::NG::Handler::Nginx;
        return Lemonldap::NG::Handler::Nginx->run( {} );
    },
    reload => sub {
        require Lemonldap::NG::Handler::Nginx;
        return Lemonldap::NG::Handler::Nginx->reload();
    },
    status => sub {
        require Lemonldap::NG::Handler::Nginx;
        return Lemonldap::NG::Handler::Nginx->status();
    },
    manager => sub {
        require Lemonldap::NG::Manager;
        return Lemonldap::NG::Manager->run( {} );
    },
    cgi => sub {
        require CGI::Emulate::PSGI;
        require CGI::Compile;
        return sub {
            my $script = $_[0]->{SCRIPT_FILENAME};
            return $_apps{$script}->(@_) if ( $_apps{$script} );
            $_apps{$script} =
              CGI::Emulate::PSGI->handler( CGI::Compile->compile($script) );
            return $_apps{$script}->(@_);
        };
    },
);

unless ($>) {
    die "Refuse to run as root. Aborting";
}

my $app = sub {
    my $type = $_[0]->{LLTYPE} || 'handler';
    return $_apps{$type}->(@_) if ( defined $_apps{$type} );
    if ( defined $builder{$type} ) {
        $_apps{$type} = $builder{$type}->();
        return $_apps{$type}->(@_);
    }
    die "Unknown PSGI type $type";
};

# Hook for customFunctions initialization
use Lemonldap::NG::Handler::PSGI::API;
Lemonldap::NG::Handler::PSGI::API->init();

my $server = Plack::Runner->new();
$server->parse_options(
    '-s'           => $opts{e},
    '-E'           => 'deployment',
    '--pid'        => $opts{p},
    '--nproc'      => $opts{n},
    '--socket'     => $opts{s},
    '--proc-title' => 'llng-fastcgi-server',
    ( $opts{F} ? () : '--daemonize' ),
    '--no-default-middleware',
);

$server->run($app);
__END__

=head1 NAME

=encoding utf8

llng-fastcgi-server - FastCGI server used to provide Lemonldap::NG services to
Nginx

=head1 SYNOPSIS

  # Start server listening to /run/llng.sock with 10 process
  llng-fastcgi-server -u nobody -g nobody -s /run/llng.sock -n 10

=head1 DESCRIPTION

llng-fastcgi-server has been designed provides Lemonldap::NG services to Nginx.
Portal, manager and handler will be compiled only is used. So this FastCGI
server can be used on every Lemonldap::NG server even if it needs only some
parts (isolated handlers, portal,...).

=head1 PARAMETERS

Each parameter can be set by an option or a environment variable.

=over

=item -p ($ENV{PID}):                   pid file

=item -u ($ENV{USER}):                  user

=item -g ($ENV{GROUP}):                 group

=item -n ($ENV{NPROC}):                 Number of processus for FCGI

=item -e ($ENV{ENGINE}):                Plack::Handler engine, default to FCGI

=item -s ($ENV{SOCKET}):                Unix socket

=item -f ($ENV{CUSTOM_FUNCTIONS_FILE}): file to load for custom functions

=back

=head1 SEE ALSO

L<http://lemonldap-ng.org/>

=head1 AUTHORS

=over

=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>

=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>

=back

=head1 BUG REPORT

Use OW2 system to report bug or ask for features:
L<http://jira.ow2.org>

=head1 DOWNLOAD

Lemonldap::NG is available at
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>

=head1 COPYRIGHT AND LICENSE

=over

=item Copyright (C) 2008-2016 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>

=item Copyright (C) 2008-2016 by Clément Oudot, E<lt>clem.oudot@gmail.comE<gt>

=back

This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see L<http://www.gnu.org/licenses/>.

=cut
