Skip to content

Commit 15cbba4

Browse files
committed
Extract exec_command function out of no_pty and use_pty
1 parent 0a0fd56 commit 15cbba4

File tree

3 files changed

+55
-75
lines changed

3 files changed

+55
-75
lines changed

src/exec/mod.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@ use std::{
1818
};
1919

2020
use crate::{
21+
common::bin_serde::BinPipe,
2122
exec::no_pty::exec_no_pty,
2223
log::{dev_info, dev_warn, user_error},
2324
system::{
25+
_exit,
2426
interface::ProcessId,
25-
killpg,
26-
signal::{consts::*, signal_name},
27+
kill, killpg, set_target_user,
28+
signal::{consts::*, signal_name, SignalNumber, SignalSet},
29+
term::UserTerm,
2730
wait::{Wait, WaitError, WaitOptions},
28-
},
29-
system::{
30-
kill, set_target_user, signal::SignalNumber, term::UserTerm, FileCloser, Group, User,
31+
FileCloser, Group, User,
3132
},
3233
};
3334

@@ -143,6 +144,45 @@ pub enum ExitReason {
143144
Signal(i32),
144145
}
145146

147+
fn exec_command(
148+
file_closer: FileCloser,
149+
mut command: Command,
150+
original_set: Option<SignalSet>,
151+
mut errpipe_tx: BinPipe<i32>,
152+
) -> ! {
153+
// Restore the signal mask now that the handlers have been setup.
154+
if let Some(set) = original_set {
155+
if let Err(err) = set.set_mask() {
156+
dev_warn!("cannot restore signal mask: {err}");
157+
}
158+
}
159+
160+
// SAFETY: We immediately exec after this call and if the exec fails we only access stderr
161+
// and errpipe before exiting without running atexit handlers using _exit
162+
if let Err(err) = unsafe { file_closer.close_the_universe() } {
163+
dev_warn!("failed to close the universe: {err}");
164+
// Send the error to the monitor using the pipe.
165+
if let Some(error_code) = err.raw_os_error() {
166+
errpipe_tx.write(&error_code).ok();
167+
}
168+
169+
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
170+
_exit(1);
171+
}
172+
173+
let err = command.exec();
174+
175+
dev_warn!("failed to execute command: {err}");
176+
// If `exec` returns, it means that executing the command failed. Send the error to the
177+
// monitor using the pipe.
178+
if let Some(error_code) = err.raw_os_error() {
179+
errpipe_tx.write(&error_code).ok();
180+
}
181+
182+
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
183+
_exit(1);
184+
}
185+
146186
// Kill the process with increasing urgency.
147187
//
148188
// Based on `terminate_command`.

src/exec/no_pty.rs

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{ffi::c_int, io, os::unix::process::CommandExt, process::Command};
1+
use std::{ffi::c_int, io, process::Command};
22

33
use super::{
44
event::PollEvent,
@@ -14,10 +14,10 @@ use crate::{
1414
},
1515
};
1616
use crate::{
17-
exec::{handle_sigchld, signal_fmt},
17+
exec::{exec_command, handle_sigchld, signal_fmt},
1818
log::{dev_error, dev_info, dev_warn},
1919
system::{
20-
_exit, fork, getpgid, getpgrp,
20+
fork, getpgid, getpgrp,
2121
interface::ProcessId,
2222
kill, killpg,
2323
term::{Terminal, UserTerm},
@@ -29,7 +29,7 @@ use crate::{
2929
pub(super) fn exec_no_pty(
3030
sudo_pid: ProcessId,
3131
mut file_closer: FileCloser,
32-
mut command: Command,
32+
command: Command,
3333
) -> io::Result<ExitReason> {
3434
// FIXME (ogsudo): Initialize the policy plugin's session here.
3535

@@ -46,7 +46,7 @@ pub(super) fn exec_no_pty(
4646
// FIXME (ogsudo): Some extra config happens here if selinux is available.
4747

4848
// Use a pipe to get the IO error if `exec` fails.
49-
let (mut errpipe_tx, errpipe_rx) = BinPipe::pair()?;
49+
let (errpipe_tx, errpipe_rx) = BinPipe::pair()?;
5050

5151
// Don't close the error pipe as we need it to retrieve the error code if the command execution
5252
// fails.
@@ -58,37 +58,7 @@ pub(super) fn exec_no_pty(
5858
err
5959
})?
6060
else {
61-
// Restore the signal mask now that the handlers have been setup.
62-
if let Some(set) = original_set {
63-
if let Err(err) = set.set_mask() {
64-
dev_warn!("cannot restore signal mask: {err}");
65-
}
66-
}
67-
68-
// SAFETY: We immediately exec after this call and if the exec fails we only access stderr
69-
// and errpipe before exiting without running atexit handlers using _exit
70-
if let Err(err) = unsafe { file_closer.close_the_universe() } {
71-
dev_warn!("failed to close the universe: {err}");
72-
// Send the error to the monitor using the pipe.
73-
if let Some(error_code) = err.raw_os_error() {
74-
errpipe_tx.write(&error_code).ok();
75-
}
76-
77-
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
78-
_exit(1);
79-
}
80-
81-
let err = command.exec();
82-
83-
dev_warn!("failed to execute command: {err}");
84-
// If `exec` returns, it means that executing the command failed. Send the error to the
85-
// monitor using the pipe.
86-
if let Some(error_code) = err.raw_os_error() {
87-
errpipe_tx.write(&error_code).ok();
88-
}
89-
90-
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
91-
_exit(1);
61+
exec_command(file_closer, command, original_set, errpipe_tx);
9262
};
9363

9464
dev_info!("executed command with pid {command_pid}");

src/exec/use_pty/monitor.rs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{convert::Infallible, ffi::c_int, io, os::unix::process::CommandExt, process::Command};
1+
use std::{convert::Infallible, ffi::c_int, io, process::Command};
22

33
use crate::exec::{opt_fmt, signal_fmt};
44
use crate::system::signal::{
@@ -189,11 +189,11 @@ pub(super) fn exec_monitor(
189189
}
190190

191191
fn exec_command(
192-
mut command: Command,
192+
command: Command,
193193
foreground: bool,
194194
pty_follower: PtyFollower,
195195
file_closer: FileCloser,
196-
mut errpipe_tx: BinPipe<i32, i32>,
196+
errpipe_tx: BinPipe<i32, i32>,
197197
original_set: Option<SignalSet>,
198198
) -> ! {
199199
// FIXME (ogsudo): Do any additional configuration that needs to be run after `fork` but before `exec`
@@ -212,37 +212,7 @@ fn exec_command(
212212
// Done with the pty follower.
213213
drop(pty_follower);
214214

215-
// Restore the signal mask now that the handlers have been setup.
216-
if let Some(set) = original_set {
217-
if let Err(err) = set.set_mask() {
218-
dev_warn!("cannot restore signal mask: {err}");
219-
}
220-
}
221-
222-
// SAFETY: We immediately exec after this call and if the exec fails we only access stderr
223-
// and errpipe before exiting without running atexit handlers using _exit
224-
if let Err(err) = unsafe { file_closer.close_the_universe() } {
225-
dev_warn!("failed to close the universe: {err}");
226-
// Send the error to the monitor using the pipe.
227-
if let Some(error_code) = err.raw_os_error() {
228-
errpipe_tx.write(&error_code).ok();
229-
}
230-
231-
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
232-
_exit(1);
233-
}
234-
235-
let err = command.exec();
236-
237-
dev_warn!("failed to execute command: {err}");
238-
// If `exec_command` returns, it means that executing the command failed. Send the error to
239-
// the monitor using the pipe.
240-
if let Some(error_code) = err.raw_os_error() {
241-
errpipe_tx.write(&error_code).ok();
242-
}
243-
244-
// We call `_exit` instead of `exit` to avoid flushing the parent's IO streams by accident.
245-
_exit(1);
215+
crate::exec::exec_command(file_closer, command, original_set, errpipe_tx)
246216
}
247217

248218
struct MonitorClosure<'a> {

0 commit comments

Comments
 (0)