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

Split utility files into separate library.

Everything in src/common has been moved to src/uucore. This is defined
as a Cargo library, instead of directly included. This gives us
flexibility to make the library an external crate in the future.

Fixes #717.
This commit is contained in:
Joseph Crail 2015-11-23 20:00:51 -05:00 committed by Roy Ivy III
parent 67b07eaaa9
commit 6095dfee66
10 changed files with 1120 additions and 0 deletions

11
src/uucore/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "uucore"
version = "0.0.1"
authors = []
[dependencies]
libc = "*"
time = "*"
[lib]
path = "lib.rs"

240
src/uucore/c_types.rs Normal file
View file

@ -0,0 +1,240 @@
#![allow(dead_code, non_camel_case_types, raw_pointer_derive)]
extern crate libc;
use self::libc::{
c_char,
c_int,
uid_t,
gid_t,
};
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
use self::libc::time_t;
#[cfg(target_os = "macos")]
use self::libc::int32_t;
use self::libc::getgroups;
use std::ffi::{CStr, CString};
use std::io::{Error, Write};
use std::iter::repeat;
use std::vec::Vec;
use std::ptr::{null_mut, read};
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct c_passwd {
pub pw_name: *const c_char, /* user name */
pub pw_passwd: *const c_char, /* user name */
pub pw_uid: uid_t, /* user uid */
pub pw_gid: gid_t, /* user gid */
pub pw_change: time_t,
pub pw_class: *const c_char,
pub pw_gecos: *const c_char,
pub pw_dir: *const c_char,
pub pw_shell: *const c_char,
pub pw_expire: time_t
}
#[cfg(target_os = "linux")]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct c_passwd {
pub pw_name: *const c_char, /* user name */
pub pw_passwd: *const c_char, /* user name */
pub pw_uid: uid_t, /* user uid */
pub pw_gid: gid_t, /* user gid */
pub pw_gecos: *const c_char,
pub pw_dir: *const c_char,
pub pw_shell: *const c_char,
}
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[repr(C)]
pub struct utsname {
pub sysname: [c_char; 256],
pub nodename: [c_char; 256],
pub release: [c_char; 256],
pub version: [c_char; 256],
pub machine: [c_char; 256]
}
#[cfg(target_os = "linux")]
#[repr(C)]
pub struct utsname {
pub sysname: [c_char; 65],
pub nodename: [c_char; 65],
pub release: [c_char; 65],
pub version: [c_char; 65],
pub machine: [c_char; 65],
pub domainame: [c_char; 65]
}
#[repr(C)]
pub struct c_group {
pub gr_name: *const c_char, // group name
pub gr_passwd: *const c_char, // password
pub gr_gid: gid_t, // group id
pub gr_mem: *const *const c_char, // member list
}
#[repr(C)]
pub struct c_tm {
pub tm_sec: c_int, /* seconds */
pub tm_min: c_int, /* minutes */
pub tm_hour: c_int, /* hours */
pub tm_mday: c_int, /* day of the month */
pub tm_mon: c_int, /* month */
pub tm_year: c_int, /* year */
pub tm_wday: c_int, /* day of the week */
pub tm_yday: c_int, /* day in the year */
pub tm_isdst: c_int /* daylight saving time */
}
extern {
pub fn getpwuid(uid: uid_t) -> *const c_passwd;
pub fn getpwnam(login: *const c_char) -> *const c_passwd;
pub fn getgrgid(gid: gid_t) -> *const c_group;
pub fn getgrnam(name: *const c_char) -> *const c_group;
pub fn getgrouplist(name: *const c_char,
gid: gid_t,
groups: *mut gid_t,
ngroups: *mut c_int) -> c_int;
}
#[cfg(target_os = "macos")]
extern {
pub fn getgroupcount(name: *const c_char, gid: gid_t) -> int32_t;
}
pub fn get_pw_from_args(free: &Vec<String>) -> Option<c_passwd> {
if free.len() == 1 {
let username = &free[0][..];
// Passed user as id
if username.chars().all(|c| c.is_digit(10)) {
let id = username.parse::<u32>().unwrap();
let pw_pointer = unsafe { getpwuid(id as uid_t) };
if !pw_pointer.is_null() {
Some(unsafe { read(pw_pointer) })
} else {
crash!(1, "{}: no such user", username);
}
// Passed the username as a string
} else {
let pw_pointer = unsafe {
let cstr = CString::new(username).unwrap();
getpwnam(cstr.as_bytes_with_nul().as_ptr() as *const i8)
};
if !pw_pointer.is_null() {
Some(unsafe { read(pw_pointer) })
} else {
crash!(1, "{}: no such user", username);
}
}
} else {
None
}
}
pub fn get_group(groupname: &str) -> Option<c_group> {
let group = if groupname.chars().all(|c| c.is_digit(10)) {
unsafe { getgrgid(groupname.parse().unwrap()) }
} else {
unsafe {
let cstr = CString::new(groupname).unwrap();
getgrnam(cstr.as_bytes_with_nul().as_ptr() as *const c_char)
}
};
if !group.is_null() {
Some(unsafe { read(group) })
}
else {
None
}
}
pub fn get_group_list(name: *const c_char, gid: gid_t) -> Vec<gid_t> {
let mut ngroups: c_int = 32;
let mut groups: Vec<gid_t> = Vec::with_capacity(ngroups as usize);
if unsafe { get_group_list_internal(name, gid, groups.as_mut_ptr(), &mut ngroups) } == -1 {
groups.reserve(ngroups as usize);
unsafe { get_group_list_internal(name, gid, groups.as_mut_ptr(), &mut ngroups); }
} else {
groups.truncate(ngroups as usize);
}
unsafe { groups.set_len(ngroups as usize); }
groups
}
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
#[inline(always)]
unsafe fn get_group_list_internal(name: *const c_char, gid: gid_t, groups: *mut gid_t, grcnt: *mut c_int) -> c_int {
getgrouplist(name, gid, groups, grcnt)
}
#[cfg(target_os = "macos")]
unsafe fn get_group_list_internal(name: *const c_char, gid: gid_t, groups: *mut gid_t, grcnt: *mut c_int) -> c_int {
let ngroups = getgroupcount(name, gid);
let oldsize = *grcnt;
*grcnt = ngroups;
if oldsize >= ngroups {
getgrouplist(name, gid, groups, grcnt);
0
} else {
-1
}
}
pub fn get_groups() -> Result<Vec<gid_t>, i32> {
let ngroups = unsafe { getgroups(0, null_mut()) };
if ngroups == -1 {
return Err(Error::last_os_error().raw_os_error().unwrap())
}
let mut groups : Vec<gid_t>= repeat(0).take(ngroups as usize).collect();
let ngroups = unsafe { getgroups(ngroups, groups.as_mut_ptr()) };
if ngroups == -1 {
Err(Error::last_os_error().raw_os_error().unwrap())
} else {
groups.truncate(ngroups as usize);
Ok(groups)
}
}
pub fn group(possible_pw: Option<c_passwd>, nflag: bool) {
let groups = match possible_pw {
Some(pw) => Ok(get_group_list(pw.pw_name, pw.pw_gid)),
None => get_groups(),
};
match groups {
Err(errno) =>
crash!(1, "failed to get group list (errno={})", errno),
Ok(groups) => {
for &g in groups.iter() {
if nflag {
let group = unsafe { getgrgid(g) };
if !group.is_null() {
let name = unsafe {
let gname = read(group).gr_name;
let bytes= CStr::from_ptr(gname).to_bytes();
String::from_utf8_lossy(bytes).to_string()
};
print!("{} ", name);
}
} else {
print!("{} ", g);
}
}
println!("");
}
}
}

