1#[cfg(feature = "futures")]
6use futures::future;
7use gio_sys;
8use glib;
9use glib::object::IsA;
10use glib::translate::*;
11use glib::GString;
12use glib_sys;
13use gobject_sys;
14use std;
15#[cfg(feature = "futures")]
16use std::boxed::Box as Box_;
17use std::fmt;
18use std::ptr;
19use Cancellable;
20use Error;
21use InputStream;
22use OutputStream;
23use SubprocessFlags;
24
25glib_wrapper! {
26 pub struct Subprocess(Object<gio_sys::GSubprocess, SubprocessClass>);
27
28 match fn {
29 get_type => || gio_sys::g_subprocess_get_type(),
30 }
31}
32
33impl Subprocess {
34 pub fn newv(argv: &[&std::ffi::OsStr], flags: SubprocessFlags) -> Result<Subprocess, Error> {
39 unsafe {
40 let mut error = ptr::null_mut();
41 let ret =
42 gio_sys::g_subprocess_newv(argv.to_glib_none().0, flags.to_glib(), &mut error);
43 if error.is_null() {
44 Ok(from_glib_full(ret))
45 } else {
46 Err(from_glib_full(error))
47 }
48 }
49 }
50
51 pub fn communicate<P: IsA<Cancellable>>(
52 &self,
53 stdin_buf: Option<&glib::Bytes>,
54 cancellable: Option<&P>,
55 ) -> Result<(Option<glib::Bytes>, Option<glib::Bytes>), Error> {
56 unsafe {
57 let mut stdout_buf = ptr::null_mut();
58 let mut stderr_buf = ptr::null_mut();
59 let mut error = ptr::null_mut();
60 let _ = gio_sys::g_subprocess_communicate(
61 self.to_glib_none().0,
62 stdin_buf.to_glib_none().0,
63 cancellable.map(|p| p.as_ref()).to_glib_none().0,
64 &mut stdout_buf,
65 &mut stderr_buf,
66 &mut error,
67 );
68 if error.is_null() {
69 Ok((from_glib_full(stdout_buf), from_glib_full(stderr_buf)))
70 } else {
71 Err(from_glib_full(error))
72 }
73 }
74 }
75
76 pub fn communicate_async<
77 P: IsA<Cancellable>,
78 Q: FnOnce(Result<(glib::Bytes, glib::Bytes), Error>) + Send + 'static,
79 >(
80 &self,
81 stdin_buf: Option<&glib::Bytes>,
82 cancellable: Option<&P>,
83 callback: Q,
84 ) {
85 let user_data: Box<Q> = Box::new(callback);
86 unsafe extern "C" fn communicate_async_trampoline<
87 Q: FnOnce(Result<(glib::Bytes, glib::Bytes), Error>) + Send + 'static,
88 >(
89 _source_object: *mut gobject_sys::GObject,
90 res: *mut gio_sys::GAsyncResult,
91 user_data: glib_sys::gpointer,
92 ) {
93 let mut error = ptr::null_mut();
94 let mut stdout_buf = ptr::null_mut();
95 let mut stderr_buf = ptr::null_mut();
96 let _ = gio_sys::g_subprocess_communicate_finish(
97 _source_object as *mut _,
98 res,
99 &mut stdout_buf,
100 &mut stderr_buf,
101 &mut error,
102 );
103 let result = if error.is_null() {
104 Ok((from_glib_full(stdout_buf), from_glib_full(stderr_buf)))
105 } else {
106 Err(from_glib_full(error))
107 };
108 let callback: Box<Q> = Box::from_raw(user_data as *mut _);
109 callback(result);
110 }
111 let callback = communicate_async_trampoline::<Q>;
112 unsafe {
113 gio_sys::g_subprocess_communicate_async(
114 self.to_glib_none().0,
115 stdin_buf.to_glib_none().0,
116 cancellable.map(|p| p.as_ref()).to_glib_none().0,
117 Some(callback),
118 Box::into_raw(user_data) as *mut _,
119 );
120 }
121 }
122
123 #[cfg(feature = "futures")]
124 pub fn communicate_async_future(
125 &self,
126 stdin_buf: Option<&glib::Bytes>,
127 ) -> Box_<
128 dyn future::Future<Output = Result<(glib::Bytes, glib::Bytes), Error>> + std::marker::Unpin,
129 > {
130 use fragile::Fragile;
131 use GioFuture;
132
133 let stdin_buf = stdin_buf.map(ToOwned::to_owned);
134 GioFuture::new(self, move |obj, send| {
135 let cancellable = Cancellable::new();
136 let send = Fragile::new(send);
137 obj.communicate_async(
138 stdin_buf.as_ref().map(::std::borrow::Borrow::borrow),
139 Some(&cancellable),
140 move |res| {
141 let _ = send.into_inner().send(res);
142 },
143 );
144
145 cancellable
146 })
147 }
148
149 pub fn communicate_utf8<P: IsA<Cancellable>>(
150 &self,
151 stdin_buf: Option<&str>,
152 cancellable: Option<&P>,
153 ) -> Result<(Option<GString>, Option<GString>), Error> {
154 unsafe {
155 let mut stdout_buf = ptr::null_mut();
156 let mut stderr_buf = ptr::null_mut();
157 let mut error = ptr::null_mut();
158 let _ = gio_sys::g_subprocess_communicate_utf8(
159 self.to_glib_none().0,
160 stdin_buf.to_glib_none().0,
161 cancellable.map(|p| p.as_ref()).to_glib_none().0,
162 &mut stdout_buf,
163 &mut stderr_buf,
164 &mut error,
165 );
166 if error.is_null() {
167 Ok((from_glib_full(stdout_buf), from_glib_full(stderr_buf)))
168 } else {
169 Err(from_glib_full(error))
170 }
171 }
172 }
173
174 pub fn force_exit(&self) {
175 unsafe {
176 gio_sys::g_subprocess_force_exit(self.to_glib_none().0);
177 }
178 }
179
180 pub fn get_exit_status(&self) -> i32 {
181 unsafe { gio_sys::g_subprocess_get_exit_status(self.to_glib_none().0) }
182 }
183
184 pub fn get_identifier(&self) -> Option<GString> {
185 unsafe { from_glib_none(gio_sys::g_subprocess_get_identifier(self.to_glib_none().0)) }
186 }
187
188 pub fn get_if_exited(&self) -> bool {
189 unsafe { from_glib(gio_sys::g_subprocess_get_if_exited(self.to_glib_none().0)) }
190 }
191
192 pub fn get_if_signaled(&self) -> bool {
193 unsafe { from_glib(gio_sys::g_subprocess_get_if_signaled(self.to_glib_none().0)) }
194 }
195
196 pub fn get_status(&self) -> i32 {
197 unsafe { gio_sys::g_subprocess_get_status(self.to_glib_none().0) }
198 }
199
200 pub fn get_stderr_pipe(&self) -> Option<InputStream> {
201 unsafe { from_glib_none(gio_sys::g_subprocess_get_stderr_pipe(self.to_glib_none().0)) }
202 }
203
204 pub fn get_stdin_pipe(&self) -> Option<OutputStream> {
205 unsafe { from_glib_none(gio_sys::g_subprocess_get_stdin_pipe(self.to_glib_none().0)) }
206 }
207
208 pub fn get_stdout_pipe(&self) -> Option<InputStream> {
209 unsafe { from_glib_none(gio_sys::g_subprocess_get_stdout_pipe(self.to_glib_none().0)) }
210 }
211
212 pub fn get_successful(&self) -> bool {
213 unsafe { from_glib(gio_sys::g_subprocess_get_successful(self.to_glib_none().0)) }
214 }
215
216 pub fn get_term_sig(&self) -> i32 {
217 unsafe { gio_sys::g_subprocess_get_term_sig(self.to_glib_none().0) }
218 }
219
220 #[cfg(any(not(windows), feature = "dox"))]
221 pub fn send_signal(&self, signal_num: i32) {
222 unsafe {
223 gio_sys::g_subprocess_send_signal(self.to_glib_none().0, signal_num);
224 }
225 }
226
227 pub fn wait<P: IsA<Cancellable>>(&self, cancellable: Option<&P>) -> Result<(), Error> {
228 unsafe {
229 let mut error = ptr::null_mut();
230 let _ = gio_sys::g_subprocess_wait(
231 self.to_glib_none().0,
232 cancellable.map(|p| p.as_ref()).to_glib_none().0,
233 &mut error,
234 );
235 if error.is_null() {
236 Ok(())
237 } else {
238 Err(from_glib_full(error))
239 }
240 }
241 }
242
243 pub fn wait_async<P: IsA<Cancellable>, Q: FnOnce(Result<(), Error>) + Send + 'static>(
244 &self,
245 cancellable: Option<&P>,
246 callback: Q,
247 ) {
248 let user_data: Box<Q> = Box::new(callback);
249 unsafe extern "C" fn wait_async_trampoline<
250 Q: FnOnce(Result<(), Error>) + Send + 'static,
251 >(
252 _source_object: *mut gobject_sys::GObject,
253 res: *mut gio_sys::GAsyncResult,
254 user_data: glib_sys::gpointer,
255 ) {
256 let mut error = ptr::null_mut();
257 let _ = gio_sys::g_subprocess_wait_finish(_source_object as *mut _, res, &mut error);
258 let result = if error.is_null() {
259 Ok(())
260 } else {
261 Err(from_glib_full(error))
262 };
263 let callback: Box<Q> = Box::from_raw(user_data as *mut _);
264 callback(result);
265 }
266 let callback = wait_async_trampoline::<Q>;
267 unsafe {
268 gio_sys::g_subprocess_wait_async(
269 self.to_glib_none().0,
270 cancellable.map(|p| p.as_ref()).to_glib_none().0,
271 Some(callback),
272 Box::into_raw(user_data) as *mut _,
273 );
274 }
275 }
276
277 #[cfg(feature = "futures")]
278 pub fn wait_async_future(
279 &self,
280 ) -> Box_<dyn future::Future<Output = Result<(), Error>> + std::marker::Unpin> {
281 use fragile::Fragile;
282 use GioFuture;
283
284 GioFuture::new(self, move |obj, send| {
285 let cancellable = Cancellable::new();
286 let send = Fragile::new(send);
287 obj.wait_async(Some(&cancellable), move |res| {
288 let _ = send.into_inner().send(res);
289 });
290
291 cancellable
292 })
293 }
294
295 pub fn wait_check<P: IsA<Cancellable>>(&self, cancellable: Option<&P>) -> Result<(), Error> {
296 unsafe {
297 let mut error = ptr::null_mut();
298 let _ = gio_sys::g_subprocess_wait_check(
299 self.to_glib_none().0,
300 cancellable.map(|p| p.as_ref()).to_glib_none().0,
301 &mut error,
302 );
303 if error.is_null() {
304 Ok(())
305 } else {
306 Err(from_glib_full(error))
307 }
308 }
309 }
310
311 pub fn wait_check_async<P: IsA<Cancellable>, Q: FnOnce(Result<(), Error>) + Send + 'static>(
312 &self,
313 cancellable: Option<&P>,
314 callback: Q,
315 ) {
316 let user_data: Box<Q> = Box::new(callback);
317 unsafe extern "C" fn wait_check_async_trampoline<
318 Q: FnOnce(Result<(), Error>) + Send + 'static,
319 >(
320 _source_object: *mut gobject_sys::GObject,
321 res: *mut gio_sys::GAsyncResult,
322 user_data: glib_sys::gpointer,
323 ) {
324 let mut error = ptr::null_mut();
325 let _ =
326 gio_sys::g_subprocess_wait_check_finish(_source_object as *mut _, res, &mut error);
327 let result = if error.is_null() {
328 Ok(())
329 } else {
330 Err(from_glib_full(error))
331 };
332 let callback: Box<Q> = Box::from_raw(user_data as *mut _);
333 callback(result);
334 }
335 let callback = wait_check_async_trampoline::<Q>;
336 unsafe {
337 gio_sys::g_subprocess_wait_check_async(
338 self.to_glib_none().0,
339 cancellable.map(|p| p.as_ref()).to_glib_none().0,
340 Some(callback),
341 Box::into_raw(user_data) as *mut _,
342 );
343 }
344 }
345
346 #[cfg(feature = "futures")]
347 pub fn wait_check_async_future(
348 &self,
349 ) -> Box_<dyn future::Future<Output = Result<(), Error>> + std::marker::Unpin> {
350 use fragile::Fragile;
351 use GioFuture;
352
353 GioFuture::new(self, move |obj, send| {
354 let cancellable = Cancellable::new();
355 let send = Fragile::new(send);
356 obj.wait_check_async(Some(&cancellable), move |res| {
357 let _ = send.into_inner().send(res);
358 });
359
360 cancellable
361 })
362 }
363}
364
365impl fmt::Display for Subprocess {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 write!(f, "Subprocess")
368 }
369}