use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProcEvent {
Exec {
cpu: u32,
pid: u32,
tgid: u32,
timestamp_ns: u64,
},
Fork {
cpu: u32,
parent_pid: u32,
parent_tgid: u32,
child_pid: u32,
child_tgid: u32,
timestamp_ns: u64,
},
Exit {
cpu: u32,
pid: u32,
tgid: u32,
exit_code: u32,
exit_signal: u32,
parent_pid: u32,
parent_tgid: u32,
timestamp_ns: u64,
},
Uid {
cpu: u32,
pid: u32,
tgid: u32,
ruid: u32,
euid: u32,
timestamp_ns: u64,
},
Gid {
cpu: u32,
pid: u32,
tgid: u32,
rgid: u32,
egid: u32,
timestamp_ns: u64,
},
Sid {
cpu: u32,
pid: u32,
tgid: u32,
timestamp_ns: u64,
},
Ptrace {
cpu: u32,
pid: u32,
tgid: u32,
tracer_pid: u32,
tracer_tgid: u32,
timestamp_ns: u64,
},
Comm {
cpu: u32,
pid: u32,
tgid: u32,
comm: [u8; 16],
timestamp_ns: u64,
},
Coredump {
cpu: u32,
pid: u32,
tgid: u32,
parent_pid: u32,
parent_tgid: u32,
timestamp_ns: u64,
},
Unknown {
what: u32,
raw_data: Vec<u8>,
},
}
impl ProcEvent {
pub fn exit_status(&self) -> Option<i32> {
if let ProcEvent::Exit {
exit_code,
exit_signal,
..
} = self
{
if *exit_signal == 0 {
Some(((exit_code >> 8) & 0xFF) as i32)
} else {
None
}
} else {
None
}
}
pub fn terminating_signal(&self) -> Option<i32> {
if let ProcEvent::Exit {
exit_code,
exit_signal,
..
} = self
{
if *exit_signal != 0 || (*exit_code & 0x7F) != 0 {
Some((exit_code & 0x7F) as i32)
} else {
None
}
} else {
None
}
}
}
impl fmt::Display for ProcEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ProcEvent::Exec {
pid,
tgid,
timestamp_ns,
..
} => write!(f, "EXEC pid={pid} tgid={tgid} ts={timestamp_ns}"),
ProcEvent::Fork {
parent_pid,
parent_tgid,
child_pid,
child_tgid,
timestamp_ns,
..
} => write!(
f,
"FORK parent=({parent_pid},{parent_tgid}) child=({child_pid},{child_tgid}) ts={timestamp_ns}"
),
ProcEvent::Exit {
pid,
tgid,
exit_code,
exit_signal,
parent_pid,
parent_tgid,
timestamp_ns,
..
} => write!(
f,
"EXIT pid={pid} tgid={tgid} code={exit_code} signal={exit_signal} parent=({parent_pid},{parent_tgid}) ts={timestamp_ns}"
),
ProcEvent::Uid {
pid,
tgid,
ruid,
euid,
timestamp_ns,
..
} => write!(
f,
"UID pid={pid} tgid={tgid} ruid={ruid} euid={euid} ts={timestamp_ns}"
),
ProcEvent::Gid {
pid,
tgid,
rgid,
egid,
timestamp_ns,
..
} => write!(
f,
"GID pid={pid} tgid={tgid} rgid={rgid} egid={egid} ts={timestamp_ns}"
),
ProcEvent::Sid {
pid,
tgid,
timestamp_ns,
..
} => write!(f, "SID pid={pid} tgid={tgid} ts={timestamp_ns}"),
ProcEvent::Ptrace {
pid,
tgid,
tracer_pid,
tracer_tgid,
timestamp_ns,
..
} => write!(
f,
"PTRACE pid={pid} tgid={tgid} tracer=({tracer_pid},{tracer_tgid}) ts={timestamp_ns}"
),
ProcEvent::Comm {
pid,
tgid,
comm,
timestamp_ns,
..
} => {
let end = comm.iter().position(|&b| b == 0).unwrap_or(16);
let name = std::str::from_utf8(&comm[..end]).unwrap_or("<invalid>");
write!(
f,
"COMM pid={pid} tgid={tgid} name=\"{name}\" ts={timestamp_ns}"
)
}
ProcEvent::Coredump {
pid,
tgid,
parent_pid,
parent_tgid,
timestamp_ns,
..
} => {
write!(
f,
"COREDUMP pid={pid} tgid={tgid} parent=({parent_pid},{parent_tgid}) ts={timestamp_ns}"
)
}
ProcEvent::Unknown { what, raw_data } => {
write!(f, "UNKNOWN what=0x{what:08x} len={}", raw_data.len())
}
}
}
}