1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// DO NOT EDIT

use crate::Subprocess;
use crate::SubprocessFlags;
use glib::translate::*;
#[cfg(any(unix, feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(unix)))]
use std::boxed::Box as Box_;
use std::fmt;
use std::ptr;

glib::wrapper! {
    /// This class contains a set of options for launching child processes,
    /// such as where its standard input and output will be directed, the
    /// argument list, the environment, and more.
    ///
    /// While the [`Subprocess`][crate::Subprocess] class has high level functions covering
    /// popular cases, use of this class allows access to more advanced
    /// options. It can also be used to launch multiple subprocesses with
    /// a similar configuration.
    ///
    /// # Implements
    ///
    /// [`trait@glib::ObjectExt`]
    #[doc(alias = "GSubprocessLauncher")]
    pub struct SubprocessLauncher(Object<ffi::GSubprocessLauncher>);

    match fn {
        type_ => || ffi::g_subprocess_launcher_get_type(),
    }
}

impl SubprocessLauncher {
    /// Creates a new [`SubprocessLauncher`][crate::SubprocessLauncher].
    ///
    /// The launcher is created with the default options. A copy of the
    /// environment of the calling process is made at the time of this call
    /// and will be used as the environment that the process is launched in.
    /// ## `flags`
    /// [`SubprocessFlags`][crate::SubprocessFlags]
    #[doc(alias = "g_subprocess_launcher_new")]
    pub fn new(flags: SubprocessFlags) -> SubprocessLauncher {
        unsafe { from_glib_full(ffi::g_subprocess_launcher_new(flags.into_glib())) }
    }

    /// Closes all the file descriptors previously passed to the object with
    /// [`take_fd()`][Self::take_fd()], [`take_stderr_fd()`][Self::take_stderr_fd()], etc.
    ///
    /// After calling this method, any subsequent calls to `g_subprocess_launcher_spawn()` or [`spawn()`][Self::spawn()] will
    /// return [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed]. This method is idempotent if
    /// called more than once.
    ///
    /// This function is called automatically when the [`SubprocessLauncher`][crate::SubprocessLauncher]
    /// is disposed, but is provided separately so that garbage collected
    /// language bindings can call it earlier to guarantee when FDs are closed.
    #[cfg(any(unix, feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(unix)))]
    #[cfg(any(feature = "v2_68", feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(feature = "v2_68")))]
    #[doc(alias = "g_subprocess_launcher_close")]
    pub fn close(&self) {
        unsafe {
            ffi::g_subprocess_launcher_close(self.to_glib_none().0);
        }
    }

    /// Returns the value of the environment variable `variable` in the
    /// environment of processes launched from this launcher.
    ///
    /// On UNIX, the returned string can be an arbitrary byte string.
    /// On Windows, it will be UTF-8.
    /// ## `variable`
    /// the environment variable to get
    ///
    /// # Returns
    ///
    /// the value of the environment variable,
    ///  [`None`] if unset
    #[doc(alias = "g_subprocess_launcher_getenv")]
    pub fn getenv(&self, variable: impl AsRef<std::path::Path>) -> Option<std::path::PathBuf> {
        unsafe {
            from_glib_none(ffi::g_subprocess_launcher_getenv(
                self.to_glib_none().0,
                variable.as_ref().to_glib_none().0,
            ))
        }
    }

