1use base::{
2 RunMode,
3 consts::*,
4 proxy::{DisEnAbleUnitFiles, DisEnAbleUnitFilesResponse},
5};
6
7use std::{borrow::Cow, env, error::Error};
8use tokio::sync::OnceCell;
9use tracing::{debug, info, warn};
10use zbus::{
11 Connection, ObjectServer, connection, interface, message::Header, object_server::SignalEmitter,
12};
13
14use crate::{SysDManagerProxy, file, sysdcom};
15
16#[interface(name = "io.github.plrigaux.SysDManager", introspection_docs = true)]
17impl SysDManagerProxy {
18 pub async fn create_drop_in(
19 &mut self,
20 #[zbus(header)] header: Header<'_>,
21 runtime: bool,
22 unit_name: &str,
23 file_name: &str,
24 content: &str,
25 ) -> zbus::fdo::Result<()> {
26 self.check_autorisation(header).await?;
28
29 file::create_drop_in(runtime, unit_name, file_name, content).await
31 }
32
33 pub async fn save_file(
34 &mut self,
35 #[zbus(header)] header: Header<'_>,
36
37 file_path: &str,
38 content: &str,
39 ) -> zbus::fdo::Result<u64> {
40 self.check_autorisation(header).await?;
41 file::save(file_path, content).await
42 }
43
44 pub async fn my_user_id(
45 &mut self,
46 #[zbus(header)] header: Header<'_>,
47 ) -> zbus::fdo::Result<u32> {
48 self.check_autorisation(header).await?;
49
50 let id = unsafe { libc::getegid() };
51 info!("ids {}", id);
52
53 Ok(id)
54 }
55
56 #[zbus(signal)]
58 async fn bye(signal_emitter: &SignalEmitter<'_>, message: &str) -> zbus::Result<()>;
59
60 #[zbus(signal)]
61 async fn hello(signal_emitter: &SignalEmitter<'_>, message: &str) -> zbus::Result<()>;
62
63 async fn quit(
65 &self,
66 #[zbus(header)] hdr: Header<'_>,
67 #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
68 #[zbus(object_server)] _server: &ObjectServer,
69 ) -> zbus::fdo::Result<()> {
70 let path = hdr.path().unwrap();
71 let msg = format!("You are leaving me on the {} path?", path);
72 emitter.bye(&msg).await?;
73
74 Ok(())
77 }
78
79 async fn even_ping(
80 &mut self,
81 #[zbus(header)] header: Header<'_>,
82 val: u32,
83 ) -> zbus::fdo::Result<u32> {
84 info!("even_ping {val}");
85 self.check_autorisation(header).await?;
86 if val.is_multiple_of(2) {
87 Ok(val)
88 } else {
89 Err(zbus::fdo::Error::Failed(format!("{val} not even!")))
90 }
91 }
92
93 async fn clean_unit(
94 &self,
95 #[zbus(header)] header: Header<'_>,
96
97 unit_name: &str,
98 what: Vec<&str>,
99 ) -> zbus::fdo::Result<()> {
100 info!("clean_unit {} {:?}", unit_name, what);
101
102 self.check_autorisation(header).await?;
103
104 let proxy = get_proxy().await?;
105 proxy
106 .clean_unit(unit_name, &what)
107 .await
108 .inspect_err(|e| warn!("Error while calling clean_unit on sysdbus proxy: {:?}", e))
109 }
110
111 async fn freeze_unit(
112 &self,
113 #[zbus(header)] header: Header<'_>,
114 unit_name: &str,
115 ) -> zbus::fdo::Result<()> {
116 info!("freeze_unit {}", unit_name);
117 self.check_autorisation(header).await?;
118
119 let proxy = get_proxy().await?;
120 proxy
121 .freeze_unit(unit_name)
122 .await
123 .inspect_err(|e| warn!("Error while calling freeze_unit on sysdbus proxy: {:?}", e))
124 }
125
126 async fn thaw_unit(
127 &self,
128 #[zbus(header)] header: Header<'_>,
129 unit_name: &str,
130 ) -> zbus::fdo::Result<()> {
131 info!("thaw_unit {}", unit_name);
132 self.check_autorisation(header).await?;
133
134 let proxy = get_proxy().await?;
135 proxy
136 .thaw_unit(unit_name)
137 .await
138 .inspect_err(|e| warn!("Error while calling thaw_unit on sysdbus proxy: {:?}", e))
139 }
140
141 async fn revert_unit_files(
142 &self,
143 #[zbus(header)] header: Header<'_>,
144 file_names: Vec<String>,
145 ) -> zbus::fdo::Result<Vec<DisEnAbleUnitFiles>> {
146 info!("Revert_unit_files {:?}", file_names);
147
148 let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy().await?;
149
150 debug!("Proxy {:?}", proxy);
151 self.check_autorisation(header).await?;
152 debug!("Polkit autorized");
153 match proxy.revert_unit_files(&file_names).await {
154 Ok(vec) => {
155 info!("revert_unit_files {:?} --> {:?}", file_names, vec);
156 Ok(vec)
157 }
158 Err(err) => {
159 warn!(
160 "Error while calling revert_unit_files on sysdbus proxy: {:?}",
161 err
162 );
163 Err(err)
164 }
165 }
166 }
167
168 async fn reload(&self, #[zbus(header)] header: Header<'_>) -> zbus::fdo::Result<()> {
169 info!("Reload");
170 let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy().await?;
171 self.check_autorisation(header).await?;
172 debug!("Polkit autorized");
173 proxy
174 .reload()
175 .await
176 .inspect_err(|e| warn!("Error while calling reload on sysdbus proxy: {:?}", e))
177 }
178
179 async fn enable_unit_files_with_flags(
180 &self,
181 #[zbus(header)] header: Header<'_>,
182 unit_files: Vec<&str>,
183 flags: u64,
184 ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse> {
185 info!(
186 "enable_unit_files_with_flags {:?} flags {}",
187 unit_files, flags
188 );
189 self.check_autorisation(header).await?;
190
191 let proxy = get_proxy().await?;
192 proxy
193 .enable_unit_files_with_flags(&unit_files, flags)
194 .await
195 .inspect_err(|e| {
196 warn!(
197 "Error while calling disable_unit_files_with_flags on sysdbus proxy: {:?}",
198 e
199 )
200 })
201 }
202
203 async fn disable_unit_files_with_flags(
204 &self,
205 #[zbus(header)] header: Header<'_>,
206 unit_files: Vec<&str>,
207 flags: u64,
208 ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse> {
209 info!(
210 "disable_unit_files_with_flags {:?} flags {}",
211 unit_files, flags
212 );
213 self.check_autorisation(header).await?;
214
215 let proxy = get_proxy().await?;
216 proxy
217 .disable_unit_files_with_flags_and_install_info(&unit_files, flags)
218 .await
219 .inspect_err(|e| {
220 warn!(
221 "Error while calling disable_unit_files_with_flags on sysdbus proxy: {:?}",
222 e
223 )
224 })
225 }
226}
227
228pub async fn init_serve_connection(
229 run_mode: RunMode,
230) -> Result<(Connection, String), Box<dyn Error>> {
231 const VERSION: &str = env!("CARGO_PKG_VERSION");
232 info!("Init Proxy version {VERSION}");
233
234 let proxy = SysDManagerProxy::new()?;
235
236 let id = unsafe { libc::getegid() };
237 info!("User id {id}");
238
239 let default_name = if run_mode == RunMode::Development {
240 DBUS_NAME_DEV
241 } else {
242 DBUS_NAME
243 };
244
245 let dbus_name = get_env("DBUS_NAME", default_name);
246 let dbus_path = get_env("DBUS_PATH", DBUS_PATH);
247
248 info!("DBus name {dbus_name}");
249 info!("DBus path {dbus_path}");
250
251 let connection = connection::Builder::system()?
252 .name(dbus_name)?
253 .serve_at(dbus_path.clone(), proxy)?
254 .build()
255 .await?;
256
257 Ok((connection, dbus_path.to_string()))
258}
259
260fn get_env<'a>(key: &str, default: &'a str) -> Cow<'a, str> {
261 match env::var(key) {
262 Ok(val) => {
263 info!("Key {key}, Value {val}");
264 Cow::Owned(val)
265 }
266 Err(e) => {
267 debug!("Env error {e:?}");
268 info!("Key {key}, Use default value {default}");
269 Cow::Borrowed(default)
270 }
271 }
272}
273
274async fn get_proxy() -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
275 system_proxy().await }
277
278static SYS_PROXY: OnceCell<sysdcom::SysDManagerComLinkProxy> = OnceCell::const_new();
279
280async fn system_proxy() -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
281 SYS_PROXY
282 .get_or_try_init(
283 async || -> Result<sysdcom::SysDManagerComLinkProxy, zbus::Error> {
284 let connection = Connection::system().await?;
285 let proxy = sysdcom::SysDManagerComLinkProxy::builder(&connection)
286 .build()
287 .await?;
288 Ok(proxy)
289 },
290 )
291 .await
292}