First version of command line and config file parsing
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Mon, 21 Feb 2011 09:49:10 +0000 (10:49 +0100)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Mon, 21 Feb 2011 10:02:14 +0000 (11:02 +0100)
src/config/configuration.cpp
src/config/configuration.h
src/config/configurationreader.cpp
src/config/configurationreader.h
src/main.cpp
uml/libpingcheck.vpp

index ce1bab4..9e1ec28 100644 (file)
@@ -1,9 +1,36 @@
+#include <iostream>
+
 #include "configuration.h"
 
-Configuration::Configuration()
+using namespace std;
+using namespace boost::program_options;
+
+Configuration::Configuration() :
+    limit_to_notify( 0 )
 {
 }
 
 Configuration::~Configuration()
 {
 }
+
+bool Configuration::read( variables_map vm )
+{
+    if ( vm.count( "limit-to-notify" ) )
+    {
+        limit_to_notify = vm[ "limit-to-notify" ].as<int> ();
+        cout << "limit-to-notify:" << limit_to_notify << endl;
+    }
+
+    return true;
+}
+
+uint32_t Configuration::get_limit_to_notify() const
+{
+    return limit_to_notify;
+}
+
+void Configuration::set_limit_to_notify( uint32_t limit_to_notify )
+{
+    this->limit_to_notify = limit_to_notify;
+}
index af72f76..984fc59 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef CONFIGURATION_H_
 #define CONFIGURATION_H_
 
+#include <stdint.h>
 #include <string>
 #include <vector>
-#include <stdint.h>
+#include <boost/program_options.hpp>
 
 #include "host.h"
 
@@ -13,14 +14,13 @@ public:
     Configuration();
     virtual ~Configuration();
 
-    virtual void read() = 0;
+    bool read( boost::program_options::variables_map vm );
+
+    uint32_t get_limit_to_notify() const;
+    void set_limit_to_notify( uint32_t limit_to_notify );
 
 private:
-    std::string call_fail_command;
-    std::string logfile;
-    bool daemonize;
-    uint32_t limit_down_hosts_to_notify;
-    std::vector<Host> hosts;
+    uint32_t limit_to_notify;
 
 };
 
index c213753..648a806 100644 (file)
+#include <iostream>
+#include <fstream>
+#include <iterator>
+
 #include "configurationreader.h"
 
-ConfigurationReader::ConfigurationReader()
+using namespace std;
+using namespace boost::program_options;
+
+ConfigurationReader::ConfigurationReader() :
+    configuration(),
+    default_config_file_name( "pingcheck.cfg" )
 {
-    // TODO how to select the source? Shall the main pass the command line?
 }
 
 ConfigurationReader::~ConfigurationReader()
 {
 }
 
-void ConfigurationReader::read()
+// A helper function to simplify the main part.
+template<class T>
+    ostream& operator<<( ostream& os, const vector<T>& v )
+    {
+        copy( v.begin(), v.end(), ostream_iterator<T> ( cout, " " ) );
+        return os;
+    }
+
+options_description ConfigurationReader::get_generic_options() const
+{
+    options_description options( "Generic options" );
+    options.add_options()
+        ( "version,v", "Print the version string and exit." )
+        ( "help,h", "Print this help and exit." )
+        ( "config-file", value<string>()->default_value( default_config_file_name ), "Name of the configuration file." );
+
+    return options;
+}
+
+options_description ConfigurationReader::get_configuration_options() const
+{
+    options_description options( "Configuration" );
+    options.add_options()
+        ( "limit-to-notify", value<int>()->default_value( 4 ), "Limit of host that have to be down in order to notify." )
+        ( "host", value< vector<string> >(), "Host address" );
+
+    return options;
+}
+
+bool ConfigurationReader::parse_command_line(
+        const int argc,
+        char* argv[],
+        variables_map& vm
+)
 {
-    //  if user provides parameters to command line
-    //      parse and use the parameters
-    //      configuration = new ConfigurationCommandLine
-    //  if user provides a file path to command line
-    //      read the given configuration file
-    //      configuration = new ConfigurationFile( file from command line )
-    //  if user doesn't provide any file or parameters
-    //      read the default file at the default location
-    //      configuration = new ConfigurationFile( default file )
-    //
-    //  configuration->read();
+    try
+    {
+        options_description generic = get_generic_options();
+        options_description config = get_configuration_options();
+
+        options_description cmdline_options;
+        cmdline_options.add( generic ).add( config );
+
+        options_description visible( "Allowed options" );
+        visible.add( generic ).add( config );
+
+        positional_options_description p;
+        p.add( "host", -1 );
+
+        store( command_line_parser( argc, argv ).
+                options( cmdline_options ).
+                positional( p ).run(), vm );
+        notify( vm );
+
+        if ( vm.count( "help" ) )
+        {
+            cout << visible << endl;
+            return false;
+        }
+
+        if ( vm.count( "version" ) )
+        {
+            cout << "pingcheck version " << VERSION_STRING << endl;
+            return false;
+        }
+    }
+    catch ( exception& e )
+    {
+        cout << e.what() << endl;
+        return false;
+    }
+
+    return true;
+}
+
+bool ConfigurationReader::parse_configuration_file( variables_map& vm )
+{
+    string config_file_name;
+    if ( vm.count( "config-file" ) )
+    {
+        config_file_name = vm[ "config-file" ].as<string> ();
+    }
+
+    return parse_configuration_file( config_file_name, vm );
+}
+
+bool ConfigurationReader::parse_configuration_file(
+        const string& config_file_name,
+        variables_map& vm
+)
+{
+    ifstream ifs( config_file_name.c_str() );
+    if ( !ifs )
+    {
+        cout << "Can not open " << config_file_name << " file\n";
+        return false;
+    }
+    else
+    {
+        options_description config = get_configuration_options();
+        options_description config_file_options;
+        config_file_options.add( config );
+
+        store( parse_config_file( ifs, config_file_options ), vm );
+        notify( vm );
+    }
+
+    return true;
+}
+
+bool ConfigurationReader::read( const int argc, char* argv[] )
+{
+    variables_map vm;
+    bool command_line_parsed = parse_command_line( argc, argv, vm );
+    bool configuration_file_parsed = parse_configuration_file( vm );
+
+    bool parser_success = command_line_parsed && configuration_file_parsed;
+    if (parser_success)
+    {
+        return configuration.read( vm );
+    }
+    else
+    {
+        return false;
+    }
 }
 
