Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web


// =======================================
// C++Wrapper around popen
//   that recognaizes invalid command_line
// ---------------------------------------
//   Alex Vinokur
//     mailto:alexvn@go.to
//     http://go.to/alexvn
// ---------------------------------------
//   2002-10-22
// =======================================


// ==============================================
// Windows 2000 Professional
// MinGW 2.0.0.-2
// gcc/g++ version 3.2 (mingw special 20020817-1)
// ==============================================


// ================
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

#include <iostream>
#include <string>
#include <vector>

using namespace std;


// ==================
// =====================================
#define FATAL_MSG(msg) \
        cout << msg \
             << " : " \
             << (strerror (errno)) \
             << " [ " \
             << __FILE__ \
             << ", #" \
             << __LINE__ \
             << " ]" \
             << endl

#define ERROR_MSG(msg) \
        cout << msg \
             << " : " \
             << " [ " \
             << __FILE__ \
             << ", #" \
             << __LINE__ \
             << " ]" \
             << endl


// =====================================
bool popen_cplusplus_wrapper (
                const string&   command_line_i,
                vector<string>& out_result_o,
                vector<string>& err_result_o
                )
{
bool            ret_boolValue = true;

FILE*           fp_outfile;
FILE*           fp_errfile;

const int       SIZEBUF = 1234;
char            buf [SIZEBUF];

const int       FD_STDERR = 2;
int             fd_errfile;
int             fd_new_errfile;
int             fd_save_error;

string          cur_string;


  // ################################################
  // ######## Redirection : stderr to errfile #######
  // ################################################
  // ======================
  if ((fp_errfile = tmpfile ()) == NULL)
  {
    FATAL_MSG ("Cannot execute tmpfile ()");
  }
  fd_errfile = fileno (fp_errfile);
  // ======================

  // ======================
  // redirect error to file
  if ((fd_save_error = dup (FD_STDERR)) == -1)
  {
    FATAL_MSG ("Cannot execute dup");
  }
  // Now fd_save_error and 2 are descriptors of the screen
  // ======================


  // ======================
  // Close screen
  if (close (FD_STDERR) == -1)
  {
    FATAL_MSG ("Cannot close descriptor");
  }
  // Now descriptor 2 (FD_STDERR) is vacant
  // ======================

  // ======================
  if ((fd_new_errfile = dup (fd_errfile)) == -1)
  {
    FATAL_MSG ("Cannot execute dup");
  }
  // Now fd_errfile and 2 are descriptors of the errfile
  // ======================


  // ##########################
  /* This is in comment
  // ======================
  if (close (fd_errfile) == -1)
  {
    FATAL_MSG ("Cannot close descriptor");
  }
  // Now only descriptor 2 (FD_STDERR) is descriptor of the errfile
  // ======================
  */
  // ##########################


  // ################################################
  // ################# popen ########################
  // ################################################
  if ((fp_outfile = popen(command_line_i.c_str (), "r")) == NULL)
  {
    FATAL_MSG ("Files or processes cannot be created");
    ret_boolValue = false;
  }


  // ################################################
  // ### Get out stream ############################
  // ################################################
  // ================================
  out_result_o = vector<string> ();
  // ================================
  if (ret_boolValue)
  {
    while (fgets(buf, sizeof (buf), fp_outfile))
    {
      cur_string = buf;
      if (cur_string [cur_string.size () - 1] != '\n')
      {
        ERROR_MSG ("SIZEBUF too small (" << SIZEBUF << ") or missing '\\n'");
        out_result_o.push_back ("!!! Cannot get this out_line !!!");
        ret_boolValue = false;
        break;
      }

      // ------------------------------------
      assert (cur_string [cur_string.size () - 1]=='\n');
      out_result_o.push_back (cur_string.substr (0, cur_string.size () - 1));
      // ------------------------------------
    } // while (fgets(buf, sizeof (buf), fp_outfile))

    // ================================
    if (pclose(fp_outfile) == -1)
    {
      FATAL_MSG ("Cannot execute pclose");
      ret_boolValue = false;
    }
  } // if (ret_boolValue)

  // ======================
  // Close screen
  if (close (FD_STDERR) == -1)
  {
    FATAL_MSG ("Cannot close descriptor");
  }
  // Now descriptor 2 (FD_STDERR) is vacant
  // ======================

  // ======================
  if ((fd_new_errfile = dup (fd_errfile)) == -1)
  {
    FATAL_MSG ("Cannot execute dup");
  }
  // Now fd_errfile and 2 are descriptors of the errfile
  // ======================



  // ################################################
  // ### Restore : error stream to screen ###########
  // ################################################
  // ======================
  // redirect (restore) error to screen
  // Close screen
  if (close (FD_STDERR) == -1)
  {
    FATAL_MSG ("Cannot close descriptor");
  }
  // Now descriptor 2 (FD_STDERR) is vacant
  // ======================

  // ======================
  if (dup (fd_save_error) == -1)
  {
    FATAL_MSG ("Cannot execute dup");
  }
  // Now fd_save_error and 2 are descriptors of the screen
  // ======================

  // ======================
  if (close (fd_save_error) == -1)
  {
    FATAL_MSG ("Cannot close descriptor");
  }
  // Now only descriptor 2 (FD_STDERR) is descriptor of the screen

  // ======================


  // ################################################
  // ### Get error stream ###########################
  // ################################################
  // ================================
  err_result_o = vector<string> ();
  // ================================
  rewind (fp_errfile);
  while (fgets(buf, sizeof (buf), fp_errfile))
  {
    cur_string = buf;
    if (cur_string [cur_string.size () - 1] != '\n')
    {
      ERROR_MSG ("SIZEBUF too small (" << SIZEBUF << ") or missing '\\n'");
      err_result_o.push_back ("!!! Cannot get this error-line !!!");
      ret_boolValue = false;
      break;
    }

    // ------------------------------------
    assert (cur_string [cur_string.size () - 1] == '\n');
    err_result_o.push_back (cur_string.substr (0, cur_string.size() - 1));
    // ------------------------------------
  } // while (fgets(buf, sizeof (buf), fp_errfile))

  if (!err_result_o.empty ())
  {
    ret_boolValue = false;
  }

  // ===================
  return ret_boolValue;
  // ===================

} // bool popen_cplusplus_wrapper (...)


