1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 #[cfg(not(windows))]
4 use std::boxed::Box as Box_;
5 #[cfg(not(windows))]
6 use std::mem;
7 #[cfg(not(windows))]
8 #[cfg(any(feature = "v2_58", feature = "dox"))]
9 use std::os::unix::io::AsRawFd;
10 #[cfg(not(windows))]
11 use std::os::unix::io::{FromRawFd, RawFd};
12 // #[cfg(windows)]
13 // #[cfg(any(feature = "v2_58", feature = "dox"))]
14 // use std::os::windows::io::AsRawHandle;
15 use crate::translate::*;
16 #[cfg(not(windows))]
17 use crate::Error;
18 use crate::GString;
19 #[cfg(not(windows))]
20 use crate::Pid;
21 #[cfg(not(windows))]
22 use crate::SpawnFlags;
23 use std::ptr;
24 
25 #[cfg(any(feature = "v2_58", feature = "dox"))]
26 #[cfg(not(windows))]
27 #[cfg_attr(feature = "dox", doc(cfg(all(feature = "v2_58", not(windows)))))]
28 #[allow(clippy::too_many_arguments)]
29 #[doc(alias = "g_spawn_async_with_fds")]
spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V: AsRawFd>( working_directory: P, argv: &[&str], envp: &[&str], flags: SpawnFlags, child_setup: Option<Box_<dyn FnOnce() + 'static>>, stdin_fd: T, stdout_fd: U, stderr_fd: V, ) -> Result<Pid, Error>30 pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V: AsRawFd>(
31     working_directory: P,
32     argv: &[&str],
33     envp: &[&str],
34     flags: SpawnFlags,
35     child_setup: Option<Box_<dyn FnOnce() + 'static>>,
36     stdin_fd: T,
37     stdout_fd: U,
38     stderr_fd: V,
39 ) -> Result<Pid, Error> {
40     let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
41     unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>(user_data: ffi::gpointer) {
42         let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
43             Box_::from_raw(user_data as *mut _);
44         let callback = (*callback).expect("cannot get closure...");
45         callback()
46     }
47     let child_setup = if child_setup_data.is_some() {
48         Some(child_setup_func::<P> as _)
49     } else {
50         None
51     };
52     let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
53     unsafe {
54         let mut child_pid = mem::MaybeUninit::uninit();
55         let mut error = ptr::null_mut();
56         let _ = ffi::g_spawn_async_with_fds(
57             working_directory.as_ref().to_glib_none().0,
58             argv.to_glib_none().0,
59             envp.to_glib_none().0,
60             flags.into_glib(),
61             child_setup,
62             Box_::into_raw(super_callback0) as *mut _,
63             child_pid.as_mut_ptr(),
64             stdin_fd.as_raw_fd(),
65             stdout_fd.as_raw_fd(),
66             stderr_fd.as_raw_fd(),
67             &mut error,
68         );
69         let child_pid = from_glib(child_pid.assume_init());
70         if error.is_null() {
71             Ok(child_pid)
72         } else {
73             Err(from_glib_full(error))
74         }
75     }
76 }
77 
78 // #[cfg(any(feature = "v2_58", feature = "dox"))]
79 // #[cfg(windows)]
80 // pub fn spawn_async_with_fds<
81 //     P: AsRef<std::path::Path>,
82 //     T: AsRawHandle,
83 //     U: AsRawHandle,
84 //     V: AsRawHandle,
85 // >(
86 //     working_directory: P,
87 //     argv: &[&str],
88 //     envp: &[&str],
89 //     flags: SpawnFlags,
90 //     child_setup: Option<Box_<dyn FnOnce() + 'static>>,
91 //     stdin_fd: T,
92 //     stdout_fd: U,
93 //     stderr_fd: V,
94 // ) -> Result<Pid, Error> {
95 //     let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
96 //     unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>(
97 //         user_data: ffi::gpointer,
98 //     ) {
99 //         let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
100 //             Box_::from_raw(user_data as *mut _);
101 //         let callback = (*callback).expect("cannot get closure...");
102 //         callback()
103 //     }
104 //     let child_setup = if child_setup_data.is_some() {
105 //         Some(child_setup_func::<P> as _)
106 //     } else {
107 //         None
108 //     };
109 //     let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
110 //     unsafe {
111 //         let mut child_pid = mem::MaybeUninit::uninit();
112 //         let mut error = ptr::null_mut();
113 //         let _ = ffi::g_spawn_async_with_fds(
114 //             working_directory.as_ref().to_glib_none().0,
115 //             argv.to_glib_none().0,
116 //             envp.to_glib_none().0,
117 //             flags.into_glib(),
118 //             child_setup,
119 //             Box_::into_raw(super_callback0) as *mut _,
120 //             child_pid.as_mut_ptr(),
121 //             stdin_fd.as_raw_handle() as usize as _,
122 //             stdout_fd.as_raw_handle() as usize as _,
123 //             stderr_fd.as_raw_handle() as usize as _,
124 //             &mut error,
125 //         );
126 //         let child_pid = from_glib(child_pid.assume_init());
127 //         if error.is_null() {
128 //             Ok(child_pid)
129 //         } else {
130 //             Err(from_glib_full(error))
131 //         }
132 //     }
133 // }
134 
135 #[cfg(not(windows))]
136 #[cfg_attr(feature = "dox", doc(cfg(not(windows))))]
137 #[doc(alias = "g_spawn_async_with_pipes")]
spawn_async_with_pipes< P: AsRef<std::path::Path>, T: FromRawFd, U: FromRawFd, V: FromRawFd, >( working_directory: P, argv: &[&std::path::Path], envp: &[&std::path::Path], flags: SpawnFlags, child_setup: Option<Box_<dyn FnOnce() + 'static>>, ) -> Result<(Pid, T, U, V), Error>138 pub fn spawn_async_with_pipes<
139     P: AsRef<std::path::Path>,
140     T: FromRawFd,
141     U: FromRawFd,
142     V: FromRawFd,
143 >(
144     working_directory: P,
145     argv: &[&std::path::Path],
146     envp: &[&std::path::Path],
147     flags: SpawnFlags,
148     child_setup: Option<Box_<dyn FnOnce() + 'static>>,
149 ) -> Result<(Pid, T, U, V), Error> {
150     let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
151     unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>(user_data: ffi::gpointer) {
152         let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
153             Box_::from_raw(user_data as *mut _);
154         let callback = (*callback).expect("cannot get closure...");
155         callback()
156     }
157     let child_setup = if child_setup_data.is_some() {
158         Some(child_setup_func::<P> as _)
159     } else {
160         None
161     };
162     let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
163     unsafe {
164         let mut child_pid = mem::MaybeUninit::uninit();
165         let mut standard_input = mem::MaybeUninit::uninit();
166         let mut standard_output = mem::MaybeUninit::uninit();
167         let mut standard_error = mem::MaybeUninit::uninit();
168         let mut error = ptr::null_mut();
169         let _ = ffi::g_spawn_async_with_pipes(
170             working_directory.as_ref().to_glib_none().0,
171             argv.to_glib_none().0,
172             envp.to_glib_none().0,
173             flags.into_glib(),
174             child_setup,
175             Box_::into_raw(super_callback0) as *mut _,
176             child_pid.as_mut_ptr(),
177             standard_input.as_mut_ptr(),
178             standard_output.as_mut_ptr(),
179             standard_error.as_mut_ptr(),
180             &mut error,
181         );
182         let child_pid = from_glib(child_pid.assume_init());
183         let standard_input = standard_input.assume_init();
184         let standard_output = standard_output.assume_init();
185         let standard_error = standard_error.assume_init();
186         if error.is_null() {
187             #[cfg(not(windows))]
188             {
189                 Ok((
190                     child_pid,
191                     FromRawFd::from_raw_fd(standard_input),
192                     FromRawFd::from_raw_fd(standard_output),
193                     FromRawFd::from_raw_fd(standard_error),
194                 ))
195             }
196         // #[cfg(windows)]
197         // {
198         //     use std::os::windows::io::{FromRawHandle, RawHandle};
199         //     Ok((
200         //         child_pid,
201         //         File::from_raw_handle(standard_input as usize as RawHandle),
202         //         File::from_raw_handle(standard_output as usize as RawHandle),
203         //         File::from_raw_handle(standard_error as usize as RawHandle),
204         //     ))
205         // }
206         } else {
207             Err(from_glib_full(error))
208         }
209     }
210 }
211 
212 /// Obtain the character set for the current locale.
213 ///
214 /// This returns whether the locale's encoding is UTF-8, and the current
215 /// charset if available.
216 #[doc(alias = "g_get_charset")]
217 #[doc(alias = "get_charset")]
charset() -> (bool, Option<GString>)218 pub fn charset() -> (bool, Option<GString>) {
219     unsafe {
220         let mut out_charset = ptr::null();
221         let is_utf8 = from_glib(ffi::g_get_charset(&mut out_charset));
222         let charset = from_glib_none(out_charset);
223         (is_utf8, charset)
224     }
225 }
226 
227 #[cfg(unix)]
228 #[doc(alias = "g_unix_open_pipe")]
unix_open_pipe(flags: i32) -> Result<(RawFd, RawFd), Error>229 pub fn unix_open_pipe(flags: i32) -> Result<(RawFd, RawFd), Error> {
230     unsafe {
231         let mut fds = [0, 2];
232         let mut error = ptr::null_mut();
233         let _ = ffi::g_unix_open_pipe(fds.as_mut_ptr(), flags, &mut error);
234         if error.is_null() {
235             Ok((
236                 FromRawFd::from_raw_fd(fds[0]),
237                 FromRawFd::from_raw_fd(fds[1]),
238             ))
239         } else {
240             Err(from_glib_full(error))
241         }
242     }
243 }
244