1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

uucore::utmpx: change API and fix error

This commit is contained in:
Knight 2016-08-11 15:41:12 +08:00
parent 7637115e51
commit 18da533538
3 changed files with 41 additions and 23 deletions

View file

@ -251,7 +251,7 @@ fn time_string(ut: &Utmpx) -> String {
impl Pinky { impl Pinky {
fn print_entry(&self, ut: &Utmpx) { fn print_entry(&self, ut: &Utmpx) {
let mut pts_path = PathBuf::from("/dev"); let mut pts_path = PathBuf::from("/dev");
pts_path.push(ut.tty_device().as_ref()); pts_path.push(ut.tty_device().as_str());
let mesg; let mesg;
let last_change; let last_change;
@ -298,7 +298,7 @@ impl Pinky {
print!(" {}", time_string(&ut)); print!(" {}", time_string(&ut));
if self.include_where && !ut.host().is_empty() { if self.include_where && !ut.host().is_empty() {
let ut_host = ut.host().into_owned(); let ut_host = ut.host();
let mut res = ut_host.split(':'); let mut res = ut_host.split(':');
let host = match res.next() { let host = match res.next() {
Some(_) => ut.canon_host().unwrap_or(ut_host.clone()), Some(_) => ut.canon_host().unwrap_or(ut_host.clone()),

View file

@ -67,7 +67,7 @@ fn exec(filename: &str) {
let mut users = Utmpx::iter_all_records() let mut users = Utmpx::iter_all_records()
.read_from(filename) .read_from(filename)
.filter(|ut| ut.is_user_process()) .filter(|ut| ut.is_user_process())
.map(|ut| ut.user().into_owned()) .map(|ut| ut.user())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !users.is_empty() { if !users.is_empty() {

View file

@ -2,6 +2,14 @@
//! //!
//! **ONLY** support linux, macos and freebsd for the time being //! **ONLY** support linux, macos and freebsd for the time being
// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
use super::libc; use super::libc;
pub extern crate time; pub extern crate time;
use self::time::{Tm, Timespec}; use self::time::{Tm, Timespec};
@ -9,8 +17,6 @@ use self::time::{Tm, Timespec};
use ::std::io::Result as IOResult; use ::std::io::Result as IOResult;
use ::std::io::Error as IOError; use ::std::io::Error as IOError;
use ::std::ptr; use ::std::ptr;
use ::std::borrow::Cow;
use ::std::ffi::CStr;
use ::std::ffi::CString; use ::std::ffi::CString;
pub use self::ut::*; pub use self::ut::*;
@ -28,11 +34,10 @@ pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
0 0
} }
macro_rules! bytes2cow { // In case the c_char array doesn' t end with NULL
($name:expr) => ( macro_rules! chars2string {
unsafe { ($arr:expr) => (
CStr::from_ptr($name.as_ref().as_ptr()).to_string_lossy() $arr.iter().take_while(|i| **i > 0).map(|&i| i as u8 as char).collect::<String>()
}
) )
} }
@ -138,26 +143,40 @@ impl Utmpx {
self.inner.ut_pid as i32 self.inner.ut_pid as i32
} }
/// A.K.A. ut.ut_id /// A.K.A. ut.ut_id
pub fn terminal_suffix(&self) -> Cow<str> { pub fn terminal_suffix(&self) -> String {
bytes2cow!(self.inner.ut_id) chars2string!(self.inner.ut_id)
} }
/// A.K.A. ut.ut_user /// A.K.A. ut.ut_user
pub fn user(&self) -> Cow<str> { pub fn user(&self) -> String {
bytes2cow!(self.inner.ut_user) chars2string!(self.inner.ut_user)
} }
/// A.K.A. ut.ut_host /// A.K.A. ut.ut_host
pub fn host(&self) -> Cow<str> { pub fn host(&self) -> String {
bytes2cow!(self.inner.ut_host) chars2string!(self.inner.ut_host)
} }
/// A.K.A. ut.ut_line /// A.K.A. ut.ut_line
pub fn tty_device(&self) -> Cow<str> { pub fn tty_device(&self) -> String {
bytes2cow!(self.inner.ut_line) chars2string!(self.inner.ut_line)
} }
/// A.K.A. ut.ut_tv /// A.K.A. ut.ut_tv
pub fn login_time(&self) -> Tm { pub fn login_time(&self) -> Tm {
time::at(Timespec::new(self.inner.ut_tv.tv_sec as i64, time::at(Timespec::new(self.inner.ut_tv.tv_sec as i64,
self.inner.ut_tv.tv_usec as i32)) self.inner.ut_tv.tv_usec as i32))
} }
/// A.K.A. ut.ut_exit
///
/// Return (e_termination, e_exit)
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn exit_status(&self) -> (i16, i16) {
(self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit)
}
/// A.K.A. ut.ut_exit
///
/// Return (0, 0) on Non-Linux platform
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn exit_status(&self) -> (i16, i16) {
(0, 0)
}
/// Consumes the `Utmpx`, returning the underlying C struct utmpx /// Consumes the `Utmpx`, returning the underlying C struct utmpx
pub fn into_inner(self) -> utmpx { pub fn into_inner(self) -> utmpx {
self.inner self.inner
@ -170,6 +189,7 @@ impl Utmpx {
pub fn canon_host(&self) -> IOResult<String> { pub fn canon_host(&self) -> IOResult<String> {
const AI_CANONNAME: libc::c_int = 0x2; const AI_CANONNAME: libc::c_int = 0x2;
let host = self.host(); let host = self.host();
let host = host.split(':').nth(0).unwrap();
let hints = libc::addrinfo { let hints = libc::addrinfo {
ai_flags: AI_CANONNAME, ai_flags: AI_CANONNAME,
ai_family: 0, ai_family: 0,
@ -180,7 +200,7 @@ impl Utmpx {
ai_canonname: ptr::null_mut(), ai_canonname: ptr::null_mut(),
ai_next: ptr::null_mut(), ai_next: ptr::null_mut(),
}; };
let c_host = CString::new(host.as_ref()).unwrap(); let c_host = CString::new(host).unwrap();
let mut res = ptr::null_mut(); let mut res = ptr::null_mut();
let status = unsafe { let status = unsafe {
libc::getaddrinfo(c_host.as_ptr(), libc::getaddrinfo(c_host.as_ptr(),
@ -194,7 +214,7 @@ impl Utmpx {
// says Darwin 7.9.0 getaddrinfo returns 0 but sets // says Darwin 7.9.0 getaddrinfo returns 0 but sets
// res->ai_canonname to NULL. // res->ai_canonname to NULL.
let ret = if info.ai_canonname.is_null() { let ret = if info.ai_canonname.is_null() {
Ok(String::from(host.as_ref())) Ok(String::from(host))
} else { } else {
Ok(unsafe { CString::from_raw(info.ai_canonname).into_string().unwrap() }) Ok(unsafe { CString::from_raw(info.ai_canonname).into_string().unwrap() })
}; };
@ -236,9 +256,7 @@ impl Iterator for UtmpxIter {
unsafe { unsafe {
let res = getutxent(); let res = getutxent();
if !res.is_null() { if !res.is_null() {
Some(Utmpx { Some(Utmpx { inner: ptr::read(res as *const _) })
inner: ptr::read(res as *const _)
})
} else { } else {
endutxent(); endutxent();
None None