    /// Sets up a child setup function.
    ///
    /// The child setup function will be called after `fork()` but before
    /// `exec()` on the child's side.
    ///
    /// `destroy_notify` will not be automatically called on the child's side
    /// of the `fork()`. It will only be called when the last reference on the
    /// [`SubprocessLauncher`][crate::SubprocessLauncher] is dropped or when a new child setup function is
    /// given.
    ///
    /// [`None`] can be given as `child_setup` to disable the functionality.
    ///
    /// Child setup functions are only available on UNIX.
    /// ## `child_setup`
    /// a `GSpawnChildSetupFunc` to use as the child setup function
    /// ## `destroy_notify`
    /// a `GDestroyNotify` for `user_data`
    #[cfg(any(unix, feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(unix)))]
    #[doc(alias = "g_subprocess_launcher_set_child_setup")]
    pub fn set_child_setup<P: Fn() + 'static>(&self, child_setup: P) {
        let child_setup_data: Box_<P> = Box_::new(child_setup);
        unsafe extern "C" fn child_setup_func<P: Fn() + 'static>(user_data: glib::ffi::gpointer) {
            let callback: &P = &*(user_data as *mut _);
            (*callback)();
        }
        let child_setup = Some(child_setup_func::<P> as _);
        unsafe extern "C" fn destroy_notify_func<P: Fn() + 'static>(data: glib::ffi::gpointer) {
            let _callback: Box_<P> = Box_::from_raw(data as *mut _);
        }
        let destroy_call3 = Some(destroy_notify_func::<P> as _);
        let super_callback0: Box_<P> = child_setup_data;
        unsafe {
            ffi::g_subprocess_launcher_set_child_setup(
                self.to_glib_none().0,
                child_setup,
                Box_::into_raw(super_callback0) as *mut _,
                destroy_call3,
            );
        }
    }

    /// Sets the current working directory that processes will be launched
    /// with.
    ///
    /// By default processes are launched with the current working directory
    /// of the launching process at the time of launch.
    /// ## `cwd`
    /// the cwd for launched processes
    #[doc(alias = "g_subprocess_launcher_set_cwd")]
    pub fn set_cwd(&self, cwd: impl AsRef<std::path::Path>) {
        unsafe {
            ffi::g_subprocess_launcher_set_cwd(
                self.to_glib_none().0,
                cwd.as_ref().to_glib_none().0,
            );
        }
    }

    /// Replace the entire environment of processes launched from this
    /// launcher with the given 'environ' variable.
    ///
    /// Typically you will build this variable by using `g_listenv()` to copy
    /// the process 'environ' and using the functions `g_environ_setenv()`,
    /// `g_environ_unsetenv()`, etc.
    ///
    /// As an alternative, you can use [`setenv()`][Self::setenv()],
    /// [`unsetenv()`][Self::unsetenv()], etc.
    ///
    /// Pass an empty array to set an empty environment. Pass [`None`] to inherit the
    /// parent process’ environment. As of GLib 2.54, the parent process’ environment
    /// will be copied when [`set_environ()`][Self::set_environ()] is called.
    /// Previously, it was copied when the subprocess was executed. This means the
    /// copied environment may now be modified (using [`setenv()`][Self::setenv()],
    /// etc.) before launching the subprocess.
    ///
    /// On UNIX, all strings in this array can be arbitrary byte strings.
    /// On Windows, they should be in UTF-8.
    /// ## `env`
    ///
    ///  the replacement environment
    #[doc(alias = "g_subprocess_launcher_set_environ")]
    pub fn set_environ(&self, env: &[&std::path::Path]) {
        unsafe {
            ffi::g_subprocess_launcher_set_environ(self.to_glib_none().0, env.to_glib_none().0);
        }
    }

    /// Sets the flags on the launcher.
    ///
    /// The default flags are [`SubprocessFlags::NONE`][crate::SubprocessFlags::NONE].
    ///
    /// You may not set flags that specify conflicting options for how to
    /// handle a particular stdio stream (eg: specifying both
    /// [`SubprocessFlags::STDIN_PIPE`][crate::SubprocessFlags::STDIN_PIPE] and
    /// [`SubprocessFlags::STDIN_INHERIT`][crate::SubprocessFlags::STDIN_INHERIT]).
    ///
    /// You may also not set a flag that conflicts with a previous call to a
    /// function like [`set_stdin_file_path()`][Self::set_stdin_file_path()] or
    /// [`take_stdout_fd()`][Self::take_stdout_fd()].
    /// ## `flags`
    /// [`SubprocessFlags`][crate::SubprocessFlags]
    #[doc(alias = "g_subprocess_launcher_set_flags")]
    pub fn set_flags(&self, flags: SubprocessFlags) {
        unsafe {
            ffi::g_subprocess_launcher_set_flags(self.to_glib_none().0, flags.into_glib());
        }
    }

    /// Sets the file path to use as the stderr for spawned processes.
    ///
    /// If `path` is [`None`] then any previously given path is unset.
    ///
    /// The file will be created or truncated when the process is spawned, as
    /// would be the case if using '2>' at the shell.
    ///
    /// If you want to send both stdout and stderr to the same file then use
    /// [`SubprocessFlags::STDERR_MERGE`][crate::SubprocessFlags::STDERR_MERGE].
    ///
    /// You may not set a stderr file path if a stderr fd is already set or
    /// if the launcher flags contain any flags directing stderr elsewhere.
    ///
    /// This feature is only available on UNIX.
    /// ## `path`
    /// a filename or [`None`]
    #[cfg(any(unix, feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(unix)))]
    #[doc(alias = "g_subprocess_launcher_set_stderr_file_path")]
    pub fn set_stderr_file_path(&self, path: Option<impl AsRef<std::path::Path>>) {
        unsafe {
            ffi::g_subprocess_launcher_set_stderr_file_path(
                self.to_glib_none().0,
                path.as_ref().map(|p| p.as_ref()).to_glib_none().0,
            );
        }
    }

    /// Sets the file path to use as the stdin for spawned processes.
    ///
    /// If `path` is [`None`] then any previously given path is unset.
    ///
    /// The file must exist or spawning the process will fail.
    ///
    /// You may not set a stdin file path if a stdin fd is already set or if
    /// the launcher flags contain any flags directing stdin elsewhere.
    ///
    /// This feature is only available on UNIX.
    #[cfg(any(unix, feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(unix)))]
    #[doc(alias = "g_subprocess_launcher_set_stdin_file_path")]
    pub fn set_stdin_file_path(&self, path: &str) {
        unsafe {
            ffi::g_subprocess_launcher_set_stdin_file_path(
                self.to_glib_none().0,
                path.to_glib_none().0,
            );
        }
    }

    /// Sets the file path to use as the stdout for spawned processes.
    ///
    /// If `path` is [`None`] then any previously given path is unset.
    ///
    /// The file will be created or truncated when the process is spawned, as
    /// would be the case if using '>' at the shell.
    ///
    /// You may not set a stdout file path if a stdout fd is already set or
    /// if the launcher flags contain any flags directing stdout elsewhere.
    ///
    /// This feature is only available on UNIX.
    /// ## `path`
    /// a filename or [`None`]
    #[cfg(any(unix, feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(unix)))]
    #[doc(alias = "g_subprocess_launcher_set_stdout_file_path")]
    pub fn set_stdout_file_path(&self, path: Option<impl AsRef<std::path::Path>>) {
        unsafe {
            ffi::g_subprocess_launcher_set_stdout_file_path(
                self.to_glib_none().0,
                path.as_ref().map(|p| p.as_ref()).to_glib_none().0,
            );
        }
    }

    /// Sets the environment variable `variable` in the environment of
    /// processes launched from this launcher.
    ///
    /// On UNIX, both the variable's name and value can be arbitrary byte
    /// strings, except that the variable's name cannot contain '='.
    /// On Windows, they should be in UTF-8.
    /// ## `variable`
    /// the environment variable to set,
    ///  must not contain '='
    /// ## `value`
    /// the new value for the variable
    /// ## `overwrite`
    /// whether to change the variable if it already exists
    #[doc(alias = "g_subprocess_launcher_setenv")]
    pub fn setenv(
        &self,
        variable: impl AsRef<std::ffi::OsStr>,
        value: impl AsRef<std::ffi::OsStr>,
        overwrite: bool,
    ) {
        unsafe {
            ffi::g_subprocess_launcher_setenv(
                self.to_glib_none().0,
                variable.as_ref().to_glib_none().0,
                value.as_ref().to_glib_none().0,
                overwrite.into_glib(),
            );
        }
    }

    //#[doc(alias = "g_subprocess_launcher_spawn")]
    //pub fn spawn(&self, error: &mut glib::Error, argv0: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> Subprocess {
    //    unsafe { TODO: call ffi:g_subprocess_launcher_spawn() }
    //}

    /// Creates a [`Subprocess`][crate::Subprocess] given a provided varargs list of arguments.
    /// ## `argv0`
    /// Command line arguments
    ///
    /// # Returns
    ///
    /// A new [`Subprocess`][crate::Subprocess], or [`None`] on error (and `error` will be set)
    #[doc(alias = "g_subprocess_launcher_spawnv")]
    #[doc(alias = "spawnv")]
    pub fn spawn(&self, argv: &[&std::ffi::OsStr]) -> Result<Subprocess, glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_subprocess_launcher_spawnv(
                self.to_glib_none().0,
                argv.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok(from_glib_full(ret))
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    /// Removes the environment variable `variable` from the environment of
    /// processes launched from this launcher.
    ///
    /// On UNIX, the variable's name can be an arbitrary byte string not
    /// containing '='. On Windows, it should be in UTF-8.
    /// ## `variable`
    /// the environment variable to unset,
    ///  must not contain '='
    #[doc(alias = "g_subprocess_launcher_unsetenv")]
    pub fn unsetenv(&self, variable: impl AsRef<std::ffi::OsStr>) {
        unsafe {
            ffi::g_subprocess_launcher_unsetenv(
                self.to_glib_none().0,
                variable.as_ref().to_glib_none().0,
            );
        }
    }
}

impl fmt::Display for SubprocessLauncher {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("SubprocessLauncher")
    }
}