service_manager/
kind.rs

1use cfg_if::cfg_if;
2use std::io;
3
4/// Represents the kind of service manager
5#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
6#[cfg_attr(feature = "clap", derive(::clap::ValueEnum))]
7#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
8#[cfg_attr(feature = "clap", clap(rename_all = "lowercase"))]
9#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
10pub enum ServiceManagerKind {
11    /// Use launchd to manage the service
12    Launchd,
13
14    /// Use OpenRC to manage the service
15    OpenRc,
16
17    /// Use rc.d to manage the service
18    Rcd,
19
20    /// Use Windows service controller to manage the service
21    Sc,
22
23    /// Use systemd to manage the service
24    Systemd,
25
26    /// Use WinSW to manage the service
27    WinSw,
28}
29
30impl ServiceManagerKind {
31    /// Looks up the kind of service management platform native to the operating system
32    pub fn native() -> io::Result<ServiceManagerKind> {
33        cfg_if! {
34            if #[cfg(target_os = "macos")] {
35                Ok(ServiceManagerKind::Launchd)
36            } else if #[cfg(target_os = "windows")] {
37                use super::{ServiceManager, TypedServiceManager};
38
39                // Prefer WinSW over sc.exe, because if it's present, it's likely been explicitly
40                // installed as an alternative to sc.exe.
41                let manager = TypedServiceManager::target(ServiceManagerKind::WinSw);
42                if let Ok(true) = manager.available() {
43                    return Ok(ServiceManagerKind::WinSw);
44                }
45
46                Ok(ServiceManagerKind::Sc)
47            } else if #[cfg(any(
48                target_os = "freebsd",
49                target_os = "dragonfly",
50                target_os = "openbsd",
51                target_os = "netbsd"
52            ))] {
53                Ok(ServiceManagerKind::Rcd)
54            } else if #[cfg(target_os = "linux")] {
55                use super::{ServiceManager, TypedServiceManager};
56
57                let manager = TypedServiceManager::target(ServiceManagerKind::Systemd);
58                if let Ok(true) = manager.available() {
59                    return Ok(ServiceManagerKind::Systemd);
60                }
61
62                let manager = TypedServiceManager::target(ServiceManagerKind::OpenRc);
63                if let Ok(true) = manager.available() {
64                    return Ok(ServiceManagerKind::OpenRc);
65                }
66
67                Err(io::Error::new(
68                    io::ErrorKind::Unsupported,
69                    "Only systemd and openrc are supported on Linux",
70                ))
71            } else {
72                Err(io::Error::new(
73                    io::ErrorKind::Unsupported,
74                    "Service manager are not supported on current Operating System!",
75                ))
76            }
77        }
78    }
79}