use std::ffi::{c_char, c_int, c_short, c_uint};
#[cfg(test)]
use std::{
mem::{align_of, size_of, MaybeUninit},
ptr::addr_of,
};
use libc::{pid_t, timeval};
pub const UT_LINESIZE: usize = 32;
pub const UT_NAMESIZE: usize = 32;
pub const UT_HOSTSIZE: usize = 256;
#[cfg(target_os = "linux")]
#[cfg(any(target_env = "musl", target_env = "gnu"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug)]
#[allow(non_camel_case_types)]
pub enum UtType {
EMPTY = 0,
RUN_LVL = 1,
BOOT_TIME = 2,
NEW_TIME = 3,
OLD_TIME = 4,
INIT_PROCESS = 5,
LOGIN_PROCESS = 6,
USER_PROCESS = 7,
DEAD_PROCESS = 8,
ACCOUNTING = 9,
}
#[test]
fn test_layout_ut_type() {
assert_eq!(
size_of::<UtType>(),
size_of::<c_short>(),
concat!("Size of: ", stringify!(timeval))
);
}
#[test]
fn bindgen_test_layout_timeval() {
const UNINIT: MaybeUninit<timeval> = MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
size_of::<timeval>(),
16usize,
concat!("Size of: ", stringify!(timeval))
);
assert_eq!(
align_of::<timeval>(),
8usize,
concat!("Alignment of ", stringify!(timeval))
);
assert_eq!(
unsafe { addr_of!((*ptr).tv_sec) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(timeval),
"::",
stringify!(tv_sec)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).tv_usec) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(timeval),
"::",
stringify!(tv_usec)
)
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct ExitStatus {
pub e_termination: c_short,
pub e_exit: c_short,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Utmpx {
pub ut_type: UtType,
pub __ut_pad1: c_short,
pub ut_pid: pid_t,
pub ut_line: [c_char; UT_LINESIZE],
pub ut_id: [c_char; 4usize],
pub ut_user: [c_char; UT_NAMESIZE],
pub ut_host: [c_char; UT_HOSTSIZE],
pub ut_exit: ExitStatus,
#[cfg(target_endian = "little")]
pub ut_session: c_int,
#[cfg(target_endian = "little")]
pub __ut_pad2: c_int,
#[cfg(target_endian = "big")]
pub __ut_pad2: c_int,
#[cfg(target_endian = "big")]
pub ut_session: c_int,
pub ut_tv: timeval,
pub ut_addr_v6: [c_uint; 4usize],
pub __unused: [c_char; 20usize],
}
#[test]
fn bindgen_test_layout_utmpx_bindgen_ty_1() {
const UNINIT: MaybeUninit<ExitStatus> = MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
size_of::<ExitStatus>(),
4usize,
concat!("Size of: ", stringify!(utmpx__bindgen_ty_1))
);
assert_eq!(
align_of::<ExitStatus>(),
2usize,
concat!("Alignment of ", stringify!(utmpx__bindgen_ty_1))
);
assert_eq!(
unsafe { addr_of!((*ptr).e_termination) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(utmpx__bindgen_ty_1),
"::",
stringify!(__e_termination)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).e_exit) as usize - ptr as usize },
2usize,
concat!(
"Offset of field: ",
stringify!(utmpx__bindgen_ty_1),
"::",
stringify!(__e_exit)
)
);
}
#[test]
fn bindgen_test_layout_utmpx() {
const UNINIT: MaybeUninit<Utmpx> = MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
size_of::<Utmpx>(),
400usize,
concat!("Size of: ", stringify!(utmpx))
);
assert_eq!(
align_of::<Utmpx>(),
8usize,
concat!("Alignment of ", stringify!(utmpx))
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_type) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_type)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).__ut_pad1) as usize - ptr as usize },
2usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(__ut_pad1)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_pid) as usize - ptr as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_pid)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_line) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_line)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_id) as usize - ptr as usize },
40usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_id)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_user) as usize - ptr as usize },
44usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_user)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_host) as usize - ptr as usize },
76usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_host)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_exit) as usize - ptr as usize },
332usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_exit)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_session) as usize - ptr as usize },
336usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_session)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).__ut_pad2) as usize - ptr as usize },
340usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(__ut_pad2)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_tv) as usize - ptr as usize },
344usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_tv)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).ut_addr_v6) as usize - ptr as usize },
360usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(ut_addr_v6)
)
);
assert_eq!(
unsafe { addr_of!((*ptr).__unused) as usize - ptr as usize },
376usize,
concat!(
"Offset of field: ",
stringify!(utmpx),
"::",
stringify!(__unused)
)
);
}
extern "C" {
pub fn endutxent();
pub fn getutxent() -> *mut Utmpx;
pub fn getutxid(b: *const Utmpx) -> *mut Utmpx;
pub fn getutxline(b: *const Utmpx) -> *mut Utmpx;
pub fn pututxline(b: *const Utmpx) -> *mut Utmpx;
pub fn setutxent();
pub fn utmpxname(file: *const c_char) -> c_int;
}