LCOV - code coverage report
Current view: top level - src/tools/kdb - main.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 77 120 64.2 %
Date: 2019-09-12 12:28:41 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include <iostream>
      10             : #include <memory>
      11             : #include <string>
      12             : #include <vector>
      13             : 
      14             : #include <coloredkdbio.hpp>
      15             : 
      16             : #include <cmdline.hpp>
      17             : #include <command.hpp>
      18             : #include <external.hpp>
      19             : #include <factory.hpp>
      20             : #include <signal.h>
      21             : #include <toolexcept.hpp>
      22             : 
      23             : #include <kdb.hpp>
      24             : #include <key.hpp>
      25             : 
      26             : using namespace kdb;
      27             : using namespace std;
      28             : 
      29          78 : int displayHelp (std::string app, Factory const & f)
      30             : {
      31         312 :         std::cout << "Usage: " << app << " <command> [args]\n" << std::endl;
      32             :         std::cout << app << " is a program to manage Elektra's key database.\n"
      33             :                   << "Please run a command with -H or --help as args to show a help text for\n"
      34         312 :                   << "a specific command.\n"
      35          78 :                   << std::endl;
      36         156 :         std::cout << "Known commands are:" << std::endl;
      37         156 :         std::vector<std::string> commands;
      38             :         try
      39             :         {
      40         156 :                 commands = f.getPrettyCommands ();
      41             :         }
      42           0 :         catch (kdb::KDBException const & ce)
      43             :         {
      44             :                 std::cerr << "Sorry, I have a severe problem, it seems like I am not installed correctly!\n"
      45           0 :                           << "kdbOpen() failed with the info:" << std::endl
      46           0 :                           << ce.what () << std::endl
      47           0 :                           << "Please report the issue at https://issues.libelektra.org/";
      48             :                 return 8;
      49             :         }
      50        3510 :         for (auto & command : commands)
      51             :         {
      52        6396 :                 std::cout << command << std::endl;
      53             :         }
      54             :         return 0;
      55             : }
      56             : 
      57           2 : void displayVersion ()
      58             : {
      59           4 :         kdb::KDB kdb;
      60           4 :         kdb::KeySet versions;
      61           4 :         kdb::Key k ("system/elektra/version", KEY_END);
      62           2 :         kdb.get (versions, k);
      63          12 :         kdb::Key kdb_version = versions.lookup ("system/elektra/version/constants/KDB_VERSION");
      64           2 :         if (!kdb_version)
      65             :         {
      66           0 :                 cerr << "Could not lookup KDB_VERSION key" << endl;
      67             :         }
      68             :         else
      69             :         {
      70          10 :                 cout << "KDB_VERSION: " << kdb_version.getString () << endl;
      71             :         }
      72          12 :         kdb::Key so_version = versions.lookup ("system/elektra/version/constants/SO_VERSION");
      73           2 :         if (!so_version)
      74             :         {
      75           0 :                 cerr << "Could not lookup SO_VERSION key" << endl;
      76             :         }
      77             :         else
      78             :         {
      79          10 :                 cout << "SO_VERSION: " << so_version.getString () << endl;
      80             :         }
      81           2 : }
      82             : 
      83           0 : void printSignal (int signum)
      84             : {
      85           0 :         switch (signum)
      86             :         {
      87             :         case SIGILL:
      88           0 :                 cerr << "SIGILL";
      89           0 :                 break;
      90             :         case SIGABRT:
      91           0 :                 cerr << "SIGABRT";
      92           0 :                 break;
      93             :         case SIGFPE:
      94           0 :                 cerr << "SIGFPE";
      95           0 :                 break;
      96             :         case SIGSEGV:
      97           0 :                 cerr << "SIGSEGV";
      98           0 :                 break;
      99             :         }
     100           0 : }
     101             : 
     102             : 
     103           0 : void catchSignal (int signum)
     104             : {
     105           0 :         cerr << endl << "Sorry, I crashed by the signal ";
     106           0 :         printSignal (signum);
     107           0 :         cerr << endl << "This should not have happened!" << endl;
     108           0 :         cerr << endl << "Please report the issue at https://issues.libelektra.org/" << std::endl;
     109           0 :         signal (SIGABRT, SIG_DFL);
     110           0 :         abort ();
     111             : }
     112             : 
     113       14328 : void setupSignal (int signum)
     114             : {
     115       14328 :         if (signal (signum, catchSignal) == SIG_ERR)
     116             :         {
     117           0 :                 cerr << "Sorry, I could not setup signal ";
     118           0 :                 printSignal (signum);
     119           0 :                 cerr << " because: " << strerror (errno) << std::endl;
     120           0 :                 cerr << "Please report the issue at https://issues.libelektra.org/" << std::endl;
     121             :         }
     122       14328 : }
     123             : 
     124        3582 : void setupSignals ()
     125             : {
     126        3582 :         setupSignal (SIGILL);
     127        3582 :         setupSignal (SIGABRT);
     128        3582 :         setupSignal (SIGFPE);
     129        3582 :         setupSignal (SIGSEGV);
     130        3582 : }
     131             : 
     132        3582 : int main (int argc, char ** argv)
     133             : {
     134        3582 :         setupSignals ();
     135        7164 :         Factory f;
     136             : 
     137        3582 :         if (argc < 2)
     138             :         {
     139           0 :                 return displayHelp (argv[0], f);
     140             :         }
     141             : 
     142       10746 :         string command = argv[1];
     143       10746 :         if (command == "help" || command == "-H" || command == "--help")
     144             :         {
     145           0 :                 if (argc >= 3)
     146             :                 {
     147           0 :                         runManPage (argv[2]);
     148             :                 }
     149             :                 else
     150             :                 {
     151           0 :                         runManPage ();
     152             :                 }
     153             : 
     154           0 :                 return displayHelp (argv[0], f);
     155             :         }
     156             : 
     157        7163 :         if (command == "-V" || command == "--version")
     158             :         {
     159           2 :                 displayVersion ();
     160             :                 return 0;
     161             :         }
     162             : 
     163        3580 :         bool printVerbose = false;
     164        3580 :         bool printDebug = false;
     165             :         try
     166             :         {
     167       10740 :                 std::vector<char *> origArguments (argv + 1, argv + argc);
     168        7285 :                 origArguments.push_back (0);
     169        7160 :                 CommandPtr cmd = f.get (command);
     170        7160 :                 Cmdline cl (argc, argv, cmd.get ());
     171        3580 :                 printVerbose = cl.verbose;
     172        3580 :                 printDebug = cl.debug;
     173             : 
     174        3580 :                 if (cl.help)
     175             :                 {
     176           0 :                         runManPage (command, cl.profile);
     177             :                         // does not return, but may throw
     178             :                 }
     179             : 
     180             :                 // version and invalidOpt might be implemented
     181             :                 // differently for external command
     182        3580 :                 if (dynamic_cast<ExternalCommand *> (cmd.get ()))
     183             :                 {
     184          78 :                         tryExternalCommand (&origArguments[0]);
     185             :                         // does not return, but may throw
     186             :                 }
     187             : 
     188        3502 :                 if (cl.version)
     189             :                 {
     190           0 :                         displayVersion ();
     191             :                         return 0;
     192             :                 }
     193             : 
     194        3502 :                 if (cl.invalidOpt)
     195             :                 {
     196           2 :                         cerr << cl << endl;
     197             :                         return 1;
     198             :                 }
     199             : 
     200             :                 try
     201             :                 {
     202        3500 :                         return cmd->execute (cl);
     203             :                 }
     204          30 :                 catch (std::invalid_argument const & ia)
     205             :                 {
     206          60 :                         cerr << "Sorry, I could not process the arguments: " << ia.what () << endl << endl;
     207          30 :                         cerr << cl << endl;
     208             :                         return 2;
     209             :                 }
     210             :         }
     211           4 :         catch (CommandException const & ce)
     212             :         {
     213           4 :                 std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
     214           6 :                           << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
     215           4 :                           << getErrorColor (ANSI_COLOR::RESET) << " with the info:\n"
     216          26 :                           << ce.what () << std::endl;
     217           2 :                 if (ce.errorCode () != 3 && (ce.errorCode () < 11 || ce.errorCode () > 20))
     218             :                 {
     219           0 :                         std::cerr << "Command used invalid return value (" << ce.errorCode ()
     220           0 :                                   << "), please report the issue at https://issues.libelektra.org/" << std::endl;
     221             :                         return 3;
     222             :                 }
     223           2 :                 return ce.errorCode ();
     224             :         }
     225         156 :         catch (UnknownCommand const & uc)
     226             :         {
     227         156 :                 std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
     228         234 :                           << getErrorColor (ANSI_COLOR::RESET) << " is " << getErrorColor (ANSI_COLOR::RED) << "not known"
     229        1014 :                           << getErrorColor (ANSI_COLOR::RESET) << std::endl;
     230         312 :                 displayHelp (argv[0], f);
     231             :                 return 4;
     232             :         }
     233          80 :         catch (kdb::KDBException const & ce)
     234             :         {
     235          80 :                 std::cerr << ce.whatWithArguments (printVerbose, printDebug) << std::endl;
     236             :                 return 5;
     237             :         }
     238          10 :         catch (std::exception const & ce)
     239             :         {
     240          10 :                 std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
     241          15 :                           << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
     242          70 :                           << getErrorColor (ANSI_COLOR::RESET) << " with the info:" << endl
     243          15 :                           << ce.what () << endl
     244          10 :                           << "Please report the issue at https://issues.libelektra.org/" << std::endl;
     245             :                 return 7;
     246             :         }
     247           0 :         catch (...)
     248             :         {
     249           0 :                 std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
     250           0 :                           << getErrorColor (ANSI_COLOR::RESET) << " terminated with an " << getErrorColor (ANSI_COLOR::RED)
     251           0 :                           << "unknown error" << getErrorColor (ANSI_COLOR::RESET) << endl
     252           0 :                           << "Please report the issue at https://issues.libelektra.org/" << std::endl;
     253           0 :                 displayHelp (argv[0], f);
     254             :                 return 7;
     255             :         }
     256        7164 : }

Generated by: LCOV version 1.13