Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #include "SgSystem.h"
00007 #include "SgProcess.h"
00008
00009
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 }
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)
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
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