Skip to content

Commit 7a7839d

Browse files
committed
w: implement --container
1 parent d231109 commit 7a7839d

1 file changed

Lines changed: 46 additions & 11 deletions

File tree

src/uu/w/src/w.rs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// file that was distributed with this source code.
55

66
#[cfg(target_os = "linux")]
7-
use chrono::Datelike;
7+
use chrono::{Datelike, Local};
88
use clap::crate_version;
99
use clap::{Arg, ArgAction, Command};
1010
#[cfg(target_os = "linux")]
@@ -134,7 +134,7 @@ fn format_time(time: String) -> Result<String, chrono::format::ParseError> {
134134
t = t.drain(..time_offset).collect();
135135
}
136136
// If login time day is not current day, format like Sat16, or Fri06
137-
let current_dt = chrono::Local::now().fixed_offset();
137+
let current_dt = Local::now().fixed_offset();
138138
let dt = chrono::DateTime::parse_from_str(&t, "%Y-%m-%d %H:%M:%S%.f %:z")?;
139139

140140
if current_dt.day() == dt.day() {
@@ -171,7 +171,7 @@ fn fetch_user_info() -> Result<Vec<UserInfo>, std::io::Error> {
171171
terminal: entry.tty_device(),
172172
login_time: format_time(entry.login_time().to_string()).unwrap_or_default(),
173173
idle_time: fetch_idle_time(entry.tty_device())?,
174-
jcpu: format!("{:.2}", jcpu),
174+
jcpu: format!("{jcpu:.2}"),
175175
pcpu: fetch_pcpu_time(entry.pid()).unwrap_or_default().to_string(),
176176
command: fetch_cmdline(entry.pid()).unwrap_or_default(),
177177
};
@@ -182,6 +182,17 @@ fn fetch_user_info() -> Result<Vec<UserInfo>, std::io::Error> {
182182
Ok(user_info_list)
183183
}
184184

185+
#[cfg(target_os = "linux")]
186+
fn get_uptime_container() -> UResult<i64> {
187+
let proc_file = fs::read_to_string("/proc/1/stat")?;
188+
let proc_stat: Vec<&str> = proc_file.split_whitespace().collect();
189+
let start_time_str = proc_stat.get(21).ok_or(UptimeError::SystemUptime)?;
190+
let start_time: i64 = start_time_str
191+
.parse()
192+
.map_err(|_| UptimeError::SystemUptime)?;
193+
Ok(get_uptime(None)? + start_time / get_clock_tick())
194+
}
195+
185196
pub fn format_uptime_procps(up_secs: i64) -> UResult<String> {
186197
if up_secs < 0 {
187198
Err(UptimeError::SystemUptime)?;
@@ -199,26 +210,42 @@ pub fn format_uptime_procps(up_secs: i64) -> UResult<String> {
199210
} else {
200211
format!("{up_mins} min")
201212
};
202-
Ok(format!("{}{}", day_str, hour_min_str))
213+
Ok(format!("{day_str}{hour_min_str}"))
203214
}
204215

205216
#[inline]
206217
pub fn get_formatted_uptime_procps() -> UResult<String> {
207218
let time_str = format_uptime_procps(get_uptime(None)?)?;
208-
Ok(format!("up {}", time_str))
219+
Ok(format!("up {time_str}"))
220+
}
221+
222+
#[cfg(target_os = "linux")]
223+
#[inline]
224+
fn get_formatted_uptime_container_procps() -> UResult<String> {
225+
let time_str = format_uptime_procps(get_uptime_container()?)?;
226+
Ok(format!("up {time_str}"))
209227
}
210228

211-
fn print_uptime() {
229+
#[allow(unused_variables)]
230+
fn print_uptime(from_container: bool) {
212231
print!(" {} ", get_formatted_time());
213-
if let Ok(uptime) = get_formatted_uptime_procps() {
214-
print!("{}, ", uptime);
232+
#[cfg(target_os = "linux")]
233+
let uptime = if from_container {
234+
get_formatted_uptime_container_procps()
235+
} else {
236+
get_formatted_uptime_procps()
237+
};
238+
#[cfg(not(target_os = "linux"))]
239+
let uptime = get_formatted_uptime_procps();
240+
if let Ok(uptime) = uptime {
241+
print!("{uptime}, ");
215242
} else {
216243
print!("up ???? days ??:??, ");
217244
}
218245

219246
print!(" {}", get_formatted_nusers());
220247
if let Ok(loadavg) = get_formatted_loadavg() {
221-
print!(", {}", loadavg);
248+
print!(", {loadavg}");
222249
}
223250
println!();
224251
}
@@ -235,11 +262,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
235262
let no_header = matches.get_flag("no-header");
236263
let short = matches.get_flag("short");
237264
let old_style = matches.get_flag("old-style");
265+
let container = matches.get_flag("container");
238266

239267
match fetch_user_info() {
240268
Ok(user_info) => {
241269
if !no_header {
242-
print_uptime();
270+
print_uptime(container);
243271
if short {
244272
println!("{:<9}{:<9}{:<7}{:<}", "USER", "TTY", "IDLE", "WHAT");
245273
} else {
@@ -273,7 +301,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
273301
}
274302
}
275303
Err(e) => {
276-
eprintln!("w: failed to fetch user info: {}", e);
304+
eprintln!("w: failed to fetch user info: {e}");
277305
process::exit(1);
278306
}
279307
}
@@ -294,6 +322,13 @@ pub fn uu_app() -> Command {
294322
.help("Print help information")
295323
.action(ArgAction::Help),
296324
)
325+
.arg(
326+
Arg::new("container")
327+
.short('c')
328+
.long("container")
329+
.help("show the container uptime instead of system uptime in the header")
330+
.action(ArgAction::SetTrue),
331+
)
297332
.arg(
298333
Arg::new("no-header")
299334
.short('h')

0 commit comments

Comments
 (0)