LCOV - code coverage report
Current view: top level - src/tools/kdb - external.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 17 81 21.0 %
Date: 2019-09-12 12:28:41 Functions: 2 6 33.3 %

          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 "kdbconfig.h"
      10             : #include <external.hpp>
      11             : #include <kdb.h>
      12             : #include <kdb.hpp>
      13             : 
      14             : #include <iostream>
      15             : #include <string>
      16             : #include <vector>
      17             : 
      18             : #include <errno.h>
      19             : #include <limits.h>
      20             : #include <stdlib.h>
      21             : #include <string.h>
      22             : #include <sys/stat.h>
      23             : #include <sys/types.h>
      24             : #include <unistd.h>
      25             : 
      26             : #ifndef _WIN32
      27             : #include <sys/types.h>
      28             : #include <sys/wait.h>
      29             : #endif
      30             : 
      31             : const char * buildinExecPath = BUILTIN_EXEC_FOLDER;
      32             : 
      33           0 : static std::string cwd ()
      34             : {
      35           0 :         std::vector<char> current_dir;
      36           0 :         current_dir.resize (KDB_MAX_PATH_LENGTH);
      37           0 :         errno = 0;
      38           0 :         while (getcwd (&current_dir[0], current_dir.size ()) == nullptr && errno == ERANGE)
      39             :         {
      40           0 :                 current_dir.resize (current_dir.size () * 2);
      41             :         }
      42             : 
      43           0 :         if (errno != 0)
      44             :         {
      45             :                 return std::string ();
      46             :         }
      47             : 
      48           0 :         return std::string (&current_dir[0]);
      49             : }
      50             : 
      51          78 : void tryExternalCommand (char ** argv)
      52             : {
      53         156 :         std::vector<std::string> pathes;
      54             : 
      55          78 :         char * execPath = getenv ("KDB_EXEC_PATH");
      56          78 :         if (execPath)
      57             :         {
      58         390 :                 pathes.push_back (execPath);
      59             :         }
      60         390 :         pathes.push_back (buildinExecPath);
      61             : 
      62         468 :         for (auto & pathe : pathes)
      63             :         {
      64         156 :                 std::string command;
      65         156 :                 char * savedArg = nullptr;
      66             : 
      67         156 :                 if (pathe[0] != '/')
      68             :                 {
      69             :                         // no absolute path, so work with current path
      70           0 :                         const std::string currentPath = cwd ();
      71             : 
      72           0 :                         if (currentPath.empty ())
      73             :                         {
      74             :                                 std::cerr << "Could not determine "
      75             :                                           << "current path for " << pathe << " with command name: " << argv[0]
      76           0 :                                           << " because: " << strerror (errno) << std::endl;
      77           0 :                                 continue;
      78             :                         }
      79           0 :                         command += currentPath;
      80           0 :                         command += "/";
      81             :                 }
      82             : 
      83         156 :                 command += pathe;
      84         156 :                 command += "/";
      85         312 :                 command += argv[0];
      86             : 
      87             :                 struct stat buf;
      88         312 :                 if (stat (command.c_str (), &buf) == -1)
      89             :                 {
      90         156 :                         if (errno == ENOENT)
      91             :                         {
      92             :                                 // the file simply does not exist
      93             :                                 // so it seems like it is an
      94             :                                 // UnknownCommand
      95             :                                 continue;
      96             :                         }
      97             :                         else
      98             :                         {
      99           0 :                                 std::cerr << "The external command " << command << " could not be found, because: " << strerror (errno)
     100             :                                           << std::endl;
     101             :                                 continue;
     102             :                         }
     103             :                 }
     104             : 
     105           0 :                 savedArg = argv[0];
     106           0 :                 argv[0] = const_cast<char *> (command.c_str ());
     107             : 
     108           0 :                 elektraExecve (command.c_str (), argv);
     109             : 
     110           0 :                 std::cerr << "Could not execute external command " << command << " because: " << strerror (errno) << std::endl;
     111             : 
     112           0 :                 argv[0] = savedArg;
     113             :         }
     114             : 
     115         156 :         throw UnknownCommand ();
     116             : }
     117             : 
     118             : #ifndef _WIN32
     119             : extern char ** environ;
     120             : #endif
     121             : 
     122           0 : void elektraExecve (const char * filename, char * const argv[])
     123             : {
     124             : #ifdef _WIN32
     125             :         execve (filename, argv, 0);
     126             : #else
     127           0 :         execve (filename, argv, environ);
     128             : #endif
     129           0 : }
     130             : 
     131             : 
     132           0 : void runManPage (std::string command, std::string profile)
     133             : {
     134           0 :         if (command.empty ())
     135             :         {
     136             :                 command = "kdb";
     137             :         }
     138             :         else
     139             :         {
     140           0 :                 command = "kdb-" + command;
     141             :         }
     142           0 :         const char * man = "/usr/bin/man";
     143             :         using namespace kdb;
     144           0 :         Key k = nullptr;
     145           0 :         if (profile != "nokdb")
     146             :         {
     147             :                 try
     148             :                 {
     149           0 :                         KDB kdb;
     150           0 :                         KeySet conf;
     151           0 :                         std::string dirname;
     152           0 :                         for (int i = 0; i <= 2; ++i)
     153             :                         {
     154           0 :                                 switch (i)
     155             :                                 {
     156             :                                 case 0:
     157           0 :                                         dirname = "/sw/elektra/kdb/#0/" + profile + "/";
     158           0 :                                         break;
     159             :                                 case 1:
     160             :                                         dirname = "/sw/elektra/kdb/#0/%/";
     161             :                                         break;
     162             :                                 case 2:
     163           0 :                                         dirname = "/sw/kdb/" + profile + "/";
     164           0 :                                         break; // legacy
     165             :                                 }
     166           0 :                                 kdb.get (conf, dirname);
     167           0 :                                 if (!k) // first one wins, because we do not reassign
     168             :                                 {
     169           0 :                                         k = conf.lookup (dirname + "man");
     170             :                                 }
     171             :                         }
     172             :                 }
     173           0 :                 catch (kdb::KDBException const & ce)
     174             :                 {
     175             :                         std::cerr << "There is a severe problem with your installation!\n"
     176           0 :                                   << "kdbOpen() failed with the info:" << std::endl
     177           0 :                                   << ce.what () << std::endl;
     178             :                 }
     179             :         }
     180           0 :         if (k)
     181             :         {
     182           0 :                 man = k.get<std::string> ().c_str ();
     183             :         }
     184           0 :         char * const argv[3] = { const_cast<char *> (man), const_cast<char *> (command.c_str ()), nullptr };
     185             : 
     186           0 :         elektraExecve (man, argv);
     187           0 :         std::cout << "Sorry, I was not able to execute the man-page viewer: \"" << man << "\".\n";
     188           0 :         std::cout << "Try to change /sw/elektra/kdb/#0/" + profile + "/man with full path to man.\n\n";
     189             :         std::cout << "If you did not modify settings related to the man-page viewer,\nplease report the issue at "
     190           0 :                      "https://issues.libelektra.org/"
     191           0 :                   << std::endl;
     192           0 :         exit (1);
     193             : }
     194             : 
     195             : #ifndef _WIN32
     196           0 : bool runEditor (std::string editor, std::string file)
     197             : {
     198           0 :         char * const argv[3] = { const_cast<char *> (editor.c_str ()), const_cast<char *> (file.c_str ()), 0 };
     199             : 
     200           0 :         pid_t childpid = fork ();
     201           0 :         if (!childpid)
     202             :         {
     203           0 :                 elektraExecve (editor.c_str (), argv);
     204           0 :                 exit (23);
     205             :         }
     206             :         else
     207             :         {
     208             :                 int status;
     209           0 :                 waitpid (childpid, &status, 0);
     210           0 :                 if (WIFEXITED (status))
     211             :                 {
     212           0 :                         if (WEXITSTATUS (status) != 23)
     213             :                         {
     214           0 :                                 return true;
     215             :                         }
     216             :                 }
     217             :         }
     218           0 :         return false;
     219        7164 : }
     220             : #else
     221             : bool runEditor (std::string, std::string)
     222             : {
     223             :         // TODO: impl
     224             :         return false;
     225             : }
     226             : #endif

Generated by: LCOV version 1.13