coreutils/uptime/uptime.rs

192 lines
4.9 KiB
Rust
Raw Normal View History

#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];
/*
* This file is part of the uutils coreutils package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/* last synced with: cat (GNU coreutils) 8.13 */
#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];
extern crate getopts;
use std::os;
use std::cast::transmute;
use std::io::{print,File};
2014-03-25 16:16:38 +00:00
use std::libc::{time_t,c_double,c_int,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;
#[path = "../common/util.rs"] mod util;
#[path = "../common/c_types.rs"] mod c_types;
#[path = "../common/utmpx.rs"] mod utmpx;
static NAME: &'static str = "uptime";
extern {
fn time(timep: *time_t) -> time_t;
fn localtime(timep: *time_t) -> *c_tm;
fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;
fn getutxent() -> *c_utmp;
fn setutxent();
fn endutxent();
fn utmpxname(file: *c_char) -> c_int;
}
fn main() {
let args = os::args();
let program = args[0].clone();
let opts = ~[
getopts::optflag("v", "version", "output version information and exit"),
getopts::optflag("h", "help", "display this help and exit"),
];
let matches = match getopts::getopts(args.tail(), opts) {
Ok(m) => m,
Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
};
if matches.opt_present("version") {
println!("uptime 1.0.0");
return;
}
if matches.opt_present("help") || matches.free.len() > 0 {
println!("Usage:");
println!(" {0:s} [OPTION]", program);
println!("");
print(getopts::usage("Print the current time, the length of time the system has been up,\n\
the number of users on the system, and the average number of jobs\n\
in the run queue over the last 1, 5 and 15 minutes.", opts));
return;
}
print_time();
let (boot_time, user_count) = process_utmpx();
let upsecs = get_uptime(boot_time) / 100;
print_uptime(upsecs);
print_nusers(user_count);
print_loadavg();
}
fn print_loadavg() {
let avg: [c_double, ..3] = [0.0, ..3];
let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };
if loads == -1 {
print!("\n");
}
else {
print!("load average: ")
for n in range(0, loads) {
print!("{:.2f}{}", avg[n], if n == loads - 1 { "\n" }
else { ", " } );
}
}
}
fn process_utmpx() -> (Option<time_t>, uint) {
DEFAULT_FILE.with_c_str(|filename| {
unsafe {
utmpxname(filename);
}
});
let mut nusers = 0;
let mut boot_time = None;
unsafe {
setutxent();
loop {
let line = getutxent();
if line == null() {
break;
}
match (*line).ut_type {
USER_PROCESS => nusers += 1,
BOOT_TIME => {
let t = (*line).ut_tv;
if t.tv_sec > 0 {
boot_time = Some(t.tv_sec);
}
},
_ => continue
}
}
endutxent();
}
(boot_time, nusers)
}
fn print_nusers(nusers: uint) {
if nusers == 1 {
print!("1 user, ");
} else if nusers > 1 {
print!("{} users, ", nusers);
}
}
fn print_time() {
let local_time = unsafe { *localtime(&time(null())) };
if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
local_time.tm_sec >= 0 {
print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
local_time.tm_min, local_time.tm_sec);
}
}
fn get_uptime(boot_time: Option<time_t>) -> i64 {
2014-03-25 15:59:29 +00:00
let proc_uptime = File::open(&Path::new("/proc/uptime"))
.read_to_str();
let uptime_text = match proc_uptime {
Ok(s) => s,
_ => return match boot_time {
Some(t) => {
let now = unsafe { time(null()) };
(now - t) * 100 // Return in ms
},
_ => -1
}
2014-03-25 15:59:29 +00:00
};
2014-03-25 15:59:29 +00:00
match uptime_text.words().next() {
Some(s) => match from_str(s.replace(".","")) {
Some(n) => n,
None => -1
},
None => -1
2014-03-25 15:59:29 +00:00
}
}
fn print_uptime(upsecs: i64) {
let updays = upsecs / 86400;
let uphours = (upsecs - (updays * 86400)) / 3600;
let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
2014-03-25 15:59:29 +00:00
if updays == 1 {
print!("up {:1d} day, {:2d}:{:02d}, ", updays, uphours, upmins);
}
else if updays > 1 {
print!("up {:1d} days, {:2d}:{:02d}, ", updays, uphours, upmins);
}
else {
print!("up {:2d}:{:02d}, ", uphours, upmins);
}
}