qsu/
lib.rs

1//! _qsu_ is a set of tools for integrating a server application against a
2//! service subsystem (such as
3//! [Windows Services](https://learn.microsoft.com/en-us/windows/win32/services/services), [systemd](https://systemd.io/), or
4//! [launchd](https://www.launchd.info/)).
5//!
6//! It offers a thin runtime wrapper layer with the purpose of abstracting away
7//! differences between service subsystems (and also provides the same
8//! interface when running the server application as a foreground process).
9//! More information about the wrapper runtime can be found in the [rt] module
10//! documentation.
11//!
12//! In addition _qsu_ offers helper functions to register/deregister an
13//! executable with the system's service subsystem.  These are documented
14//! [installer] module.
15//!
16//! And finally it offers an argument parser to offer basic service
17//! registration/deregistration and running using a consistent command line
18//! interface.  These are documented in the [argp] module.
19//!
20//!
21//! # Features
22//! | Feature     | Function
23//! |-------------|----------
24//! | `clap`      | Enable `clap` (argument parser) integration.
25//! | `installer` | Tools for registering/deregistering services.
26//! | `rt`        | Service wrapper (enabled by default).
27//! | `systemd`   | systemd integration support.
28//! | `tokio`     | Tokio server application type support.
29//! | `rocket`    | Rocket server application type support.
30//!
31//! In addition there's a special `wait-for-debugger` feature that is only used
32//! on Windows.  It will make the service runtime halt and wait for a debugger
33//! to attach just before starting the Windows Service runtime.  Once a
34//! debugger has attached, it will voluntarily trigger a breakpoint.
35
36#![cfg_attr(docsrs, feature(doc_cfg))]
37
38mod err;
39mod lumberjack;
40
41#[cfg(feature = "rt")]
42#[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
43pub mod rt;
44
45#[cfg(feature = "clap")]
46#[cfg_attr(docsrs, doc(cfg(feature = "clap")))]
47pub mod argp;
48
49#[cfg(feature = "installer")]
50#[cfg_attr(docsrs, doc(cfg(feature = "installer")))]
51pub mod installer;
52
53use std::{ffi::OsStr, path::Path};
54
55pub use async_trait::async_trait;
56
57pub use lumberjack::LumberJack;
58
59pub use err::Error;
60
61#[cfg(any(feature = "rt", feature = "installer"))]
62#[cfg_attr(docsrs, doc(cfg(any(feature = "rt", feature = "installer"))))]
63pub use err::CbErr;
64
65#[cfg(feature = "tokio")]
66pub use tokio;
67
68#[cfg(feature = "rocket")]
69pub use rocket;
70
71pub use log;
72pub use tracing;
73
74
75#[cfg(feature = "clap")]
76#[cfg_attr(docsrs, doc(cfg(feature = "clap")))]
77pub use clap;
78
79/// Attempt to derive a default service name based on the executable's name.
80///
81/// The idea is to get the current executable's file name and strip it's
82/// extension (if there is one).  The file stem name is the default service
83/// name.  On macos the name will be prefixed by `local.`.
84#[must_use]
85pub fn default_service_name() -> Option<String> {
86  let binary_path = ::std::env::current_exe().ok()?;
87
88  let name = binary_path.file_name()?;
89  let name = Path::new(name);
90  let name = name.file_stem()?;
91
92  mkname(name)
93}
94
95#[cfg(not(target_os = "macos"))]
96fn mkname(nm: &OsStr) -> Option<String> {
97  nm.to_str().map(String::from)
98}
99
100#[cfg(target_os = "macos")]
101fn mkname(nm: &OsStr) -> Option<String> {
102  nm.to_str().map(|x| format!("local.{x}"))
103}
104
105// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :