@@ -13,7 +13,7 @@ use std::{
1313 os:: unix:: ffi:: OsStrExt ,
1414 os:: unix:: process:: CommandExt ,
1515 path:: { Path , PathBuf } ,
16- process:: Command ,
16+ process:: { self , Command } ,
1717 time:: Duration ,
1818} ;
1919
@@ -24,13 +24,12 @@ use crate::{
2424 exec:: no_pty:: exec_no_pty,
2525 log:: { dev_info, dev_warn, user_error} ,
2626 system:: {
27- _exit,
27+ ForkResult , Group , User , _exit, fork ,
2828 interface:: ProcessId ,
29- kill, killpg, mark_fds_as_cloexec, set_target_user,
29+ kill, killpg, mark_fds_as_cloexec, set_target_user, setpgid ,
3030 signal:: { consts:: * , signal_name, SignalNumber , SignalSet } ,
3131 term:: UserTerm ,
3232 wait:: { Wait , WaitError , WaitOptions } ,
33- Group , User ,
3433 } ,
3534} ;
3635
@@ -71,6 +70,7 @@ pub struct RunOptions<'a> {
7170 pub group : & ' a Group ,
7271 pub umask : Umask ,
7372
73+ pub background : bool ,
7474 pub use_pty : bool ,
7575 pub noexec : bool ,
7676}
@@ -83,6 +83,19 @@ pub fn run_command(
8383 options : RunOptions < ' _ > ,
8484 env : impl IntoIterator < Item = ( impl AsRef < OsStr > , impl AsRef < OsStr > ) > ,
8585) -> io:: Result < ExitReason > {
86+ if options. background {
87+ // SAFETY: There should be no other threads at this point.
88+ match unsafe { fork ( ) } ? {
89+ ForkResult :: Parent ( _) => process:: exit ( 0 ) ,
90+ ForkResult :: Child => {
91+ // Child continues in an orphaned process group.
92+ // Reads from the terminal fail with EIO.
93+ // Writes succeed unless tostop is set on the terminal.
94+ setpgid ( ProcessId :: new ( 0 ) , ProcessId :: new ( 0 ) ) ?;
95+ }
96+ }
97+ }
98+
8699 // FIXME: should we pipe the stdio streams?
87100 let qualified_path = options. command ;
88101 let mut command = Command :: new ( qualified_path) ;
@@ -185,6 +198,7 @@ pub fn run_command(
185198 command,
186199 user_tty,
187200 options. user ,
201+ options. background ,
188202 ) ,
189203 Err ( err) => {
190204 dev_info ! ( "Could not open user's terminal, not allocating a pty: {err}" ) ;
0 commit comments