144
src/uucore/fs.rs Normal file
View file

@ -0,0 +1,144 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Joseph Crail <jbcrail@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};
pub trait UUPathExt {
fn uu_exists(&self) -> bool;
fn uu_is_file(&self) -> bool;
fn uu_is_dir(&self) -> bool;
fn uu_metadata(&self) -> Result<fs::Metadata>;
}
impl UUPathExt for Path {
fn uu_exists(&self) -> bool {
fs::metadata(self).is_ok()
}
fn uu_is_file(&self) -> bool {
fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
}
fn uu_is_dir(&self) -> bool {
fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
}
fn uu_metadata(&self) -> Result<fs::Metadata> {
fs::metadata(self)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
None,
Normal,
Existing,
Missing,
}
fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
const MAX_LINKS_FOLLOWED: u32 = 255;
let mut followed = 0;
let mut result = original.as_ref().to_path_buf();
loop {
if followed == MAX_LINKS_FOLLOWED {
return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
}
match fs::metadata(&result) {
Err(e) => return Err(e),
Ok(ref m) if !m.file_type().is_symlink() => break,
Ok(..) => {
followed += 1;
match fs::read_link(&result) {
Ok(path) => {
result.pop();
result.push(path);
},
Err(e) => {
return Err(e);
}
}
}
}
}
Ok(result)
}
pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
// Create an absolute path
let original = original.as_ref();
let original = if original.is_absolute() {
original.to_path_buf()
} else {
env::current_dir().unwrap().join(original)
};
let mut result = PathBuf::new();
let mut parts = vec!();
// Split path by directory separator; add prefix (Windows-only) and root
// directory to final path buffer; add remaining parts to temporary
// vector for canonicalization.
for part in original.components() {
match part {
Component::Prefix(_) | Component::RootDir => {
result.push(part.as_os_str());
},
Component::CurDir => {},
Component::ParentDir => {
parts.pop();
},
Component::Normal(_) => {
parts.push(part.as_os_str());
}
}
}
// Resolve the symlinks where possible
if parts.len() > 0 {
for part in parts[..parts.len()-1].iter() {
result.push(part);
if can_mode == CanonicalizeMode::None {
continue;
}
match resolve(&result) {
Err(e) => match can_mode {
CanonicalizeMode::Missing => continue,
_ => return Err(e)
},
Ok(path) => {
result.pop();
result.push(path);
}
}
}
result.push(parts.last().unwrap());
match resolve(&result) {
Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
Ok(path) => {
result.pop();
result.push(path);
}
}
}
Ok(result)
}