// =====================================
bool show_popen (
                const string&   command_line_i,
                vector<string>& out_result_o,
                vector<string>& err_result_o,
                const string&   msg_i = string ()
                )
{
bool    ret_bool = popen_cplusplus_wrapper (
                        command_line_i,
                        out_result_o,
                        err_result_o
                        );
unsigned int    i;
  // ====================================
  cout << endl;
  cout << "############################################" << endl;
  if (!msg_i.empty ())
  {
    cout << "### ===> " << msg_i << endl;
  }
  cout << "### Command Line <" << command_line_i << ">";
  if (!ret_bool)
  {
    cout << " : CANNOT EXECUTE";
  }
  cout << endl;
  cout << "############################################" << endl;

  // ====================================
  cout << endl;
  cout << "##########################" << endl;
  cout << "=== popen : err stream ===" << endl;
  cout << "##########################" << endl;
  cout << "==========================" << endl;

  if (err_result_o.empty ())
  {
    cout << " ---> err stream is empty" << endl;
  }
  else
  {
    for (i = 0; i < err_result_o.size (); i++)
    {
      cout << "Line#" << i << "\t  : " << "<" << err_result_o [i] << ">" << endl;
    }
  }
  cout << "==========================" << endl;


  // ====================================
  cout << endl;
  cout << "##########################" << endl;
  cout << "=== popen : out stream ===" << endl;
  cout << "##########################" << endl;
  cout << "==========================" << endl;

  if (out_result_o.empty ())
  {
    cout << " ---> out stream is empty" << endl;
  }
  else
  {
    for (i = 0; i < out_result_o.size (); i++)
    {
      cout << "Line#" << i << "\t  : " << "<" << out_result_o [i] << ">" << endl;
    }
  }
  cout << "==========================" << endl;
  cout << endl;
  cout << endl;

  // ====================================
  return ret_bool;

} //show_popen

// ==========================
int main ()
{
string          command_line;
vector<string>  out_result;
vector<string>  err_result;

  command_line = "xyz /abcd";
  show_popen (
     command_line,
     out_result,
     err_result,
     "Test#1 : Invalid command name"
     );

  command_line = "ls /abcd";
  show_popen (
     command_line,
     out_result,
     err_result,
     "Test#2 : Invalid argument value"
     );

  command_line = "ls -l C:\\WINNT";
     show_popen (
     command_line,
     out_result,
     err_result,
     "Test#3 : Valid command line"
     );

        return 0;
}