1 //------------------------------------------------------------------------------ 2 // emProcess.h 3 // 4 // Copyright (C) 2006-2010,2014,2017-2018 Oliver Hamann. 5 // 6 // Homepage: http://eaglemode.sourceforge.net/ 7 // 8 // This program is free software: you can redistribute it and/or modify it under 9 // the terms of the GNU General Public License version 3 as published by the 10 // Free Software Foundation. 11 // 12 // This program is distributed in the hope that it will be useful, but WITHOUT 13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for 15 // more details. 16 // 17 // You should have received a copy of the GNU General Public License version 3 18 // along with this program. If not, see <http://www.gnu.org/licenses/>. 19 //------------------------------------------------------------------------------ 20 21 #ifndef emProcess_h 22 #define emProcess_h 23 24 #ifndef emStd2_h 25 #include <emCore/emStd2.h> 26 #endif 27 28 struct emProcessPrivate; 29 30 31 //============================================================================== 32 //================================= emProcess ================================== 33 //============================================================================== 34 35 class emProcess : public emUncopyable { 36 37 public: 38 39 // This class helps in creating and managing system processes. 40 41 emProcess(); 42 // Construct with no child process running. 43 44 virtual ~emProcess(); 45 // If a child process is still running, Terminate() is called. 46 47 enum StartFlags { 48 SF_SHARE_STDIN = 1<<0, 49 SF_PIPE_STDIN = 1<<1, 50 SF_SHARE_STDOUT = 1<<2, 51 SF_PIPE_STDOUT = 1<<3, 52 SF_SHARE_STDERR = 1<<4, 53 SF_PIPE_STDERR = 1<<5, 54 SF_NO_WINDOW = 1<<6 55 }; 56 57 void TryStart( 58 const emArray<emString> & args, 59 const emArray<emString> & extraEnv=emArray<emString>(), 60 const char * dirPath=NULL, 61 int flags=SF_SHARE_STDIN|SF_SHARE_STDOUT|SF_SHARE_STDERR 62 ); 63 // Start a managed child process. 64 // Arguments: 65 // args - Program arguments for the child process. The 66 // first entry is the program name itself, either 67 // as a file path, or just the name (PATH is 68 // searched then). The array must not be empty. 69 // extraEnv - The child process inherits the environment from 70 // this process, and in addition, it gets the 71 // environment variables given here. The array can 72 // have any number of environment variables, each 73 // of the form <Name>[=<value>]. If it's just the 74 // name, the variable is removed (on UNIX: only if 75 // supported by putenv), otherwise the variable is 76 // set or changed to the given value (which can be 77 // empty). 78 // dirPath - Current working directory for the child process, 79 // or NULL for inheriting the current directory 80 // from this process. 81 // flags - Combination of start flags from enum StartFlags. 82 // The flags SF_SHARE_STDIN and SF_PIPE_STDIN 83 // control the type of the standard input handle 84 // for the child process. Giving none of these 85 // flags means to have no standard input (closed 86 // handle). SF_SHARE_STDIN means to inherit the 87 // handle from this process. SF_PIPE_STDIN means to 88 // create a pipe (see methods TryWrite and 89 // CloseWrite). Setting both flags is not allowed. 90 // The other SF_*_STD* flags are for standard 91 // output and standard error analogously. 92 // SF_NO_WINDOW means to omit the console window of 93 // a console process on Windows. 94 // Throws: An error message on failure. 95 96 static void TryStartUnmanaged( 97 const emArray<emString> & args, 98 const emArray<emString> & extraEnv=emArray<emString>(), 99 const char * dirPath=NULL, 100 int flags=SF_SHARE_STDIN|SF_SHARE_STDOUT|SF_SHARE_STDERR 101 ); 102 // This function(!) is like the method TryStart, but the new 103 // process is not managed by an emProcess object. Pipelining is 104 // not possible with this. On UNIX, the new process is detached 105 // from this process, so that it does not become a child 106 // process. 107 108 int TryWrite(const char * buf, int len); 109 // Write to standard input of the child process, without 110 // blocking. The child process should have been started with 111 // SF_PIPE_STDIN. 112 // Arguments: 113 // buf - Array of bytes to be written. 114 // len - Number of bytes to be written. 115 // Returns: 116 // >0 - Number of bytes actually written. 117 // 0 - No writing possible at this moment, please try again 118 // later (or wait by calling WaitPipes). 119 // -1 - Any end of the pipe has been closed (e.g. child 120 // process exited). 121 // Throws: An error message on failure. 122 123 int TryRead(char * buf, int maxLen); 124 // Read from standard output of the child process, without 125 // blocking. The child process should have been started with 126 // SF_PIPE_STDOUT. 127 // Arguments: 128 // buf - Array for storing the bytes. 129 // len - Maximum number of bytes to be read. 130 // Returns: 131 // >0 - Number of bytes actually read. 132 // 0 - No bytes available at this moment, please try again 133 // later (or wait by calling WaitPipes). 134 // -1 - Any end of the pipe has been closed (e.g. child 135 // process exited). 136 // Throws: An error message on failure. 137 138 int TryReadErr(char * buf, int maxLen); 139 // Like TryRead, but for standard error (SF_PIPE_STDERR). 140 141 enum WaitFlags { 142 WF_WAIT_STDIN = 1<<0, 143 WF_WAIT_STDOUT = 1<<1, 144 WF_WAIT_STDERR = 1<<2 145 }; 146 void WaitPipes(int waitFlags, unsigned timeoutMS=UINT_MAX); 147 // Wait until a pipe is ready for writing and/or reading. 148 // Arguments: 149 // waitFlags - Combination of flags from enum WaitFlags. This 150 // specifies the pipes to wait for. The method 151 // returns when at least one of these pipes is 152 // ready. 153 // timeoutMS - After this time-out in milliseconds, the 154 // method returns even if no pipe is ready. 155 // UINT_MAX means infinite. 156 157 void CloseWriting(); 158 void CloseReading(); 159 void CloseReadingErr(); 160 // Close this end of a pipe. 161 162 void SendTerminationSignal(); 163 // Send a termination request to the child process. On UNIX, the 164 // signal SIGTERM is sent to the child process. On Windows, the 165 // message WM_QUIT is sent to the primary thread of the child 166 // process. Note that this does not work with a normal Windows 167 // console program, except the latter is explicitly programmed 168 // for receiving WM_QUIT. 169 170 void SendKillSignal(); 171 // Hardly kill the child process. Usually this should never be 172 // called. On UNIX, the signal SIGKILL is sent to the child 173 // process. On Windows, the SDK function TerminateProcess is 174 // called. 175 176 bool WaitForTermination(unsigned timeoutMS=UINT_MAX); 177 // Wait for the child process to terminate. 178 // Arguments: 179 // timeoutMS - Time-out in milliseconds. UINT_MAX means 180 // infinite. 181 // Returns: 182 // true - Child process terminated (or never started). 183 // false - Timed out. 184 185 bool IsRunning(); 186 // true if a child process has been started and not yet 187 // terminated. 188 189 void Terminate(unsigned fatalTimeoutMS=20000); 190 // Like SendTerminationSignal plus WaitForTermination. But if 191 // the process does not terminate within the given time-out in 192 // milliseconds, emFatalError is called (because it is assumed 193 // to have a programming error somewhere). The time-out should 194 // be quite large, for the case of a badly overloaded system. 195 196 int GetExitStatus() const; 197 // Get the exit status of a terminated child process. 198 199 private: 200 201 emProcessPrivate * P; 202 203 }; 204 205 206 #endif 207