14
src/uucore/lib.rs Normal file
View file

@ -0,0 +1,14 @@
extern crate libc;
extern crate time;
#[macro_use]
mod macros;
pub mod c_types;
pub mod fs;
pub mod parse_time;
pub mod process;
#[cfg(unix)] pub mod signals;
#[cfg(unix)] pub mod utmpx;
#[cfg(windows)] pub mod wide;

220
src/uucore/macros.rs Normal file
View file

@ -0,0 +1,220 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Arcterus <arcterus@mail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#[macro_export]
macro_rules! show_error(
($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", module_path!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
})
);
#[macro_export]
macro_rules! show_warning(
($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", module_path!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
})
);
#[macro_export]
macro_rules! show_info(
($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: ", module_path!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
})
);
#[macro_export]
macro_rules! eprint(
($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+))
);
#[macro_export]
macro_rules! eprintln(
($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+))
);
#[macro_export]
macro_rules! crash(
($exitcode:expr, $($args:tt)+) => ({
show_error!($($args)+);
::std::process::exit($exitcode)
})
);
#[macro_export]
macro_rules! exit(
($exitcode:expr) => ({
::std::process::exit($exitcode)
})
);
#[macro_export]
macro_rules! crash_if_err(
($exitcode:expr, $exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => crash!($exitcode, "{}", f),
}
)
);
#[macro_export]
macro_rules! pipe_crash_if_err(
($exitcode:expr, $exp:expr) => (
match $exp {
Ok(_) => (),
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
()
} else {
crash!($exitcode, "{}", f)
}
},
}
)
);
#[macro_export]
macro_rules! return_if_err(
($exitcode:expr, $exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => {
show_error!("{}", f);
return $exitcode;
}
}
)
);
// XXX: should the pipe_* macros return an Err just to show the write failed?
#[macro_export]
macro_rules! pipe_print(
($($args:tt)+) => (
match write!(&mut ::std::io::stdout(), $($args)+) {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
)
);
#[macro_export]
macro_rules! pipe_println(
($($args:tt)+) => (
match writeln!(&mut ::std::io::stdout(), $($args)+) {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
)
);
#[macro_export]
macro_rules! pipe_write(
($fd:expr, $($args:tt)+) => (
match write!($fd, $($args)+) {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
)
);
#[macro_export]
macro_rules! pipe_writeln(
($fd:expr, $($args:tt)+) => (
match writeln!($fd, $($args)+) {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
)
);
#[macro_export]
macro_rules! pipe_flush(
() => (
match ::std::io::stdout().flush() {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
);
($fd:expr) => (
match $fd.flush() {
Ok(_) => true,
Err(f) => {
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false
} else {
panic!("{}", f)
}
}
}
)
);
#[macro_export]
macro_rules! safe_write(
($fd:expr, $($args:tt)+) => (
match write!($fd, $($args)+) {
Ok(_) => {}
Err(f) => panic!(f.to_string())
}
)
);
#[macro_export]
macro_rules! safe_writeln(
($fd:expr, $($args:tt)+) => (
match writeln!($fd, $($args)+) {
Ok(_) => {}
Err(f) => panic!(f.to_string())
}
)
);
#[macro_export]
macro_rules! safe_unwrap(
($exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => crash!(1, "{}", f.to_string())
}
)
);

35
src/uucore/parse_time.rs Normal file
View file

@ -0,0 +1,35 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Arcterus <arcterus@mail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
pub fn from_str(string: &str) -> Result<f64, String> {
let len = string.len();
if len == 0 {
return Err("empty string".to_string())
}
let slice = &string[..len - 1];
let (numstr, times) = match string.chars().next_back().unwrap() {
's' | 'S' => (slice, 1),
'm' | 'M' => (slice, 60),
'h' | 'H' => (slice, 60 * 60),
'd' | 'D' => (slice, 60 * 60 * 24),
val => {
if !val.is_alphabetic() {
(string, 1)
} else if string == "inf" || string == "infinity" {
("inf", 1)
} else {
return Err(format!("invalid time interval '{}'", string))
}
}
};
match numstr.parse::<f64>() {
Ok(m) => Ok(m * times as f64),
Err(e) => Err(format!("invalid time interval '{}': {}", string, e))
}
}

140
src/uucore/process.rs Normal file
View file

@ -0,0 +1,140 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Maciej Dziardziel <fiedzia@gmail.com>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/
extern crate libc;
use libc::{c_int, pid_t};
use std::fmt;
use std::io;
use std::process::Child;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
use time::{Duration, get_time};
use std::time::Duration as StdDuration;
// This is basically sys::unix::process::ExitStatus
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum ExitStatus {
Code(i32),
Signal(i32),
}
impl ExitStatus {
fn from_status(status: c_int) -> ExitStatus {
if status & 0x7F != 0 { // WIFSIGNALED(status)
ExitStatus::Signal(status & 0x7F)
} else {
ExitStatus::Code(status & 0xFF00 >> 8)
}
}
pub fn success(&self) -> bool {
match *self {
ExitStatus::Code(code) => code == 0,
_ => false,
}
}
pub fn code(&self) -> Option<i32> {
match *self {
ExitStatus::Code(code) => Some(code),
_ => None,
}
}
pub fn signal(&self) -> Option<i32> {
match *self {
ExitStatus::Signal(code) => Some(code),
_ => None,
}
}
}
impl fmt::Display for ExitStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ExitStatus::Code(code) => write!(f, "exit code: {}", code),
ExitStatus::Signal(code) => write!(f, "exit code: {}", code),
}
}
}
/// Missing methods for Child objects
pub trait ChildExt {
/// Send a signal to a Child process.
fn send_signal(&mut self, signal: usize) -> io::Result<()>;
/// Wait for a process to finish or return after the specified duration.
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>>;
}
impl ChildExt for Child {
fn send_signal(&mut self, signal: usize) -> io::Result<()> {
if unsafe { libc::kill(self.id() as pid_t,
signal as i32) } != 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>> {
// The result will be written to that Option, protected by a Mutex
// Then the Condvar will be signaled
let state = Arc::new((
Mutex::new(Option::None::<io::Result<ExitStatus>>),
Condvar::new(),
));
// Start the waiting thread
let state_th = state.clone();
let pid_th = self.id();
thread::spawn(move || {
let &(ref lock_th, ref cvar_th) = &*state_th;
// Child::wait() would need a &mut to self, can't use that...
// use waitpid() directly, with our own ExitStatus
let mut status: c_int = 0;
let r = unsafe { libc::waitpid(pid_th as i32, &mut status, 0) };
// Fill the Option and notify on the Condvar
let mut exitstatus_th = lock_th.lock().unwrap();
if r != pid_th as c_int {
*exitstatus_th = Some(Err(io::Error::last_os_error()));
} else {
let s = ExitStatus::from_status(status);
*exitstatus_th = Some(Ok(s));
}
cvar_th.notify_one();
});
// Main thread waits
let &(ref lock, ref cvar) = &*state;
let mut exitstatus = lock.lock().unwrap();
// Condvar::wait_timeout_ms() can wake too soon, in this case wait again
let target = get_time() +
Duration::seconds(timeout as i64) +
Duration::nanoseconds((timeout * 1.0e-6) as i64);
while exitstatus.is_none() {
let now = get_time();
if now >= target {
return Ok(None)
}
let ms = (target - get_time()).num_milliseconds() as u32;
exitstatus = cvar.wait_timeout(exitstatus, StdDuration::new(0, ms*1000)).unwrap().0;
}
// Turn Option<Result<ExitStatus>> into Result<Option<ExitStatus>>
match exitstatus.take() {
Some(r) => match r {
Ok(s) => Ok(Some(s)),
Err(e) => Err(e),
},
None => panic!(),
}
}
}

156
src/uucore/signals.rs Normal file
View file

@ -0,0 +1,156 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Maciej Dziardziel <fiedzia@gmail.com>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/
pub static DEFAULT_SIGNAL:usize= 15;
pub struct Signal<'a> { pub name:&'a str, pub value: usize}
/*
Linux Programmer's Manual
1 HUP 2 INT 3 QUIT 4 ILL 5 TRAP 6 ABRT 7 BUS
8 FPE 9 KILL 10 USR1 11 SEGV 12 USR2 13 PIPE 14 ALRM
15 TERM 16 STKFLT 17 CHLD 18 CONT 19 STOP 20 TSTP 21 TTIN
22 TTOU 23 URG 24 XCPU 25 XFSZ 26 VTALRM 27 PROF 28 WINCH
29 POLL 30 PWR 31 SYS
*/
#[cfg(target_os = "linux")]
pub static ALL_SIGNALS:[Signal<'static>; 31] = [
Signal{ name: "HUP", value:1 },
Signal{ name: "INT", value:2 },
Signal{ name: "QUIT", value:3 },
Signal{ name: "ILL", value:4 },
Signal{ name: "TRAP", value:5 },
Signal{ name: "ABRT", value:6 },
Signal{ name: "BUS", value:7 },
Signal{ name: "FPE", value:8 },
Signal{ name: "KILL", value:9 },
Signal{ name: "USR1", value:10 },
Signal{ name: "SEGV", value:11 },
Signal{ name: "USR2", value:12 },
Signal{ name: "PIPE", value:13 },
Signal{ name: "ALRM", value:14 },
Signal{ name: "TERM", value:15 },
Signal{ name: "STKFLT", value:16 },
Signal{ name: "CHLD", value:17 },
Signal{ name: "CONT", value:18 },
Signal{ name: "STOP", value:19 },
Signal{ name: "TSTP", value:20 },
Signal{ name: "TTIN", value:21 },
Signal{ name: "TTOU", value:22 },
Signal{ name: "URG", value:23 },
Signal{ name: "XCPU", value:24 },
Signal{ name: "XFSZ", value:25 },
Signal{ name: "VTALRM", value:26 },
Signal{ name: "PROF", value:27 },
Signal{ name: "WINCH", value:28 },
Signal{ name: "POLL", value:29 },
Signal{ name: "PWR", value:30 },
Signal{ name: "SYS", value:31 },
];
/*
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html
No Name Default Action Description
1 SIGHUP terminate process terminal line hangup
2 SIGINT terminate process interrupt program
3 SIGQUIT create core image quit program
4 SIGILL create core image illegal instruction
5 SIGTRAP create core image trace trap
6 SIGABRT create core image abort program (formerly SIGIOT)
7 SIGEMT create core image emulate instruction executed
8 SIGFPE create core image floating-point exception
9 SIGKILL terminate process kill program
10 SIGBUS create core image bus error
11 SIGSEGV create core image segmentation violation
12 SIGSYS create core image non-existent system call invoked
13 SIGPIPE terminate process write on a pipe with no reader
14 SIGALRM terminate process real-time timer expired
15 SIGTERM terminate process software termination signal
16 SIGURG discard signal urgent condition present on socket
17 SIGSTOP stop process stop (cannot be caught or ignored)
18 SIGTSTP stop process stop signal generated from keyboard
19 SIGCONT discard signal continue after stop
20 SIGCHLD discard signal child status has changed
21 SIGTTIN stop process background read attempted from control terminal
22 SIGTTOU stop process background write attempted to control terminal
23 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2))
24 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2))
25 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2))
26 SIGVTALRM terminate process virtual time alarm (see setitimer(2))
27 SIGPROF terminate process profiling timer alarm (see setitimer(2))
28 SIGWINCH discard signal Window size change
29 SIGINFO discard signal status request from keyboard
30 SIGUSR1 terminate process User defined signal 1
31 SIGUSR2 terminate process User defined signal 2
*/
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
pub static ALL_SIGNALS:[Signal<'static>; 31] = [
Signal{ name: "HUP", value:1 },
Signal{ name: "INT", value:2 },
Signal{ name: "QUIT", value:3 },
Signal{ name: "ILL", value:4 },
Signal{ name: "TRAP", value:5 },
Signal{ name: "ABRT", value:6 },
Signal{ name: "EMT", value:7 },
Signal{ name: "FPE", value:8 },
Signal{ name: "KILL", value:9 },
Signal{ name: "BUS", value:10 },
Signal{ name: "SEGV", value:11 },
Signal{ name: "SYS", value:12 },
Signal{ name: "PIPE", value:13 },
Signal{ name: "ALRM", value:14 },
Signal{ name: "TERM", value:15 },
Signal{ name: "URG", value:16 },
Signal{ name: "STOP", value:17 },
Signal{ name: "TSTP", value:18 },
Signal{ name: "CONT", value:19 },
Signal{ name: "CHLD", value:20 },
Signal{ name: "TTIN", value:21 },
Signal{ name: "TTOU", value:22 },
Signal{ name: "IO", value:23 },
Signal{ name: "XCPU", value:24 },
Signal{ name: "XFSZ", value:25 },
Signal{ name: "VTALRM", value:26 },
Signal{ name: "PROF", value:27 },
Signal{ name: "WINCH", value:28 },
Signal{ name: "INFO", value:29 },
Signal{ name: "USR1", value:30 },
Signal{ name: "USR2", value:31 },
];
pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
if signal_name_or_value == "0" {
return Some(0);
}
for signal in ALL_SIGNALS.iter() {
let long_name = format!("SIG{}", signal.name);
if signal.name == signal_name_or_value || (signal_name_or_value == signal.value.to_string()) || (long_name == signal_name_or_value) {
return Some(signal.value);
}
}
None
}
#[inline(always)]
pub fn is_signal(num: usize) -> bool {
num < ALL_SIGNALS.len()
}

