1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#![doc = include_str!("../README.md")]
pub mod config;
pub mod extension;
pub mod host;
pub mod port;
pub use config::read_and_resolve;
#[cfg(feature = "bin")]
pub fn command() -> clap::Command {
use clap::Arg;
let c = clap::command!();
c.long_about(
"Mölla runns the Kvarn web server using plain-text configs.\n\
See https://kvarn.org/moella/ for more details and how to write the config.\n\
\n\
Logging is controlled using the environment variable `KVARN_LOG`.\n\
See https://docs.rs/env_logger/latest/env_logger/#example for log settings.",
)
.arg(
Arg::new("config")
.short('c')
.long("config")
.num_args(1)
.required(true)
.help("Main config file"),
)
.arg(
Arg::new("high_ports")
.long("high-ports")
.help("Bind to higher ports (8080, 8443) to avoid permission issues")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("host")
.short('h')
.long("host")
.help("Set the default host to show")
.num_args(1),
)
.arg(
Arg::new("instance")
.long("instance-path")
.long("ctl-socket")
.short('p')
.help(
"The path of the control socket. \
If you want to start multiple instances of moella, \
consider this to be an instance name, \
and make it different for all instances. \
If you are using kvarnctl, remember to specify this \
when running the kvarnctl, else it won't find this instance!",
)
.default_value("kvarn.sock"),
)
.disable_help_flag(true)
.arg(
Arg::new("help")
.long("help")
.action(clap::ArgAction::Help)
.help("Print help"),
)
}
#[cfg(feature = "bin")]
pub async fn run(
custom_extensions: &config::CustomExtensions,
) -> std::sync::Arc<kvarn::shutdown::Manager> {
let env_log = env_logger::Env::new().filter_or("KVARN_LOG", "rustls=off,info");
env_logger::Builder::from_env(env_log).init();
let matches = command().get_matches();
let mut rc = match config::read_and_resolve(
matches.get_one::<String>("config").expect("it's required"),
custom_extensions,
matches.get_flag("high_ports"),
matches.get_one::<String>("host").map(String::as_str),
)
.await
{
Ok(rc) => rc,
Err(s) => {
log::error!("{s}");
std::process::exit(1);
}
};
let ctl_path = socket_path().join(
matches
.get_one::<String>("instance")
.expect("we provided a default"),
);
rc = rc.set_ctl_path(ctl_path);
rc.execute().await
}
#[cfg(feature = "bin")]
#[allow(unused_assignments)]
#[cfg_attr(windows, allow(unused_mut))]
pub(crate) fn socket_path() -> std::path::PathBuf {
use std::path::Path;
let mut p = Path::new("/run").to_path_buf();
#[cfg(all(unix, target_os = "macos"))]
{
p = std::env::var_os("HOME")
.map_or_else(|| Path::new("/Library/Caches").to_path_buf(), Into::into);
}
#[cfg(all(unix, not(target_os = "macos")))]
{
let user: u32 = unsafe { libc::getuid() };
if user != 0 {
p.push("user");
p.push(user.to_string());
}
}
p
}