summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorIgor Matuszewski <igor@sequoia-pgp.org>2020-04-01 18:03:27 +0200
committerIgor Matuszewski <igor@sequoia-pgp.org>2020-04-01 21:30:03 +0200
commit29892caa89b6177507d147952f647d4be3fd71c1 (patch)
tree7224ac5e634c9d1f8d0233cd409fd750e68faa8d /ipc
parenta0a9f564cf9fad4edd88258a51a6bc0cb1529151 (diff)
ipc: Don't compile when spawning external server is unsupported on OS
Diffstat (limited to 'ipc')
-rw-r--r--ipc/src/lib.rs83
1 files changed, 47 insertions, 36 deletions
diff --git a/ipc/src/lib.rs b/ipc/src/lib.rs
index 028a5052..7e6a62ab 100644
--- a/ipc/src/lib.rs
+++ b/ipc/src/lib.rs
@@ -69,6 +69,21 @@ use sequoia_core as core;
pub mod assuan;
pub mod gnupg;
+macro_rules! platform {
+ { unix => { $($unix:tt)* }, windows => { $($windows:tt)* } } => {
+ if cfg!(unix) {
+ #[cfg(unix)] { $($unix)* }
+ #[cfg(not(unix))] { unreachable!() }
+ } else if cfg!(windows) {
+ #[cfg(windows)] { $($windows)* }
+ #[cfg(not(windows))] { unreachable!() }
+ } else {
+ #[cfg(not(any(unix, windows)))] compile_error!("Unsupported platform");
+ unreachable!()
+ }
+ }
+}
+
/// Servers need to implement this trait.
pub trait Handler {
/// Called on every connection.
@@ -219,30 +234,30 @@ impl Descriptor {
.stdout(Stdio::null())
.stderr(Stdio::null());
- #[cfg(unix)]
- {
- // Pass the listening TCP socket as child stdin.
- cmd.stdin(unsafe { Stdio::from_raw_fd(listener.into_raw_fd()) });
- }
- #[cfg(windows)]
- {
- // Sockets for `TcpListener` are not inheritable by default, so
- // let's make them so, since we'll pass them to a child process.
- unsafe {
- match winapi::um::handleapi::SetHandleInformation(
- listener.as_raw_socket() as _,
- winapi::um::winbase::HANDLE_FLAG_INHERIT,
- winapi::um::winbase::HANDLE_FLAG_INHERIT,
- ) {
- 0 => Err(std::io::Error::last_os_error()),
- _ => Ok(())
- }?
- };
- // We can't pass the socket to stdin directly on Windows, since only
- // non-overlapped (blocking) I/O handles can be redirected there.
- // We use Tokio (async I/O), so we just pass it via env var rather than
- // establishing a whole separate channel to pass the socket through.
- cmd.env("SOCKET", format!("{}", listener.into_raw_socket()));
+ platform! {
+ unix => {
+ // Pass the listening TCP socket as child stdin.
+ cmd.stdin(unsafe { Stdio::from_raw_fd(listener.into_raw_fd()) });
+ },
+ windows => {
+ // Sockets for `TcpListener` are not inheritable by default, so
+ // let's make them so, since we'll pass them to a child process.
+ unsafe {
+ match winapi::um::handleapi::SetHandleInformation(
+ listener.as_raw_socket() as _,
+ winapi::um::winbase::HANDLE_FLAG_INHERIT,
+ winapi::um::winbase::HANDLE_FLAG_INHERIT,
+ ) {
+ 0 => Err(std::io::Error::last_os_error()),
+ _ => Ok(())
+ }?
+ };
+ // We can't pass the socket to stdin directly on Windows, since
+ // non-overlapped (blocking) I/O handles can be redirected there.
+ // We use Tokio (async I/O), so we just pass it via env var rather
+ // than establishing a separate channel to pass the socket through.
+ cmd.env("SOCKET", format!("{}", listener.into_raw_socket()));
+ }
}
cmd.spawn()?;
@@ -332,18 +347,14 @@ impl Server {
/// }
/// ```
pub fn serve(&mut self) -> Result<()> {
- #[cfg(unix)]
- fn fetch_listener() -> Result<TcpListener> {
- Ok(unsafe { TcpListener::from_raw_fd(0) })
- }
- #[cfg(windows)]
- fn fetch_listener() -> Result<TcpListener> {
- let socket = std::env::var("SOCKET")?.parse()?;
-
- Ok(unsafe { TcpListener::from_raw_socket(socket) })
- }
-
- self.serve_listener(fetch_listener()?)
+ let listener = platform! {
+ unix => { unsafe { TcpListener::from_raw_fd(0) } },
+ windows => {
+ let socket = std::env::var("SOCKET")?.parse()?;
+ unsafe { TcpListener::from_raw_socket(socket) }
+ }
+ };
+ self.serve_listener(listener)
}
fn serve_listener(&mut self, l: TcpListener) -> Result<()> {