125
src/uucore/utmpx.rs Normal file
View file

@ -0,0 +1,125 @@
#![allow(dead_code, non_camel_case_types)]
extern crate libc;
pub use self::utmpx::{DEFAULT_FILE,USER_PROCESS,BOOT_TIME,c_utmp};
#[cfg(target_os = "linux")]
mod utmpx {
use super::libc;
pub static DEFAULT_FILE: &'static str = "/var/run/utmp";
pub const UT_LINESIZE: usize = 32;
pub const UT_NAMESIZE: usize = 32;
pub const UT_IDSIZE: usize = 4;
pub const UT_HOSTSIZE: usize = 256;
pub const EMPTY: libc::c_short = 0;
pub const RUN_LVL: libc::c_short = 1;
pub const BOOT_TIME: libc::c_short = 2;
pub const NEW_TIME: libc::c_short = 3;
pub const OLD_TIME: libc::c_short = 4;
pub const INIT_PROCESS: libc::c_short = 5;
pub const LOGIN_PROCESS: libc::c_short = 6;
pub const USER_PROCESS: libc::c_short = 7;
pub const DEAD_PROCESS: libc::c_short = 8;
pub const ACCOUNTING: libc::c_short = 9;
#[repr(C)]
pub struct c_exit_status {
pub e_termination: libc::c_short,
pub e_exit: libc::c_short,
}
#[repr(C)]
pub struct c_utmp {
pub ut_type: libc::c_short,
pub ut_pid: libc::pid_t,
pub ut_line: [libc::c_char; UT_LINESIZE],
pub ut_id: [libc::c_char; UT_IDSIZE],
pub ut_user: [libc::c_char; UT_NAMESIZE],
pub ut_host: [libc::c_char; UT_HOSTSIZE],
pub ut_exit: c_exit_status,
pub ut_session: libc::c_long,
pub ut_tv: libc::timeval,
pub ut_addr_v6: [libc::int32_t; 4],
pub __unused: [libc::c_char; 20],
}
}
#[cfg(target_os = "macos")]
mod utmpx {
use super::libc;
pub static DEFAULT_FILE: &'static str = "/var/run/utmpx";
pub const UT_LINESIZE: usize = 32;
pub const UT_NAMESIZE: usize = 256;
pub const UT_IDSIZE: usize = 4;
pub const UT_HOSTSIZE: usize = 256;
pub const EMPTY: libc::c_short = 0;
pub const RUN_LVL: libc::c_short = 1;
pub const BOOT_TIME: libc::c_short = 2;
pub const OLD_TIME: libc::c_short = 3;
pub const NEW_TIME: libc::c_short = 4;
pub const INIT_PROCESS: libc::c_short = 5;
pub const LOGIN_PROCESS: libc::c_short = 6;
pub const USER_PROCESS: libc::c_short = 7;
pub const DEAD_PROCESS: libc::c_short = 8;
pub const ACCOUNTING: libc::c_short = 9;
#[repr(C)]
pub struct c_exit_status {
pub e_termination: libc::c_short,
pub e_exit: libc::c_short,
}
#[repr(C)]
pub struct c_utmp {
pub ut_user: [libc::c_char; UT_NAMESIZE],
pub ut_id: [libc::c_char; UT_IDSIZE],
pub ut_line: [libc::c_char; UT_LINESIZE],
pub ut_pid: libc::pid_t,
pub ut_type: libc::c_short,
pub ut_tv: libc::timeval,
pub ut_host: [libc::c_char; UT_HOSTSIZE],
pub __unused: [libc::c_char; 16]
}
}
#[cfg(target_os = "freebsd")]
mod utmpx {
use super::libc;
pub static DEFAULT_FILE : &'static str = "";
pub const UT_LINESIZE : usize = 16;
pub const UT_NAMESIZE : usize = 32;
pub const UT_IDSIZE : usize = 8;
pub const UT_HOSTSIZE : usize = 128;
pub const EMPTY : libc::c_short = 0;
pub const BOOT_TIME : libc::c_short = 1;
pub const OLD_TIME : libc::c_short = 2;
pub const NEW_TIME : libc::c_short = 3;
pub const USER_PROCESS : libc::c_short = 4;
pub const INIT_PROCESS : libc::c_short = 5;
pub const LOGIN_PROCESS : libc::c_short = 6;
pub const DEAD_PROCESS : libc::c_short = 7;
pub const SHUTDOWN_TIME : libc::c_short = 8;
#[repr(C)]
pub struct c_utmp {
pub ut_type : libc::c_short,
pub ut_tv : libc::timeval,
pub ut_id : [libc::c_char; UT_IDSIZE],
pub ut_pid : libc::pid_t,
pub ut_user : [libc::c_char; UT_NAMESIZE],
pub ut_line : [libc::c_char; UT_LINESIZE],
pub ut_host : [libc::c_char; UT_HOSTSIZE],
pub ut_spare : [libc::c_char; 64],
}
}

35
src/uucore/wide.rs Normal file
View file

@ -0,0 +1,35 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Peter Atashian <retep998@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use std::ffi::{OsStr, OsString};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
pub trait ToWide {
fn to_wide(&self) -> Vec<u16>;
fn to_wide_null(&self) -> Vec<u16>;
}
impl<T> ToWide for T where T: AsRef<OsStr> {
fn to_wide(&self) -> Vec<u16> {
self.as_ref().encode_wide().collect()
}
fn to_wide_null(&self) -> Vec<u16> {
self.as_ref().encode_wide().chain(Some(0)).collect()
}
}
pub trait FromWide {
fn from_wide(wide: &[u16]) -> Self;
fn from_wide_null(wide: &[u16]) -> Self;
}
impl FromWide for String {
fn from_wide(wide: &[u16]) -> String {
OsString::from_wide(wide).to_string_lossy().into_owned()
}
fn from_wide_null(wide: &[u16]) -> String {
let len = wide.iter().take_while(|&&c| c != 0).count();
OsString::from_wide(&wide[..len]).to_string_lossy().into_owned()
}
}