85 if (error) throw relpipe::cli::RelpipeCLIException(L"Unable to close FD: " + to_wstring(fd) + L" from PID: " + to_wstring(getpid()), relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
86 if (error) throw relpipe::cli::RelpipeCLIException(L"Unable to close FD: " + to_wstring(fd) + L" from PID: " + to_wstring(getpid()), relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
86 } |
87 } |
87 |
88 |
88 public: |
89 public: |
89 |
90 |
90 SystemProcess(std::vector<std::string> commandLine) : commandLine(commandLine) { |
91 SystemProcess(const std::vector<std::string>& commandLine, const std::vector<std::string>& environment = {}) : commandLine(commandLine), environment(environment) { |
91 nullFile = open("/dev/null", O_RDWR); |
92 nullFile = open("/dev/null", O_RDWR); |
92 } |
93 } |
93 |
94 |
94 virtual ~SystemProcess() { |
95 virtual ~SystemProcess() { |
95 close(nullFile); |
96 close(nullFile); |
97 |
98 |
98 std::string execute() { |
99 std::string execute() { |
99 |
100 |
100 std::stringstream result; |
101 std::stringstream result; |
101 |
102 |
|
103 // FIXME: different kinds of exception or return the exit code (now it enters infinite loop if the execp() fails) |
|
104 // TODO: rename (not specific to hash) |
102 int hashReaderFD; |
105 int hashReaderFD; |
103 int hashWriterFD; |
106 int hashWriterFD; |
104 createPipe(hashReaderFD, hashWriterFD); |
107 createPipe(hashReaderFD, hashWriterFD); |
105 |
108 |
106 __pid_t hashPid = fork(); |
109 __pid_t hashPid = fork(); |
107 |
110 |
108 if (hashPid < 0) { |
111 if (hashPid < 0) { |
109 throw relpipe::cli::RelpipeCLIException(L"Unable to fork the hash process.", relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
112 throw relpipe::cli::RelpipeCLIException(L"Unable to fork the hash process.", relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
110 } else if (hashPid == 0) { |
113 } else if (hashPid == 0) { |
111 // Child process |
114 // Child process |
112 closeOrThrow(hashReaderFD); |
115 closeOrThrow(hashReaderFD); |
113 redirectFD(nullFile, STDIN_FILENO); |
116 redirectFD(nullFile, STDIN_FILENO); |
114 redirectFD(nullFile, STDERR_FILENO); |
117 redirectFD(nullFile, STDERR_FILENO); |
115 redirectFD(hashWriterFD, STDOUT_FILENO); |
118 redirectFD(hashWriterFD, STDOUT_FILENO); |
|
119 for (int i = 0; i < environment.size();) { |
|
120 std::string name = environment[i++]; |
|
121 std::string value = environment[i++]; |
|
122 setenv(name.c_str(), value.c_str(), true); |
|
123 } |
116 execp(commandLine); |
124 execp(commandLine); |
117 } else { |
125 } else { |
118 // Parent process |
126 // Parent process |
119 closeOrThrow(hashWriterFD); |
127 closeOrThrow(hashWriterFD); |
120 |
128 |
121 __gnu_cxx::stdio_filebuf<char> hashReaderBuffer(hashReaderFD, std::ios::in); |
129 __gnu_cxx::stdio_filebuf<char> hashReaderBuffer(hashReaderFD, std::ios::in); |
122 std::istream hashReader(&hashReaderBuffer); |
130 std::istream hashReader(&hashReaderBuffer); |
123 |
131 |
124 for (char ch; hashReader.read(&ch, 1).good();) result.put(ch); |
132 for (char ch; hashReader.read(&ch, 1).good();) result.put(ch); |
125 |
133 |
126 int waitError; |
134 int waitError; |
127 __pid_t waitPID = wait(&waitError); |
135 __pid_t waitPID = wait(&waitError); |
128 if (waitError) throw relpipe::cli::RelpipeCLIException(L"The child process returned an error exit code.", relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
136 if (waitError) throw relpipe::cli::RelpipeCLIException(L"The child process returned an error exit code.", relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception? |
129 } |
137 } |
130 |
138 |