|
|
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.