Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgProcess.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgProcess.cpp
00003     See SgProcess.h */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "SgSystem.h"
00007 #include "SgProcess.h"
00008 
00009 // Not yet implemented for Windows
00010 #ifndef WIN32
00011 
00012 #include <errno.h>
00013 #include <fstream>
00014 #include <iostream>
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <sys/types.h>
00019 #include <unistd.h>
00020 #include "SgDebug.h"
00021 #include "SgException.h"
00022 #include "SgStringUtil.h"
00023 
00024 using namespace std;
00025 
00026 //----------------------------------------------------------------------------
00027 
00028 namespace {
00029 
00030 __gnu_cxx::stdio_filebuf<char>* CreateFileBuf(int fileDescriptor,
00031                                               std::ios_base::openmode mode)
00032 {
00033 #if __GNUC__ == 3 && __GNUC_MINOR__ >= 4
00034     return new __gnu_cxx::stdio_filebuf<char>(fileDescriptor, mode,
00035                                               static_cast<size_t>(BUFSIZ));
00036 #elif __GNUC__ == 3
00037     return new __gnu_cxx::stdio_filebuf<char>(fileDescriptor, mode, true,
00038                                               static_cast<size_t>(BUFSIZ));
00039 #else
00040     return new __gnu_cxx::stdio_filebuf<char>(fileDescriptor, mode);
00041 #endif
00042 }
00043 
00044 void TerminateChild(const char* message)
00045 {
00046     SgDebug() << message << '\n';
00047     exit(1);
00048 }
00049 
00050 } // namespace
00051 
00052 //----------------------------------------------------------------------------
00053 
00054 SgProcess::SgProcess(const std::string& command)
00055 {
00056     vector<string> args = SgStringUtil::SplitArguments(command);
00057     if (args.size() == 0)
00058         throw SgException("Empty command line");
00059     int fd1[2];
00060     if (pipe(fd1) < 0)
00061         throw SgException("Pipe error");
00062     int fd2[2];
00063     if (pipe(fd2) < 0)
00064     {
00065         close(fd1[0]);
00066         close(fd1[1]);
00067         throw SgException("Pipe error");
00068     }
00069     pid_t pid;
00070     if ((pid = fork()) < 0)
00071         throw SgException("Fork error");
00072     else if (pid > 0) // Parent
00073     {
00074         close(fd1[0]);
00075         close(fd2[1]);
00076         m_bufOut.reset(CreateFileBuf(fd1[1], ios::out));
00077         m_out.reset(new ostream(m_bufOut.get()));
00078         m_bufIn.reset(CreateFileBuf(fd2[0], ios::in));
00079         m_in.reset(new istream(m_bufIn.get()));
00080         return;
00081     }
00082     else // Child
00083     {
00084         close(fd1[1]);
00085         close(fd2[0]);
00086         if (fd1[0] != STDIN_FILENO)
00087             if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO)
00088             {
00089                 close(fd1[0]);
00090                 TerminateChild("Error dup2 to stdin");
00091             }
00092         if (fd2[1] != STDOUT_FILENO)
00093             if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO)
00094             {
00095                 close(fd2[1]);
00096                 TerminateChild("Error dup2 to stdout");
00097             }
00098         char** const argv = new char*[args.size() + 1];
00099         for (size_t i = 0; i < args.size(); ++i)
00100         {
00101             argv[i] = new char[args[i].size()];
00102             strcpy(argv[i], args[i].c_str());
00103         }
00104         argv[args.size()] = 0;
00105         if (execvp(args[0].c_str(), argv) == -1)
00106             TerminateChild("Error execvp");
00107     }
00108 }
00109 
00110 SgProcess::~SgProcess()
00111 {
00112 }
00113 
00114 //----------------------------------------------------------------------------
00115 
00116 #endif // ifndef WIN32


Sun Mar 13 2011 Doxygen 1.7.1