]> Dogcows Code - chaz/yoink/blob - src/stlplus/portability/subprocesses.hpp
testing new non-autotools build system
[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-2009
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
106 class env_vector
107 {
108 private:
109 ENVIRON_TYPE m_env;
110
111 public:
112 // create an env_vector vector from the current process
113 env_vector (void);
114 env_vector (const env_vector&);
115 ~env_vector (void);
116
117 env_vector& operator = (const env_vector&);
118
119 void clear (void);
120
121 // manipulate the env_vector by adding or removing variables
122 // adding a name that already exists replaces its value
123 void add (const std::string& name, const std::string& value);
124 bool remove (const std::string& name);
125
126 // get the value associated with a name
127 // the first uses an indexed notation (e.g. env["PATH"] )
128 // the second is a function based form (e.g. env.get("PATH"))
129 std::string operator [] (const std::string& name) const;
130 std::string get (const std::string& name) const;
131
132 // number of name=value pairs in the env_vector
133 unsigned size (void) const;
134
135 // get the name=value pairs by index (in the range 0 to size()-1)
136 std::pair<std::string,std::string> operator [] (unsigned index) const throw(std::out_of_range);
137 std::pair<std::string,std::string> get (unsigned index) const throw(std::out_of_range);
138
139 // access the env_vector as an envp type - used for passing to subprocesses
140 ENVIRON_TYPE envp (void) const;
141 };
142
143 ////////////////////////////////////////////////////////////////////////////////
144
145 #ifdef MSWINDOWS
146 #define PID_TYPE PROCESS_INFORMATION
147 #define PIPE_TYPE HANDLE
148 #else
149 #define PID_TYPE int
150 #define PIPE_TYPE int
151 #endif
152
153 ////////////////////////////////////////////////////////////////////////////////
154 // Synchronous subprocess
155
156 class subprocess
157 {
158 private:
159
160 PID_TYPE m_pid;
161 #ifdef MSWINDOWS
162 HANDLE m_job;
163 #endif
164 PIPE_TYPE m_child_in;
165 PIPE_TYPE m_child_out;
166 PIPE_TYPE m_child_err;
167 env_vector m_env;
168 int m_err;
169 int m_status;
170
171 public:
172 subprocess(void);
173 virtual ~subprocess(void);
174
175 void add_variable(const std::string& name, const std::string& value);
176 bool remove_variable(const std::string& name);
177
178 bool spawn(const std::string& path, const arg_vector& argv,
179 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
180 bool spawn(const std::string& command_line,
181 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
182
183 virtual bool callback(void);
184 bool kill(void);
185
186 int write_stdin(std::string& buffer);
187 int read_stdout(std::string& buffer);
188 int read_stderr(std::string& buffer);
189
190 void close_stdin(void);
191 void close_stdout(void);
192 void close_stderr(void);
193
194 bool error(void) const;
195 int error_number(void) const;
196 std::string error_text(void) const;
197
198 int exit_status(void) const;
199
200 private:
201 // disallow copying
202 subprocess(const subprocess&);
203 subprocess& operator=(const subprocess&);
204 };
205
206 ////////////////////////////////////////////////////////////////////////////////
207 // Preconfigured subprocess which executes a command and captures its output
208
209 class backtick_subprocess : public subprocess
210 {
211 private:
212 std::string m_text;
213 public:
214 backtick_subprocess(void);
215 virtual bool callback(void);
216 bool spawn(const std::string& path, const arg_vector& argv);
217 bool spawn(const std::string& command_line);
218 std::vector<std::string> text(void) const;
219 };
220
221 std::vector<std::string> backtick(const std::string& path, const arg_vector& argv);
222 std::vector<std::string> backtick(const std::string& command_line);
223
224 ////////////////////////////////////////////////////////////////////////////////
225 // Asynchronous subprocess
226
227 class async_subprocess
228 {
229 private:
230 PID_TYPE m_pid;
231 #ifdef MSWINDOWS
232 HANDLE m_job;
233 #endif
234 PIPE_TYPE m_child_in;
235 PIPE_TYPE m_child_out;
236 PIPE_TYPE m_child_err;
237 env_vector m_env;
238 int m_err;
239 int m_status;
240 void set_error(int);
241
242 public:
243 async_subprocess(void);
244 virtual ~async_subprocess(void);
245
246 void add_variable(const std::string& name, const std::string& value);
247 bool remove_variable(const std::string& name);
248
249 bool spawn(const std::string& path, const arg_vector& argv,
250 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
251 bool spawn(const std::string& command_line,
252 bool connect_stdin = false, bool connect_stdout = false, bool connect_stderr = false);
253
254 virtual bool callback(void);
255 bool tick(void);
256 bool kill(void);
257
258 int write_stdin(std::string& buffer);
259 int read_stdout(std::string& buffer);
260 int read_stderr(std::string& buffer);
261
262 void close_stdin(void);
263 void close_stdout(void);
264 void close_stderr(void);
265
266 bool error(void) const;
267 int error_number(void) const;
268 std::string error_text(void) const;
269
270 int exit_status(void) const;
271
272 private:
273 // disallow copying
274 async_subprocess(const async_subprocess&);
275 async_subprocess& operator=(const async_subprocess&);
276 };
277
278 ////////////////////////////////////////////////////////////////////////////////
279
280 } // end namespace stlplus
281
282 #endif
This page took 0.043624 seconds and 4 git commands to generate.