1#[cfg(target_os = "linux")]
17pub(crate) use self::portable_linux::*;
18
19#[cfg(any(
20 target_os = "freebsd",
21 target_os = "dragonfly",
22 target_os = "openbsd",
23 target_os = "netbsd",
24 target_os = "macos"
25))]
26pub(crate) use self::portable_bsd::*;
27
28#[cfg(target_family = "windows")]
29pub(crate) use self::portable_windows::*;
30
31#[cfg(target_family = "windows")]
33pub mod portable_windows
34{
35 use std::
36 {
37 env, ffi::{CStr, c_void}, io::{self, ErrorKind}, mem::transmute, time::Duration
38 };
39
40 use windows::
41 {
42 Win32::
43 {
44 Foundation::HANDLE,
45 Networking::WinSock::{self, SOCKET_ERROR},
46 System::
47 {
48 EventLog::{EVENTLOG_INFORMATION_TYPE, RegisterEventSourceA, ReportEventA},
49 SystemInformation
50 }
51 },
52 core::{Free, PCSTR}
53 };
54
55 use crate::{LogFacility, LogMask, NILVALUE, Priority, SyslogMsgPriFac, WindowsEvent, error::SyRes};
56
57 pub const DEFAULT_MAXGRAM_SIZE: u64 = 2048;
58
59 #[derive(Debug)]
61 pub struct EventLogLocal
62 {
63 evs: usize,
66 }
67
68 impl Drop for EventLogLocal
69 {
70 fn drop(&mut self)
71 {
72 unsafe { HANDLE(self.evs as *mut c_void).free() };
73 }
74 }
75
76 impl EventLogLocal
77 {
78 pub
79 fn new(winnie_ev: &WindowsEvent) -> io::Result<Self>
80 {
81 let evs =
84 unsafe
85 {
86 RegisterEventSourceA(
87 winnie_ev
88 .get_server_unc()
89 .map_or(
90 PCSTR::null(),
91 |f| PCSTR::from_raw( transmute(f.as_ptr()) )
92 ),
93 PCSTR::from_raw(
94 transmute(winnie_ev.get_service_name().as_ptr())
95 )
96 )
97 }
98 .map_err(|e|
99 io::Error::new(ErrorKind::ConnectionRefused, e)
100 )?;
101
102 return Ok(Self{ evs: evs.0 as usize });
103 }
104
105 pub
122 fn send(&self, msg: &[u8]) -> io::Result<usize>
123 {
124 if msg.len() == 0
125 {
126 return Ok(0);
127 }
128
129 let mut event_log_type = EVENTLOG_INFORMATION_TYPE;
130 let mut facility = LogFacility::LOG_USER.into_win_facility();
131
132 if msg[0] == '|' as u8
133 {
134 for (idx, c) in msg.iter().enumerate().skip(1)
135 {
136 if *c == '|' as u8
137 {
138 let Ok(pri_fac) =
139 SyslogMsgPriFac::try_from(&msg[1..idx])
140 else { break };
141
142 event_log_type = pri_fac.get_priority().into();
143 facility = pri_fac.get_log_facility().into_win_facility();
144 break;
145 }
146
147 if idx == 8
148 {
149 break;
150 }
151 }
152 }
153
154 let cmsg =
155 CStr::from_bytes_with_nul(msg)
156 .map_err(|e|
157 io::Error::new(ErrorKind::InvalidData, e)
158 )?;
159
160 let msgs =
161 &[PCSTR::from_raw( unsafe { transmute(cmsg.as_ptr()) })];
162
163 unsafe
164 {
165 ReportEventA(
166 HANDLE(self.evs as *mut c_void),
167 event_log_type, 1,
169 0x20010000 | facility,
170 None,
171 0,
172 Some(msgs),
173 None
174 )
175
176 }
177 .map_err(|e|
178 io::Error::new(ErrorKind::ConnectionRefused, e)
179 )?;
180
181 return Ok(msg.len());
182 }
183 }
184
185 pub(crate)
187 fn p_getprogname() -> Option<String>
188 {
189 return
190 env::current_exe()
191 .ok()
192 .map_or(None,
193 |path|
194 path
195 .file_name()
196 .map(|name| name.to_string_lossy().to_string())
197 );
198 }
199
200 pub(crate)
201 fn get_local_dgram_maxdgram() -> u64
202 {
203 return DEFAULT_MAXGRAM_SIZE;
204 }
205
206 pub(crate)
207 fn get_uptime() -> SyRes<Duration>
208 {
209 let ret: u64 = unsafe {SystemInformation::GetTickCount64() };
210
211 return Ok(Duration::from_millis(ret));
212 }
213
214 pub(crate)
215 fn portable_gethostname() -> SyRes<String>
216 {
217 let mut hostname = vec![0_u8; 512];
218
219 let res =
220 unsafe
221 {
222 WinSock::gethostname(&mut hostname)
223 };
224
225 if res == SOCKET_ERROR
226 {
227 let err = unsafe { WinSock::WSAGetLastError() };
228
229 throw_error!("can bot obtain kern.boottime, err: '{}'", err.0);
230 }
231
232 return Ok(String::from_utf8(hostname).map_or(NILVALUE.into(), |f| f));
233 }
234}
235
236#[cfg(target_os = "linux")]
237pub mod portable_linux
238{
239 use std::ffi::CStr;
240 use std::path::Path;
241 use std::time::Duration;
242
243 use nix::libc;
244
245 use crate::error::SyRes;
246 use crate::{map_error};
247
248 pub const DEFAULT_MAXGRAM_SIZE: u64 = 2048;
249
250 #[link(name = "c")]
251 unsafe extern "C" {
252 pub static mut program_invocation_name : *mut libc::c_char ;
253 }
254
255 pub(crate)
257 fn p_getprogname() -> Option<String>
258 {
259 let pn = unsafe{ program_invocation_name };
260
261 let temp = unsafe {CStr::from_ptr(pn)};
262
263 return
264 temp
265 .to_str()
266 .ok()
267 .map_or(None, |r| Path::new(r).file_name().map(|r| r.to_string_lossy().into()));
268}
285
286 pub(crate)
287 fn get_local_dgram_maxdgram() -> u64
288 {
289 return DEFAULT_MAXGRAM_SIZE;
290 }
291
292 pub(crate)
293 fn get_uptime() -> SyRes<Duration>
294 {
295 let sysinfo =
296 nix::sys::sysinfo::sysinfo()
297 .map_err(|e|
298 map_error!("get_uptime() sysinfo error: {}", e)
299 )?;
300
301 return Ok(sysinfo.uptime());
302 }
303
304 pub(crate)
305 fn portable_gethostname() -> SyRes<String>
306 {
307 return
308 nix::unistd::gethostname()
309 .map_or_else(
310 |e|
311 Err(map_error!("gethostname() error: {}", e)),
312 |hn|
313 hn.into_string()
314 .map_or(
315 Err(map_error!("gethostname() into_string() error")),
316 |hostname| Ok(hostname)
317 )
318 );
319 }
320}
321
322
323#[cfg(any(
324 target_os = "freebsd",
325 target_os = "dragonfly",
326 target_os = "openbsd",
327 target_os = "netbsd",
328 target_os = "macos"
329))]
330pub mod portable_bsd
331{
332 use std::{ffi::{CStr, CString}, time::Duration};
333
334 use chrono::Local;
335 use nix::{errno::Errno, libc::{self, timeval}};
336
337 use crate::error::SyRes;
338
339 pub const DEFAULT_MAXGRAM_SIZE: u64 = 2048;
340
341 #[link(name = "c")]
342 unsafe extern "C" {
343 fn getprogname() -> *const libc::c_char;
344 }
345
346 pub(crate)
348 fn p_getprogname() -> Option<String>
349 {
350 let pn = unsafe { getprogname() };
351
352 let temp = unsafe {CStr::from_ptr(pn)};
353
354 match temp.to_str()
355 {
356 Ok(r) =>
357 return Some(r.to_string()),
358 Err(_) =>
359 return None,
360 }
361
362 }
363
364 pub(crate)
365 fn get_local_dgram_maxdgram() -> u64
366 {
367 let name = CString::new("net.local.dgram.maxdgram").unwrap();
368 let mut maxdgram: u64 = 0;
369 let mut maxdgram_size: libc::size_t = std::mem::size_of_val(&maxdgram) as libc::size_t;
370
371 let res =
372 unsafe
373 {
374 libc::sysctlbyname(
375 name.as_ptr(),
376 &mut maxdgram as *mut _ as *mut libc::c_void,
377 &mut maxdgram_size as *mut _ as *mut libc::size_t,
378 std::ptr::null(),
379 0)
380 };
381
382 if res == -1
383 {
384 if cfg!(feature = "dgram_sysctl_failure_panic")
385 {
386 let err = Errno::last_raw();
387 panic!("can not obtain MAXDGRAM from sysctl '{}', err: '{}'", name.to_string_lossy(), err);
388 }
389 else
390 {
391 return DEFAULT_MAXGRAM_SIZE;
392 }
393 }
394 else if res == 0
395 {
396 return maxdgram;
397 }
398 else
399 {
400 panic!("can not obtain MAXDGRAM from sysctl '{}', unknwon res: '{}'", name.to_string_lossy(), res);
401 }
402 }
403
404 pub(crate)
405 fn get_uptime() -> SyRes<Duration>
406 {
407 let name = CString::new("kern.boottime").unwrap();
408
409 let mut boottime: timeval = unsafe { std::mem::zeroed() };
410 let mut size: libc::size_t = std::mem::size_of_val(&boottime) as libc::size_t;
411
412 let res =
413 unsafe
414 {
415 libc::sysctlbyname(
416 name.as_ptr(),
417 &mut boottime as *mut _ as *mut libc::c_void,
418 &mut size as *mut _ as *mut libc::size_t,
419 std::ptr::null(),
420 0)
421 };
422
423
424 if res == -1
425 {
426 throw_error!("can bot obtain kern.boottime, err: '{}'", Errno::last_raw());
427 }
428 else if res == 0
429 {
430 let c =
431 chrono::Duration::new(boottime.tv_sec, boottime.tv_usec as u32)
432 .ok_or_else(||
433 map_error!("timeval to chrono::Duration converion error")
434 )?;
435 let now = Local::now();
436
437 let r =
438 now
439 .checked_sub_signed(c)
440 .ok_or_else(||
441 map_error!("error checked_sub_signed()")
442 )?;
443 return Ok(Duration::from_millis(r.timestamp_millis() as u64));
444 }
445 else
446 {
447 throw_error!("can not obtain kern.boottime from sysctl '{}', unknwon res: '{}'", name.to_string_lossy(), res);
448 }
449 }
450
451 pub(crate)
452 fn portable_gethostname() -> SyRes<String>
453 {
454 return
455 nix::unistd::gethostname()
456 .map_or_else(
457 |e|
458 Err(map_error!("gethostname() error: {}", e)),
459 |hn|
460 hn.into_string()
461 .map_or(
462 Err(map_error!("gethostname() into_string() error")),
463 |hostname| Ok(hostname)
464 )
465 );
466 }
467
468 #[cfg(test)]
469 mod tests
470 {
471 use crate::portable::get_uptime;
472
473 #[test]
474 fn test_get_uptime()
475 {
476 let res = get_uptime();
477 assert_eq!(res.is_ok(), true);
478
479 println!("{:?}", res.unwrap());
480 }
481 }
482}
483
484
485#[inline]
487pub
488fn get_pid() -> u32
489{
490 return std::process::id();
491}
492
493#[cfg(test)]
494mod test_portables
495{
496 use super::*;
497
498 #[test]
499 fn test_get_procname()
500 {
501 let procname = p_getprogname();
502
503 println!("Processname is: {:?}", procname);
504
505 assert_eq!(procname.is_some(), true);
506 assert_eq!(procname.as_ref().unwrap().starts_with("syslog_rs"), true);
507 }
508
509 #[test]
510 fn test_maxgram()
511 {
512 let max = get_local_dgram_maxdgram();
513
514 println!("maxdgram: '{}'", max);
515
516 assert_eq!(max > 0, true);
517 }
518}