#!/usr/bin/perl

use strict;
use warnings;
use lib './lib';

use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;

use FusionInventory::Agent;

Getopt::Long::Configure( "no_ignorecase" );

my $options = {};

GetOptions(
    $options,
    'additional-content=s',
    'backend-collect-timeout=s',
    'ca-cert-dir=s',
    'ca-cert-file=s',
    'conf-file=s',
    'config=s',
    'color',
    'daemon|d',
    'no-fork',
    'debug+',
    'delaytime=s',
    'force|f',
    'help|h',
    'html',
    'lazy',
    'list-tasks',
    'setup',
    'local|l=s',
    'logger=s',
    'logfile=s',
    'logfile-maxsize=i',
    'no-category=s',
    'no-httpd',
    'no-ssl-check',
    'no-task=s',
    'no-p2p',
    'password|p=s',
    'proxy|P=s',
    'httpd-ip=s',
    'httpd-port=s',
    'httpd-trust=s',
    'scan-homedirs',
    'server|s=s',
    'stdout',
    'tag|t=s',
    'timeout=i',
    'user|u=s',
    'version',
    'wait|w=s',
    # deprecated options
    'daemon-no-fork|D',
    'devlib',
    'no-ocsdeploy',
    'no-inventory',
    'no-wakeonlan',
    'no-snmpquery',
    'no-netdiscovery',
    'no-printer',
    'no-software',
    'rpc-trust-localhost',
    'rpc-port',
    'rpc-ip',
    'no-socket',
    'realm',
    'info|i',
) or pod2usage(-verbose => 0);

pod2usage(-verbose => 0) if $options->{help};

if ($options->{version}) {
    print $FusionInventory::Agent::VERSION_STRING . "\n";
    exit 0;
}

my %setup = (
    confdir => './etc',
    datadir => './share',
    libdir  => './lib',
    vardir  => './var',
);

if ($options->{setup}) {
    foreach my $key (keys %setup) {
        print "$key: $setup{$key}\n";
    }
    exit 0;
}

my $agent = FusionInventory::Agent->new(%setup);

if ($options->{'list-tasks'}) {
    my %tasks = $agent->getAvailableTasks();
    foreach my $task (keys %tasks) {
        print "$task (v$tasks{$task})\n";
    }
    exit 0;
}

eval {
    $agent->init(options => $options);
    $agent->run();
};

if ($EVAL_ERROR) {
    print STDERR "Execution failure:.\n";
    print STDERR $EVAL_ERROR;
    exit 1;
}

exit(0);

__END__

=head1 NAME

fusioninventory-agent - FusionInventory agent For Linux/UNIX, Windows and MacOSX

=head1 SYNOPSIS

B<fusioninventory-agent> [options] [--server server|--local directory|--sdout]

  Target definition options
    -s --server=URI     send tasks result to a server
    -l --local=DIR      write tasks results in a directory
    --stdout            write tasks result on STDOUT

  Target scheduling options
    --delaytime=DURATION        maximum initial delay before first target, in seconds (3600)
    -w --wait=DURATION          maximum delay between each target, in seconds
    --lazy                      do not contact the target before next scheduled time

  Task selection options
    --list-tasks        list available tasks and exit
    --no-task=TASK      do not run given task

  Inventory task specific options
    --no-category=CATEGORY do not list given category items
    --scan-homedirs     allow to scan use home directories (false)
    --html              save the inventory as HTML (false)
    -f --force          always send data to server (false)
    -t --tag=TAG        mark the machine with given tag
    --backend-collect-timeout   timeout for inventory modules execution (30)
    --additional-content=FILE   additional inventory content

  Package deployment task specific options
    --no-p2p            do not use peer to peer to download files (false)

  Network options:
    -P --proxy=PROXY    proxy address
    -u --user=USER      user name for server authentication
    -p --password=PWD   password for server authentication
    --ca-cert-dir=D     path to the CA certificates directory
    --ca-cert-file=F    path to the CA certificates file
    --no-ssl-check      do not check server SSL certificates (false)
    --timeout           connection timeout (180)

  Web interface options
    --no-httpd                 disable embedded web server (false)
    --httpd-ip=IP              network interface to listen to
    --httpd-port=PORT          network port to listen to (62354)
    --httpd-trust=RANGE        trust requests from range without authentication token (false)

  Logging options
    --logger=BACKEND            logger backend [Stderr|File|Syslog] (Stderr)
    --logfile=FILE              log file
    --logfile-maxsize=X         maximum size of the log file in MB (0)
    --logfacility=FACILITY      syslog facility (LOG_USER)
    --color                     use color in the console (false)

  Configuration options
    --config=BACKEND            configuration backend [file|registry|none]
    --conf-file=FILE            configuration file

  Execution mode options
    -d --daemon                 run the agent as a daemon (false)
    --no-fork                   don't fork in background (false)
    --debug                     debug mode (false)
    --version                   print the version and exit

