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


17 Jun 2010 Doxygen 1.4.7