|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
7: */
8:
9: #include <fcntl.h>
10: #include <unistd.h>
11: #include <sys/stat.h>
12: #include <sys/wait.h>
13: #include "Process.h"
14: #include "Platform/Exception.h"
15: #include "Platform/FileStream.h"
16: #include "Platform/ForEach.h"
17: #include "Platform/MemoryStream.h"
18: #include "Platform/SystemException.h"
19: #include "Platform/StringConverter.h"
20: #include "Platform/Unix/Pipe.h"
21: #include "Platform/Unix/Poller.h"
22:
23: namespace TrueCrypt
24: {
25: string Process::Execute (const string &processName, const list <string> &arguments, int timeOut, ProcessExecFunctor *execFunctor)
26: {
27: char *args[32];
28: if (array_capacity (args) <= arguments.size())
29: throw ParameterTooLarge (SRC_POS);
30:
31: #if 0
32: stringstream dbg;
33: dbg << "exec " << processName;
34: foreach (const string &at, arguments)
35: dbg << " " << at;
36: trace_msg (dbg.str());
37: #endif
38:
39: Pipe outPipe, errPipe, exceptionPipe;
40:
41: int forkedPid = fork();
42: throw_sys_if (forkedPid == -1);
43:
44: if (forkedPid == 0)
45: {
46: try
47: {
48: try
49: {
50: int argIndex = 0;
51: if (!execFunctor)
52: args[argIndex++] = const_cast <char*> (processName.c_str());
53:
54: foreach (const string &arg, arguments)
55: {
56: args[argIndex++] = const_cast <char*> (arg.c_str());
57: }
58: args[argIndex] = nullptr;
59:
60: int f = open ("/dev/null", 0);
61: throw_sys_sub_if (f == -1, "/dev/null");
62: throw_sys_if (dup2 (f, STDIN_FILENO) == -1);
63: throw_sys_if (dup2 (outPipe.GetWriteFD(), STDOUT_FILENO) == -1);
64: throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1);
65: exceptionPipe.GetWriteFD();
66:
67: if (execFunctor)
68: {
69: (*execFunctor)(argIndex, args);
70: }
71: else
72: {
73: execvp (args[0], args);
74: throw SystemException (SRC_POS, args[0]);
75: }
76: }
77: catch (Exception &)
78: {
79: throw;
80: }
81: catch (exception &e)
82: {
83: throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e));
84: }
85: catch (...)
86: {
87: throw UnknownException (SRC_POS);
88: }
89: }
90: catch (Exception &e)
91: {
92: try
93: {
94: shared_ptr <Stream> outputStream (new FileStream (exceptionPipe.GetWriteFD()));
95: e.Serialize (outputStream);
96: }
97: catch (...) { }
98: }
99:
100: _exit (1);
101: }
102:
103: throw_sys_if (fcntl (outPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
104: throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
105: throw_sys_if (fcntl (exceptionPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
106:
107: vector <char> buffer (4096), stdOutput (4096), errOutput (4096), exOutput (4096);
108: buffer.clear ();
109: stdOutput.clear ();
110: errOutput.clear ();
111: exOutput.clear ();
112:
113: Poller poller (outPipe.GetReadFD(), errPipe.GetReadFD(), exceptionPipe.GetReadFD());
114: int status, waitRes;
115:
116: int timeTaken = 0;
117: do
118: {
119: const int pollTimeout = 200;
120: try
121: {
122: ssize_t bytesRead = 0;
123: foreach (int fd, poller.WaitForData (pollTimeout))
124: {
125: bytesRead = read (fd, &buffer[0], buffer.capacity());
126: if (bytesRead > 0)
127: {
128: if (fd == outPipe.GetReadFD())
129: stdOutput.insert (stdOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
130: else if (fd == errPipe.GetReadFD())
131: errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
132: else if (fd == exceptionPipe.GetReadFD())
133: exOutput.insert (exOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
134: }
135: }
136:
137: if (bytesRead == 0)
138: {
139: waitRes = waitpid (forkedPid, &status, 0);
140: break;
141: }
142: }
143: catch (TimeOut&)
144: {
145: timeTaken += pollTimeout;
146: if (timeOut >= 0 && timeTaken >= timeOut)
147: throw;
148: }
149: } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0);
150: throw_sys_if (waitRes == -1);
151:
152: stdOutput.push_back (0);
153: errOutput.push_back (0);
154:
155: if (!exOutput.empty())
156: {
157: auto_ptr <Serializable> deserializedObject;
158: Exception *deserializedException = nullptr;
159:
160: try
161: {
162: shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size())));
163: deserializedObject.reset (Serializable::DeserializeNew (stream));
164: deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
165: }
166: catch (...) { }
167:
168: if (deserializedException)
169: deserializedException->Throw();
170: }
171:
172: int exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1);
173: if (exitCode != 0)
174: {
175: string strErrOutput;
176: strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end());
177: throw ExecutedProcessFailed (SRC_POS, processName, exitCode, strErrOutput);
178: }
179:
180: string strOutput;
181: strOutput.insert (strOutput.begin(), stdOutput.begin(), stdOutput.end());
182: return strOutput;
183: }
184: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.