=head1 EXAMPLES

    % fusioninventory-agent --server localhost
    # execute all available tasks required by a local server

    % fusioninventory-agent --server http://localhost/ocsinventory2
    # execute all available tasks required by a local server, using a specific
    # URI

    % fusioninventory-agent --server https://localhost/ocsinventory
    # execute all available tasks required by a local server, using a secure
    # connection

    % fusioninventory-agent --server localhost --user test --password s3cr3t
    # execute all available tasks required by a local server, using HTTP
    # authentication

    % fusioninventory-agent --local /tmp
    # execute all available tasks and write the result in /tmp directory

    % fusioninventory-agent --local /tmp --html
    # execute all available tasks and write the result in /tmp directory in
    # HTML format

=head1 DESCRIPTION

F<fusioninventory-agent> is an agent for OCS Inventory server and
FusionInventory for GLPI servers. It creates local inventory of the machines
(hardware and software) and send it to the server. It can also write it
in a local XML file.
This agent is the successor of the former linux_agent which was released with
OCS 1.01 and prior. It also replaces the Solaris/AIX/BSD unofficial agents.

Supported systems:

=over 4

=item F<Windows> (since Windows 2000)

=item F<GNU/Linux>

=item F<MacOSX>

=item F<Solaris>

=item F<FreeBSD>

=item F<NetBSD>

=item F<OpenBSD>

=item F<AIX>

=item F<HP-UX>

=item F<GNU/kFreeBSD>

=back

=head1 OCS INVENTORY PROTOCOL

FusionInventory Agent uses OCS Inventory protocol and is compatible with OCS
Inventory server. The agent uses the same protocol with the FusionInventory
For GLPI plugin.

The OCS protocol is basicly an exchange of XML file done over HTTP(S).

=head2 First, The PROLOG

The agent send a first message to give it's ID (DEVICEID). The
server send back to the agent an XML file with a list of parameter. It's the
PROLOG RESP. You can see it if you're in Debug mode.
In this PROLOG, the server send the PROLOG_FREQ. The agent will use it to
know when it need to contact the server for the next time.

The agent compute the next query date this way:

     PROLOG_FREQ/2+RANDOM(PROLOG_FREQ/2)


=head2 Module execution

The agent will launch each modules and pass the list of options found in the
PROLOG RESP as parameter. The module can send information directly to the
server (inventory, SNMP scan result, etc)

=head2 Server mode (Windows service or Unix daemon)

In server mode, the agent wait during a period between the last PROLOG and
PROLOG_FREQ. If PROLOG_FREQ is not set, it will use --delaytime value.
The default value is 3600.

=head1 OPTIONS

Most of the options are available in a I<short> form and a I<long> form.  For
example, the two lines below are all equivalent:

    % fusioninventory-agent -s localhost
    % fusioninventory-agent --server localhost

=head2 Target definition options

=over


=item B<-s>, B<--server>=I<URI>

Send results of tasks execution to given server.

If I<URI> doesn't start with http:// or https://, the agent assume the
parameter is a hostname and rewrite it as:

    % --server=http://servername/ocsinventory

In general, OCS Inventory server URL have this format:

    http://servername/ocsinventory

and FusionInventory for GLPI this one:

    http://servername/glpi/plugins/fusioninventory/front/plugin_fusioninventory.communication.php

Multiple values can be specified, using comma as a separator.

=item B<-l>, B<--local>=I<DIR>

Write the results of tasks execution to given directory.

=item B<--stdout>

Write the results of tasks execution on stdout.

=back

=head2 Target scheduling options

=over

=item B<--delaytime>=I<LIMIT>

Set an initial delay before the first target, whose value is computed randomly
between LIMIT / 2 and LIMIT seconds. This setting is ignored for server targets
after the initial contact, in favor of server-specified parameter
(PROLOG_FREQ).

=item B<-w> I<LIMIT>, B<--wait>=I<LIMIT>

Set a delay between each targets, whose value is computed randomly between 0
and LIMIT seconds.

=item B<--lazy>

Do not contact the target before next scheduled time.

