diff --git a/src/arch/Cargo.toml b/src/arch/Cargo.toml index ef886adc0..a075c65d7 100644 --- a/src/arch/Cargo.toml +++ b/src/arch/Cargo.toml @@ -7,9 +7,10 @@ authors = [] name = "uu_arch" path = "arch.rs" -[dependencies] -libc = "*" -uucore = { path="../uucore" } +[dependencies.uucore] +path = "../uucore" +default-features = false +features = ["utsname"] [[bin]] name = "arch" diff --git a/src/arch/arch.rs b/src/arch/arch.rs index 94dfb3a89..7c13f8024 100644 --- a/src/arch/arch.rs +++ b/src/arch/arch.rs @@ -1,54 +1,25 @@ #![crate_name = "uu_arch"] -/* - * This file is part of the uutils coreutils package. - * - * (c) Smigle00 - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate libc; +// This file is part of the uutils coreutils package. +// +// (c) Smigle00 +// (c) Jian Zeng +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +// #[macro_use] extern crate uucore; - -use std::ffi::CStr; -use std::mem::uninitialized; -use uucore::c_types::utsname; +use uucore::utsname::Uname; static SYNTAX: &'static str = ""; static SUMMARY: &'static str = "Determine architecture name for current machine."; static LONG_HELP: &'static str = ""; -struct Arch { - arch_name: String -} - -extern { - fn uname(uts: *mut utsname); -} - -unsafe fn string_from_c_str(ptr: *const i8) -> String { - String::from_utf8_lossy(CStr::from_ptr(ptr as *const std::os::raw::c_char).to_bytes()).to_string() -} - -unsafe fn get_machine_arch() -> Arch { - let mut uts: utsname = uninitialized(); - uname(&mut uts); - Arch { - arch_name: string_from_c_str(uts.machine.as_ptr() as *const i8) - } -} - pub fn uumain(args: Vec) -> i32 { new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args); - - let machine_arch = unsafe { get_machine_arch() }; - let mut output = String::new(); - output.push_str(machine_arch.arch_name.as_ref()); - println!("{}", output.trim()); - + let uts = Uname::new(); + println!("{}", uts.machine().trim()); 0 } diff --git a/src/groups/Cargo.toml b/src/groups/Cargo.toml index c468e8a08..c5132f620 100644 --- a/src/groups/Cargo.toml +++ b/src/groups/Cargo.toml @@ -7,10 +7,10 @@ authors = [] name = "uu_groups" path = "groups.rs" -[dependencies] -getopts = "*" -libc = "*" -uucore = { path="../uucore" } +[dependencies.uucore] +path = "../uucore" +default-features = false +features = ["entries"] [[bin]] name = "groups" diff --git a/src/groups/groups.rs b/src/groups/groups.rs index 2ba06c1b4..f279eb1d3 100644 --- a/src/groups/groups.rs +++ b/src/groups/groups.rs @@ -1,52 +1,35 @@ #![crate_name = "uu_groups"] -/* - * This file is part of the uutils coreutils package. - * - * (c) Alan Andrade - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - */ - -extern crate getopts; +// This file is part of the uutils coreutils package. +// +// (c) Alan Andrade +// (c) Jian Zeng +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +// +// #[macro_use] extern crate uucore; - +use uucore::entries::{Passwd, Locate, get_groups, gid2grp}; use std::io::Write; -use uucore::c_types::{get_pw_from_args, group}; -static NAME: &'static str = "groups"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[user]"; +static SUMMARY: &'static str = "display current group names"; pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "display this help menu and exit"); - opts.optflag("V", "version", "display version information and exit"); + let mut opts = new_coreopts!(SYNTAX, SUMMARY, ""); + let matches = opts.parse(args); - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m }, - Err(f) => { - show_error!("{}", f); - return 1; - } - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [USER]... - -Prints the groups a user is in to standard output.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); + if matches.free.is_empty() { + println!("{}", get_groups().unwrap().iter().map(|&g| gid2grp(g).unwrap()).collect::>().join(" ")); } else { - group(get_pw_from_args(&matches.free), true); + if let Ok(p) = Passwd::locate(matches.free[0].as_str()) { + println!("{}", p.belongs_to().iter().map(|&g| gid2grp(g).unwrap()).collect::>().join(" ")); + } else { + crash!(1, "unknown user {}", matches.free[0]); + } } 0 diff --git a/src/uname/Cargo.toml b/src/uname/Cargo.toml index 03cc6923b..de9b1ef3f 100644 --- a/src/uname/Cargo.toml +++ b/src/uname/Cargo.toml @@ -9,8 +9,11 @@ path = "uname.rs" [dependencies] getopts = "*" -libc = "*" -uucore = { path="../uucore" } + +[dependencies.uucore] +path = "../uucore" +default-features = false +features = ["utsname"] [[bin]] name = "uname" diff --git a/src/uname/uname.rs b/src/uname/uname.rs index a59d90f06..5e0b21b38 100644 --- a/src/uname/uname.rs +++ b/src/uname/uname.rs @@ -1,105 +1,80 @@ #![crate_name = "uu_uname"] -/* - * This file is part of the uutils coreutils package. - * - * (c) Joao Oliveira - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +// This file is part of the uutils coreutils package. +// +// (c) Joao Oliveira +// (c) Jian Zeng +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +// -/* last synced with: uname (GNU coreutils) 8.21 */ +// last synced with: uname (GNU coreutils) 8.21 extern crate getopts; -extern crate libc; #[macro_use] extern crate uucore; +use uucore::utsname::Uname; -use std::ffi::CStr; -use std::io::Write; -use std::mem::uninitialized; -use uucore::c_types::utsname; +static SYNTAX: &'static str = "[OPTION]..."; +static SUMMARY: &'static str = "Print certain system information. With no OPTION, same as -s."; -struct Uts { - sysname: String, - nodename: String, - release: String, - version: String, - machine: String -} - -extern { - fn uname(uts: *mut utsname); -} - -unsafe fn string_from_c_str(ptr: *const i8) -> String { - String::from_utf8_lossy(CStr::from_ptr(ptr as *const std::os::raw::c_char).to_bytes()).to_string() -} - -unsafe fn getuname() -> Uts { - let mut uts: utsname = uninitialized(); - uname(&mut uts); - Uts { - sysname: string_from_c_str(uts.sysname.as_ptr() as *const i8), - nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8), - release: string_from_c_str(uts.release.as_ptr() as *const i8), - version: string_from_c_str(uts.version.as_ptr() as *const i8), - machine: string_from_c_str(uts.machine.as_ptr() as *const i8) - } -} - -static NAME: &'static str = "uname"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +#[cfg(target_os = "linux")] +static HOST_OS: &'static str = "GNU/Linux"; +#[cfg(target_os = "windows")] +static HOST_OS: &'static str = "Windows NT"; +#[cfg(target_os = "freebsd")] +static HOST_OS: &'static str = "FreeBSD"; +#[cfg(target_os = "openbsd")] +static HOST_OS: &'static str = "OpenBSD"; +#[cfg(target_os = "macos")] +static HOST_OS: &'static str = "Darwin"; pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); + let mut opts = new_coreopts!(SYNTAX, SUMMARY, ""); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("a", "all", "Behave as though all of the options -mnrsv were specified."); - opts.optflag("m", "machine", "print the machine hardware name."); - opts.optflag("n", "nodename", "print the nodename (the nodename may be a name that the system is known by to a communications network)."); - opts.optflag("p", "processor", "print the machine processor architecture name."); - opts.optflag("r", "release", "print the operating system release."); + opts.optflag("a", + "all", + "Behave as though all of the options -mnrsv were specified."); opts.optflag("s", "sysname", "print the operating system name."); - opts.optflag("v", "version", "print the operating system version."); + opts.optflag("n", "nodename", "print the nodename (the nodename may be a name that the system is known by to a communications network)."); + opts.optflag("r", "kernel-release", "print the operating system release."); + opts.optflag("v", "kernel-version", "print the operating system version."); + opts.optflag("m", "machine", "print the machine hardware name."); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f), - }; - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTIONS]", NAME); - println!(""); - print!("{}", opts.usage("The uname utility writes symbols representing one or more system characteristics to the standard output.")); - return 0; - } - let uname = unsafe { getuname() }; + // FIXME: Unimplemented + // opts.optflag("p", "processor", "print the machine processor architecture name."); + // opts.optflag("i", "hardware-platform", "print the hardware platform."); + + opts.optflag("o", "operating-system", "print the operating system"); + let argc = args.len(); + let matches = opts.parse(args); + let uname = Uname::new(); let mut output = String::new(); - if matches.opt_present("sysname") || matches.opt_present("all") - || !matches.opts_present(&["nodename".to_owned(), "release".to_owned(), "version".to_owned(), "machine".to_owned()]) { - output.push_str(uname.sysname.as_ref()); - output.push_str(" "); + if matches.opt_present("sysname") || matches.opt_present("all") || argc == 1 { + output.push_str(uname.sysname().as_ref()); + output.push_str(" "); } if matches.opt_present("nodename") || matches.opt_present("all") { - output.push_str(uname.nodename.as_ref()); + output.push_str(uname.nodename().as_ref()); output.push_str(" "); } - if matches.opt_present("release") || matches.opt_present("all") { - output.push_str(uname.release.as_ref()); + if matches.opt_present("kernel-release") || matches.opt_present("all") { + output.push_str(uname.release().as_ref()); output.push_str(" "); } - if matches.opt_present("version") || matches.opt_present("all") { - output.push_str(uname.version.as_ref()); + if matches.opt_present("kernel-version") || matches.opt_present("all") { + output.push_str(uname.version().as_ref()); output.push_str(" "); } if matches.opt_present("machine") || matches.opt_present("all") { - output.push_str(uname.machine.as_ref()); + output.push_str(uname.machine().as_ref()); + output.push_str(" "); + } + if matches.opt_present("operating-system") || matches.opt_present("all") { + output.push_str(HOST_OS); output.push_str(" "); } println!("{}", output.trim()); diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 77676c251..9d53cae62 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -18,12 +18,12 @@ utf8 = [] encoding = ["data-encoding"] parse_time = [] utmpx = ["time", "libc"] -c_types = ["libc"] process = ["libc"] signals = [] entries = ["libc"] wide = [] -default = ["fs", "libc", "utf8", "encoding", "parse_time", "utmpx", "c_types", "process", "entries", "signals", "wide"] +utsname = ["libc"] +default = ["fs", "libc", "utf8", "utsname", "encoding", "parse_time", "utmpx", "process", "entries", "signals", "wide"] [lib] path = "lib.rs" diff --git a/src/uucore/c_types.rs b/src/uucore/c_types.rs deleted file mode 100644 index ce5b7426b..000000000 --- a/src/uucore/c_types.rs +++ /dev/null @@ -1,211 +0,0 @@ -#![allow(dead_code, non_camel_case_types)] - -extern crate libc; - -use self::libc::{ - c_char, - c_int, - uid_t, - gid_t, -}; -pub use self::libc::passwd as c_passwd; - -#[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)] -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: &[String]) -> Option { - 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::().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 _) - }; - 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 { - 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 { - let mut ngroups: c_int = 32; - let mut groups: Vec = 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, 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= 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, 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 { - 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!(""); - } - } -} diff --git a/src/uucore/lib.rs b/src/uucore/lib.rs index ff45693aa..5f19aa718 100644 --- a/src/uucore/lib.rs +++ b/src/uucore/lib.rs @@ -18,8 +18,8 @@ pub mod parse_time; #[cfg(all(unix, feature = "utmpx"))] pub mod utmpx; -#[cfg(all(unix, feature = "c_types"))] -pub mod c_types; +#[cfg(all(unix, feature = "utsname"))] +pub mod utsname; #[cfg(all(unix, feature = "entries"))] pub mod entries; #[cfg(all(unix, feature = "process"))] diff --git a/src/uucore/utsname.rs b/src/uucore/utsname.rs new file mode 100644 index 000000000..c928c6191 --- /dev/null +++ b/src/uucore/utsname.rs @@ -0,0 +1,52 @@ +// This file is part of the uutils coreutils package. +// +// (c) Jian Zeng +// +// For the full copyright and license information, please view the LICENSE file +// that was distributed with this source code. +// + +use super::libc::{uname, utsname}; +use ::std::mem; +use ::std::ffi::CStr; +use ::std::borrow::Cow; + +macro_rules! cstr2cow { + ($v:expr) => ( + unsafe { CStr::from_ptr($v.as_ref().as_ptr()).to_string_lossy() } + ) +} + +pub struct Uname { + inner: utsname, +} + +impl Uname { + pub fn new() -> Self { + unsafe { + let mut uts: utsname = mem::uninitialized(); + uname(&mut uts); + Uname { inner: uts } + } + } + + pub fn sysname(&self) -> Cow { + cstr2cow!(self.inner.sysname) + } + + pub fn nodename(&self) -> Cow { + cstr2cow!(self.inner.nodename) + } + + pub fn release(&self) -> Cow { + cstr2cow!(self.inner.release) + } + + pub fn version(&self) -> Cow { + cstr2cow!(self.inner.version) + } + + pub fn machine(&self) -> Cow { + cstr2cow!(self.inner.machine) + } +}