]> Dogcows Code - chaz/yoink/blob - src/stlplus/portability/subprocesses.hpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / subprocesses.hpp
1 #ifndef STLPLUS_SUBPROCESSES
2 #define STLPLUS_SUBPROCESSES
3 ////////////////////////////////////////////////////////////////////////////////
4
5 // Author: Andy Rushton
6 // Copyright: (c) Southampton University 1999-2004
7 // (c) Andy Rushton 2004 onwards
8 // License: BSD License, see ../docs/license.html
9
10 // Platform-independent wrapper around the very platform-specific handling of
11 // subprocesses. Uses the C++ convention that all resources must be contained in
12 // an object so that when a subprocess object goes out of scope the subprocess
13 // itself gets closed down.
14
15 ////////////////////////////////////////////////////////////////////////////////
16 #include "portability_fixes.hpp"
17 #ifdef MSWINDOWS
18 #include <windows.h>
19 #endif
20 #include <stdexcept>
21 #include <vector>
22 #include <string>
23 #include <map> // for std::pair - why is this not defined separately?
24
25 ////////////////////////////////////////////////////////////////////////////////
26
27 namespace stlplus
28 {
29
30 ////////////////////////////////////////////////////////////////////////////////
31 // Argument vector class
32 // allows manipulation of argv-like vectors
33 // includes splitting of command lines into argvectors as per the shell
34 // (removing quotes) and the reverse conversion (adding quotes where necessary)
35
36 class arg_vector
37 {
38 private:
39 char** m_argv;
40
41 public:
42 // create an empty vector
43 arg_vector (void);
44
45 // copy constructor (yes it copies)
46 arg_vector (const arg_vector&);
47
48 // construct from an argv
49 arg_vector (char**);
50
51 // construct from a command-line string
52 // includes de-quoting of values
53 arg_vector (const std::string&);
54 arg_vector (const char*);
55
56 ~arg_vector (void);
57
58 // assignment operators are compatible with the constructors
59 arg_vector& operator = (const arg_vector&);
60 arg_vector& operator = (char**);
61 arg_vector& operator = (const std::string&);
62 arg_vector& operator = (const char*);
63
64 // add an argument to the vector
65 arg_vector& operator += (const std::string&);
66 arg_vector& operator -= (const std::string&);
67
68 // insert/clear an argument at a certain index
69 // adding is like the other array classes - it moves the current item at index
70 // up one (and all subsequent values) to make room
71 void insert (unsigned index, const std::string&) throw(std::out_of_range);
72 void clear (unsigned index) throw(std::out_of_range);
73 void clear (void);
74
75 // number of values in the vector (including argv[0], the command itself
76 unsigned size (void) const;
77
78 // type conversion to the argv type
79 operator char** (void) const;
80 // function-based version of the above for people who don't like type conversions
81 char** argv (void) const;
82
83 // access individual values in the vector
84 char* operator [] (unsigned index) const throw(std::out_of_range);
85
86 // special-case access of the command name (e.g. to do path lookup on the command)
87 char* argv0 (void) const throw(std::out_of_range);
88
89 // get the command-line string represented by this vector
90 // includes escaping of special characters and quoting
91 std::string image (void) const;
92 };
93
94 ////////////////////////////////////////////////////////////////////////////////
95 // Environment class
96 // Allows manipulation of an environment vector
97 // This is typically used to create an environment to be used by a subprocess
98 // It does NOT modify the environment of the current process
99
100 #ifdef MSWINDOWS
101 #define ENVIRON_TYPE char*
102 #else
103 #define ENVIRON_TYPE char**
104 #endif
105 class subprocess;
106 class async_subprocess;
107
108 class env_vector
109 {
110 private:
111 ENVIRON_TYPE m_env;
112 friend class subprocess;
113 friend class async_subprocess;
114 // access the env_vector as an envp type - used for passing to subprocesses
115 ENVIRON_TYPE envp (void) const;
116
117 public:
118 // create an env_vector vector from the current process
119 env_vector (void);
120 env_vector (const env_vector&);
121 ~env_vector (void);
122
123 env_vector& operator = (const env_vector&);
124
125 // manipulate the env_vector by adding or removing variables
126 // adding a name that already exists replaces its value
127 void add (const std::string& name, const std::string& value);
128 bool remove (const std::string& name);
129 void clear (void);
130
131 // get the value associated with a name
132 // the first uses an indexed notation (e.g. env["PATH"] )
133 // the second is a function based form (e.g. env.get("PATH"))
134 bool present(const std::string& name) const;
135 std::string operator [] (const std::string& name) const;
136 std::string get (const std::string& name) const;
137
138 // number of name=value pairs in the env_vector
139 unsigned size (void) const;
140
141 // get the name=value pairs by index (in the range 0 to size()-1)
142 std::pair<std::string,std::string> operator [] (unsigned index) const throw(std::out_of_range);
143 std::pair<std::string,std::string> get (unsigned index) const throw(std::out_of_range);
144 };
145
146 ////////////////////////////////////////////////////////////////////////////////
147
148 #ifdef MSWINDOWS
149 #define PID_TYPE PROCESS_INFORMATION
150 #define PIPE_TYPE HANDLE
151 #else
152 #define PID_TYPE int
153 #define PIPE_TYPE int
154 #endif
155
156 ////////////////////////////////////////////////////////////////////////////////
157 // Synchronous subprocess
158
159 class subprocess
160 {
161 protected:
162
163 PID_TYPE m_pid;
164 #ifdef MSWINDOWS
165 HANDLE m_job;
166 #endif
167 PIPE_TYPE m_child_in;
168 PIPE_TYPE m_child_out;
169 PIPE_TYPE m_child_err;
170 env_vector m_env;
171 int m_err;
172 int m_status;
173 void set_error(int);
174
175 public:
176 subprocess(void);
177 virtual ~subprocess(void);
178
179 void add_variable(const std::string& name, const std::string& value);
180 bool remove_variable(const std::string& name);
181 const env_vector& get_variables(void) const;
182
183 bool spawn(const std::string& path, const arg_vector& argv,
184 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
185 bool spawn(const std::string& command_line,
186 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
187
188 virtual bool callback(void);
189 bool kill(void);
190
191 int write_stdin(std::string& buffer);
192 int read_stdout(std::string& buffer);
193 int read_stderr(std::string& buffer);
194
195 void close_stdin(void);
196 void close_stdout(void);
197 void close_stderr(void);
198
199 bool error(void) const;
200 int error_number(void) const;
201 std::string error_text(void) const;
202
203 int exit_status(void) const;
204
205 private:
206 // disallow copying
207 subprocess(const subprocess&);
208 subprocess& operator=(const subprocess&);
209 };
210
211 ////////////////////////////////////////////////////////////////////////////////
212 // Preconfigured subprocess which executes a command and captures its output
213
214 class backtick_subprocess : public subprocess
215 {
216 protected:
217 std::string m_text;
218 public:
219 backtick_subprocess(void);
220 virtual bool callback(void);
221 bool spawn(const std::string& path, const arg_vector& argv);
222 bool spawn(const std::string& command_line);
223 std::vector<std::string> text(void) const;
224 };
225
226 std::vector<std::string> backtick(const std::string& path, const arg_vector& argv);
227 std::vector<std::string> backtick(const std::string& command_line);
228
229 ////////////////////////////////////////////////////////////////////////////////
230 // Asynchronous subprocess
231
232 class async_subprocess
233 {
234 protected:
235 PID_TYPE m_pid;
236 #ifdef MSWINDOWS
237 HANDLE m_job;
238 #endif
239 PIPE_TYPE m_child_in;
240 PIPE_TYPE m_child_out;
241 PIPE_TYPE m_child_err;
242 env_vector m_env;
243 int m_err;
244 int m_status;
245 void set_error(int);
246
247 public:
248 async_subprocess(void);
249 virtual ~async_subprocess(void);
250
251 void add_variable(const std::string& name, const std::string& value);
252 bool remove_variable(const std::string& name);
253 const env_vector& get_variables(void) const;
254
255 bool spawn(const std::string& path, const arg_vector& argv,
256 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
257 bool spawn(const std::string& command_line,
258 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
259
260 virtual bool callback(void);
261 bool tick(void);
262 bool kill(void);
263
264 int write_stdin(std::string& buffer);
265 int read_stdout(std::string& buffer);
266 int read_stderr(std::string& buffer);
267
268 void close_stdin(void);
269 void close_stdout(void);
270 void close_stderr(void);
271
272 bool error(void) const;
273 int error_number(void) const;
274 std::string error_text(void) const;
275
276 int exit_status(void) const;
277
278 private:
279 // disallow copying
280 async_subprocess(const async_subprocess&);
281 async_subprocess& operator=(const async_subprocess&);
282 };
283
284 ////////////////////////////////////////////////////////////////////////////////
285
286 } // end namespace stlplus
287
288 #endif
This page took 0.048983 seconds and 4 git commands to generate.