This option is only available when the agent is not run as a server.

=back

=head2 Task selection options

=over

=item B<--no-task>=I<TASK>

Disable the given task

=item B<--list-tasks>

List available tasks and exit

=back

=head2 Inventory task specific options

=over

=item B<--no-category>=I<CATEGORY>

Do not list given category items in inventory.

=item B<--scan-homedirs>

Allow the agent to scan home directories for virtual machines.

=item B<--html>

Save the inventory as HTML.

This is only used for local inventories.

=item B<-f>, B<--force>

Send an inventory to the server, even if this last one doesn't ask for it.

=item B<--tag>=I<TAG>

Mark the machine with given tag.

=item B<--backend-collect-timeout>=I<TIME>

Timeout for inventory modules execution.

=back

=head2 Package deployment task specific options

=over

=item B<--no-p2p>

Do not use peer to peer to download files.

=back

=head2 Server target specific options

=over

=item B<-P>, B<--proxy>=I<PROXY>

Use I<PROXY> as HTTP proxy.

By default, the agent uses HTTP_PROXY environment variable.

=item B<-u> I<USER>, B<--user>=I<USER>

Use I<USER> for server authentication.

=item B<-p>, B<--password>=I<PASSWORD>

Use I<PASSWORD> for server authentication.

=item B<--ca-cert-dir>=I<PATH>

Path to the CA certificates directory.

=item B<--ca-cert-file>=I<FILE>

Path to the CA certificates file.

=item B<--no-ssl-check>

Do not check server SSL certificates.

Hint: you can set HTTPS_DEBUG environment variable to get SSL error messages in
the console.

=back

=head2 Web interface options

=over

=item B<--no-httpd>

Disable the embedded web server.

=item B<--httpd-ip>=I<IP>

The network interface to use for the embedded web server (all 
available interfaces).

=item B<--httpd-port>=I<PORT>

The network port to use for the embedded web server (62354).

=item B<--httpd-trust>=I<RANGE>

Trust requests from given range without authentication token (false).

For example: "192.168.0.0/24", "192.68.168.0.5" or an IP range like
"20.34.101.207 - 201.3.9.99". See L<Net::IP> documentation to get more example.

=back

=head2 Logging options

=over

=item B<--logger>=I<BACKEND>

Logger backend to use. It can be:

=over 4

=item

Stderr: log messages directly in the console.

=item

File: log messages in a file.

=item

Syslog: log messages through the local syslog server

=back

Multiple values can be specified, using comma as a separator.

=item B<--logfile>=I<FILE>

Log message in I<FILE> (implies File logger backend)

=item B<--logfile-maxsize>=I<FILE>

Max logfile size in MB, default is unlimited. When the max size is reached, the
file is truncated. This is only useful if there is no log rotation mechanism on
the system.

=item B<--logfacility>=I<FACILITY>

Syslog facility to use (default LOG_USER)

=item B<--color>

Display color on the terminal, when the Stderr backend is used.

This options is ignored on Windows.

=back

=head2 Configuration options

=over

=item B<--conf-file>=I<FILE>

Use I<FILE> as configuration file (implies file configuration backend)

=item B<--config>=I<BACKEND>

Configuration backend to use. It can be:

=over 4

=item

file: read configuration from a file (default anywhere else as Windows)

=item

registry: read configuration from the registry (default on Windows)

=item

none: don't read any configuration

=back

=back

=head2 Execution mode options

=over

=item B<-d>, B<--daemon>

Run the agent as a daemon.

=item B<--no-fork>

Don't fork in background.

This is only useful when running as a daemon.

=item B<--debug>

Turn the debug mode on.

=item B<--setup>

Print the agent setup directories and exit.

=item B<--version>

Print the version and exit.

=back

=head1 CONFIGURATION

The agent is able to use multiple configuration backends. The registry backend
is the default on Windows platform, and the file backend is the default
everywhere else. Another backend can be specified using the B<--config> option.

The I<file> backend reads configuration directives from a configuration file,
whose default location is determined at installation time as
PREFIX/etc/agent.cfg. An alternative location can also be given with
B<--conf-file> option.

The I<registry> backend reads configuration directives from the Windows
registry, with an arch-dependant location:

=over

=item * F<HKEY_LOCAL_MACHINE\SOFTWARE\FusionInventory-Agent> for 32 bits machines

=item * F<HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\FusionInventory-Agent> for 64 bits machines

=back

The I<none> backend doesn't read any configuration directive at all, allowing
to isolate the agent execution from any installed configuration.
