00001
00002
00003
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 }
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)
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
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