LCOV - code coverage report
Current view: top level - source/ipc - processInterface.cpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 91 0
Test Date: 2026-08-30 22:23:37 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /** \file processInterface.cpp
       2              :  * \author Jared R. Males (jaredmales@gmail.com)
       3              :  * \brief Process interface facilities
       4              :  * \ingroup IPC
       5              :  *
       6              :  */
       7              : 
       8              : //***********************************************************************//
       9              : // Copyright 2021 Jared R. Males (jaredmales@gmail.com)
      10              : //
      11              : // This file is part of mxlib.
      12              : //
      13              : // mxlib is free software: you can redistribute it and/or modify
      14              : // it under the terms of the GNU General Public License as published by
      15              : // the Free Software Foundation, either version 3 of the License, or
      16              : // (at your option) any later version.
      17              : //
      18              : // mxlib is distributed in the hope that it will be useful,
      19              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      20              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21              : // GNU General Public License for more details.
      22              : //
      23              : // You should have received a copy of the GNU General Public License
      24              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      25              : //***********************************************************************//
      26              : 
      27              : #include "ipc/processInterface.hpp"
      28              : #include "mxlib.hpp"
      29              : 
      30              : #include <cstring>
      31              : #include <sstream>
      32              : #include <cstdio>
      33              : #include <iostream>
      34              : 
      35              : #include <unistd.h>
      36              : #include <sys/wait.h>
      37              : 
      38              : namespace mx
      39              : {
      40              : namespace ipc
      41              : {
      42              : 
      43            0 : int command_response( const char *cmd, char *resp, size_t respsz )
      44              : {
      45              :     FILE *cmd_ptr;
      46              : 
      47            0 :     if( ( cmd_ptr = popen( cmd, "r" ) ) != NULL )
      48              :     {
      49            0 :         size_t written = 0;
      50              : 
      51              :         char buf[MX_IPC_PI_BUFSZ];
      52              : 
      53            0 :         while( fgets( buf, MX_IPC_PI_BUFSZ, cmd_ptr ) != NULL && written + 1 < respsz )
      54              :         {
      55            0 :             strcat( resp, buf );
      56            0 :             written = strlen( resp );
      57              :         }
      58            0 :         pclose( cmd_ptr );
      59              :     }
      60              :     else
      61              :     {
      62            0 :         return -1;
      63              :     }
      64              : 
      65            0 :     return 0;
      66              : }
      67              : 
      68            0 : int runCommand(
      69              :     int &retVal,        // [out] the return value of the process. Only meaningful if this returns 0.
      70              :     std::vector<std::string>
      71              :         &commandOutput, // [out] the output, line by line.  If an error, first entry contains the message.
      72              :     std::vector<std::string> &commandStderr,    // [out] the output of stderr.
      73              :     const std::vector<std::string> &commandList // [in] command to be run, with one entry per command line word
      74              : )
      75              : {
      76              :     int link[2];
      77              :     int errlink[2];
      78              : 
      79              :     pid_t pid;
      80              : 
      81            0 :     if( pipe( link ) == -1 )
      82              :     {
      83            0 :         internal::mxlib_error_report(errno2error_t(errno),  "piping stdout" );
      84            0 :         return -1;
      85              :     }
      86              : 
      87            0 :     if( pipe( errlink ) == -1 )
      88              :     {
      89            0 :         internal::mxlib_error_report(errno2error_t(errno),  "piping stderr" );
      90            0 :         return -1;
      91              :     }
      92              : 
      93            0 :     if( ( pid = fork() ) == -1 )
      94              :     {
      95            0 :         internal::mxlib_error_report(errno2error_t(errno),  "forking" );
      96            0 :         return -1;
      97              :     }
      98              : 
      99            0 :     if( pid == 0 )
     100              :     {
     101            0 :         if( dup2( link[1], STDOUT_FILENO ) < 0 )
     102              :         {
     103            0 :             internal::mxlib_error_report(errno2error_t(errno),  "dup2" );
     104            0 :             return -1;
     105              :         }
     106              : 
     107            0 :         if( close( link[0] ) < 0 )
     108              :         {
     109            0 :             internal::mxlib_error_report(errno2error_t(errno),  "close" );
     110            0 :             return -1;
     111              :         }
     112              : 
     113            0 :         if( close( link[1] ) < 0 )
     114              :         {
     115            0 :            internal::mxlib_error_report(errno2error_t(errno),  "close" );
     116            0 :             return -1;
     117              :         }
     118              : 
     119            0 :         if( dup2( errlink[1], STDERR_FILENO ) < 0 )
     120              :         {
     121            0 :            internal::mxlib_error_report(errno2error_t(errno), "dup2" );
     122            0 :             return -1;
     123              :         }
     124              : 
     125            0 :         if( close( errlink[0] ) < 0 )
     126              :         {
     127            0 :             internal::mxlib_error_report(errno2error_t(errno), "close" );
     128            0 :             return -1;
     129              :         }
     130              : 
     131            0 :         if( close( errlink[1] ) < 0 )
     132              :         {
     133            0 :             internal::mxlib_error_report(errno2error_t(errno), "close" );
     134            0 :             return -1;
     135              :         }
     136              : 
     137            0 :         std::vector<const char *> charCommandList( commandList.size() + 1, NULL );
     138              : 
     139            0 :         for( int index = 0; index < (int)commandList.size(); ++index )
     140              :         {
     141            0 :             charCommandList[index] = commandList[index].c_str();
     142              :         }
     143            0 :         execvp( charCommandList[0], const_cast<char **>( charCommandList.data() ) );
     144              : 
     145            0 :        internal::mxlib_error_report(errno2error_t(errno),  "execvp returned" );
     146              : 
     147            0 :         return -1;
     148            0 :     }
     149              :     else
     150              :     {
     151              :         char commandOutput_c[4096];
     152              : 
     153              :         int status;
     154              : 
     155            0 :         pid_t rvid = waitpid( pid, &status, 0 );
     156              : 
     157            0 :         if( rvid < 0 )
     158              :         {
     159            0 :             internal::mxlib_error_report( errno2error_t( errno ), "waitpid" );
     160            0 :             return -1;
     161              :         }
     162              : 
     163            0 :         if( WIFEXITED( status ) )
     164              :         {
     165            0 :             retVal = WEXITSTATUS( status );
     166              :         }
     167              :         else
     168              :         {
     169            0 :             internal::mxlib_error_report( error_t::procerr, "child did not exit" );
     170            0 :             return -1;
     171              :         }
     172              : 
     173            0 :         if( close( link[1] ) < 0 )
     174              :         {
     175            0 :             internal::mxlib_error_report( errno2error_t( errno ), "close" );
     176            0 :             return -1;
     177              :         }
     178              : 
     179            0 :         if( close( errlink[1] ) < 0 )
     180              :         {
     181            0 :             internal::mxlib_error_report( errno2error_t( errno ), "close" );
     182            0 :             return -1;
     183              :         }
     184              : 
     185              :         int rd;
     186            0 :         if( ( rd = read( link[0], commandOutput_c, sizeof( commandOutput_c ) ) ) < 0 )
     187              :         {
     188            0 :             internal::mxlib_error_report( errno2error_t( errno ), "read" );
     189              : 
     190            0 :             if( close( errlink[0] ) < 0 )
     191              :             {
     192            0 :                 internal::mxlib_error_report( errno2error_t( errno ), "close" );
     193              :             }
     194            0 :             if( close( link[0] ) < 0 )
     195              :             {
     196            0 :                 internal::mxlib_error_report( errno2error_t( errno ), "close" );
     197              :             }
     198              : 
     199            0 :             return -1;
     200              :         }
     201              : 
     202            0 :         if( close( link[0] ) < 0 )
     203              :         {
     204            0 :             internal::mxlib_error_report( errno2error_t( errno ), "close" );
     205            0 :             if( close( errlink[0] ) < 0 )
     206              :             {
     207            0 :                 internal::mxlib_error_report( errno2error_t( errno ), "close" );
     208              :             }
     209            0 :             return -1;
     210              :         }
     211              : 
     212            0 :         std::string line;
     213              : 
     214            0 :         commandOutput_c[rd] = '\0';
     215            0 :         std::string commandOutputString( commandOutput_c );
     216              : 
     217            0 :         std::istringstream iss( commandOutputString );
     218              : 
     219            0 :         while( getline( iss, line ) )
     220              :         {
     221            0 :             commandOutput.push_back( line );
     222              :         }
     223              : 
     224              :         //----stderr
     225            0 :         if( ( rd = read( errlink[0], commandOutput_c, sizeof( commandOutput_c ) ) ) < 0 )
     226              :         {
     227            0 :             commandStderr.push_back( std::string( "Read error on stderr: " ) + strerror( errno ) );
     228            0 :             if( close( errlink[0] ) < 0 ){internal::mxlib_error_report(errno2error_t(errno),  "close" );}
     229            0 :             return -1;
     230              :         }
     231              : 
     232            0 :         if( close( errlink[0] ) < 0 )
     233              :         {
     234            0 :             internal::mxlib_error_report(errno2error_t(errno), "close" );
     235            0 :             return -1;
     236              :         }
     237              : 
     238            0 :         commandOutput_c[rd] = '\0';
     239            0 :         commandOutputString = commandOutput_c;
     240              : 
     241            0 :         std::istringstream iss2( commandOutputString );
     242              : 
     243            0 :         while( getline( iss2, line ) )
     244              :         {
     245            0 :             commandStderr.push_back( line );
     246              :         }
     247              : 
     248            0 :         return 0;
     249            0 :     }
     250              : }
     251              : 
     252              : } // namespace ipc
     253              : } // namespace mx
        

Generated by: LCOV version 2.0-1