-Configuration *ConfigurationReader::getConfiguration() const
+Configuration ConfigurationReader::getConfiguration() const
 {
     return configuration;
 }
index 11a9767..dce0c01 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef CONFIGURATIONREADER_H_
 #define CONFIGURATIONREADER_H_
 
+#include <string>
+#include <boost/program_options.hpp>
+
 #include "configuration.h"
 
 class ConfigurationReader
@@ -9,11 +12,26 @@ public:
     ConfigurationReader();
     virtual ~ConfigurationReader();
 
-    void read();
-    Configuration *getConfiguration() const;
+    bool read( const int argc, char* argv[] );
+    Configuration getConfiguration() const;
+
+private:
+    boost::program_options::options_description get_generic_options() const;
+    boost::program_options::options_description get_configuration_options() const;
+    bool parse_command_line(
+            const int argc,
+            char* argv[],
+            boost::program_options::variables_map& vm
+    );
+    bool parse_configuration_file( boost::program_options::variables_map& vm );
+    bool parse_configuration_file(
+            const std::string& config_file_name,
+            boost::program_options::variables_map& vm
+    );
 
 private:
-    Configuration *configuration;
+    Configuration configuration;
+    const std::string default_config_file_name;
 };
 
 #endif /* CONFIGURATIONREADER_H_ */
index 2aff178..7613610 100644 (file)
@@ -4,28 +4,33 @@
 #include <iostream>
 #include <ostream>
 
+#include "configurationreader.h"
 #include "host.h"
 #include "boostpinger.h"
 
 int main( int argc, char* argv[] )
 {
-    if (argc != 2)
+    // sends the program command line to be parsed by the configuration reader
+    ConfigurationReader config_reader;
+    bool read_success = config_reader.read( argc, argv );
+    if ( read_success )
     {
-        std::cerr << "Usage: ping <host>" << std::endl;
-        std::cerr << "(You may need to run this program as root.)" << std::endl;
-        return 1;
+        try
+        {
+            boost::asio::io_service io_service;
+            BoostPinger p( io_service );
+//            Configuration configuration = config_reader.getConfiguration();
+//            Host host( configuration.get_hosts().at(0) ); // TODO pass Configuration object
+            Host host( argv[1] );
+            p.ping( host );
+            io_service.run();
+        }
+        catch ( std::exception& e )
+        {
+            std::cerr << "Exception: " << e.what() << std::endl;
+            return -1;
+        }
     }
 
-    try
-    {
-        boost::asio::io_service io_service;
-        BoostPinger p( io_service );
-        Host host( argv[ 1 ] );
-        p.ping( host );
-        io_service.run();
-    }
-    catch (std::exception& e)
-    {
-        std::cerr << "Exception: " << e.what() << std::endl;
-    }
+    return 0;
 }
index afb4256..3c637d9 100644 (file)
Binary files a/uml/libpingcheck.vpp and b/uml/libpingcheck.vpp differ