Skip to content

Commit a866fcc

Browse files
committed
pinky: fix panic when outputting to /dev/full (#10562)
- fixes panic by replacing all println with writeln
1 parent 52e1bc1 commit a866fcc

2 files changed

Lines changed: 60 additions & 38 deletions

File tree

src/uu/pinky/src/platform/openbsd.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
// Specific implementation for OpenBSD: tool unsupported (utmpx not supported)
66

77
use crate::uu_app;
8+
use std::io::{Write, stdout};
89
use uucore::error::UResult;
910
use uucore::translate;
1011

1112
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
1213
let _matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
13-
println!("{}", translate!("pinky-unsupported-openbsd"));
14+
writeln!(stdout(), "{}", translate!("pinky-unsupported-openbsd"))?;
1415
Ok(())
1516
}

src/uu/pinky/src/platform/unix.rs

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use uucore::utmpx::{self, Utmpx, UtmpxRecord, time};
1717

1818
use std::io::BufReader;
1919
use std::io::prelude::*;
20+
use std::io::stdout;
2021

2122
use std::fs::File;
2223
use std::os::unix::fs::MetadataExt;
@@ -96,9 +97,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
9697
};
9798

9899
if do_short_format {
99-
pk.short_pinky();
100+
pk.short_pinky()?;
100101
} else {
101-
pk.long_pinky();
102+
pk.long_pinky()?;
102103
}
103104
Ok(())
104105
}
@@ -167,8 +168,9 @@ fn gecos_to_fullname(pw: &Passwd) -> Option<String> {
167168
}
168169

169170
impl Pinky {
170-
fn print_entry(&self, ut: &UtmpxRecord) {
171+
fn print_entry(&self, ut: &UtmpxRecord) -> UResult<()> {
171172
let mut pts_path = PathBuf::from("/dev");
173+
let mut stdout = stdout().lock();
172174
pts_path.push(ut.tty_device().as_str());
173175

174176
let mesg;
@@ -187,7 +189,7 @@ impl Pinky {
187189
last_change = 0;
188190
}
189191

190-
print!("{1:<8.0$}", utmpx::UT_NAMESIZE, ut.user());
192+
write!(stdout, "{1:<8.0$}", utmpx::UT_NAMESIZE, ut.user())?;
191193

192194
if self.include_fullname {
193195
let fullname = if let Ok(pw) = Passwd::locate(ut.user().as_ref()) {
@@ -196,23 +198,28 @@ impl Pinky {
196198
None
197199
};
198200
if let Some(fullname) = fullname {
199-
print!(" {fullname:<19.19}");
201+
write!(stdout, " {fullname:<19.19}")?;
200202
} else {
201-
print!(" {:19}", " ???");
203+
write!(stdout, " {:19}", " ???")?;
202204
}
203205
}
204206

205-
print!(" {mesg}{:<8.*}", utmpx::UT_LINESIZE, ut.tty_device());
207+
write!(
208+
stdout,
209+
" {mesg}{:<8.*}",
210+
utmpx::UT_LINESIZE,
211+
ut.tty_device()
212+
)?;
206213

207214
if self.include_idle {
208215
if last_change == 0 {
209-
print!(" {:<6}", "?????");
216+
write!(stdout, " {:<6}", "?????")?;
210217
} else {
211-
print!(" {:<6}", idle_string(last_change));
218+
write!(stdout, " {:<6}", idle_string(last_change))?;
212219
}
213220
}
214221

215-
print!(" {}", time_string(ut));
222+
write!(stdout, " {}", time_string(ut))?;
216223

217224
if self.include_where {
218225
let s: String = if self.do_lookup {
@@ -222,86 +229,100 @@ impl Pinky {
222229
};
223230

224231
if !s.is_empty() {
225-
print!(" {s}");
232+
write!(stdout, " {s}")?;
226233
}
227234
}
228235

229-
println!();
236+
writeln!(stdout)?;
237+
Ok(())
230238
}
231239

232-
fn print_heading(&self) {
233-
print!("{:<8}", translate!("pinky-column-login"));
240+
fn print_heading(&self) -> UResult<()> {
241+
let mut stdout = stdout().lock();
242+
write!(stdout, "{:<8}", translate!("pinky-column-login"))?;
234243
if self.include_fullname {
235-
print!(" {:<19}", translate!("pinky-column-name"));
244+
write!(stdout, " {:<19}", translate!("pinky-column-name"))?;
236245
}
237-
print!(" {:<9}", translate!("pinky-column-tty"));
246+
write!(stdout, " {:<9}", translate!("pinky-column-tty"))?;
238247
if self.include_idle {
239-
print!(" {:<6}", translate!("pinky-column-idle"));
248+
write!(stdout, " {:<6}", translate!("pinky-column-idle"))?;
240249
}
241-
print!(" {:<16}", translate!("pinky-column-when"));
250+
write!(stdout, " {:<16}", translate!("pinky-column-when"))?;
242251
if self.include_where {
243-
print!(" {}", translate!("pinky-column-where"));
252+
write!(stdout, " {}", translate!("pinky-column-where"))?;
244253
}
245-
println!();
254+
writeln!(stdout)?;
255+
Ok(())
246256
}
247257

248-
fn short_pinky(&self) {
258+
fn short_pinky(&self) -> UResult<()> {
249259
if self.include_heading {
250-
self.print_heading();
260+
self.print_heading()?;
251261
}
252262
for ut in Utmpx::iter_all_records() {
253263
if ut.is_user_process()
254264
&& (self.names.is_empty() || self.names.iter().any(|n| n.as_str() == ut.user()))
255265
{
256-
self.print_entry(&ut);
266+
self.print_entry(&ut)?;
257267
}
258268
}
269+
Ok(())
259270
}
260271

261-
fn long_pinky(&self) {
272+
fn long_pinky(&self) -> UResult<()> {
273+
let mut stdout = stdout().lock();
262274
for u in &self.names {
263-
print!(
275+
write!(
276+
stdout,
264277
"{} {u:<28}{} ",
265278
translate!("pinky-login-name-label"),
266279
translate!("pinky-real-life-label")
267-
);
280+
)?;
268281
if let Ok(pw) = Passwd::locate(u.as_str()) {
269282
let fullname = gecos_to_fullname(&pw).unwrap_or_default();
270283
let user_dir = pw.user_dir.unwrap_or_default();
271284
let user_shell = pw.user_shell.unwrap_or_default();
272-
println!(" {fullname}");
285+
writeln!(stdout, " {fullname}")?;
273286
if self.include_home_and_shell {
274-
print!("{} {user_dir:<29}", translate!("pinky-directory-label"));
275-
println!("{} {user_shell}", translate!("pinky-shell-label"));
287+
write!(
288+
stdout,
289+
"{} {user_dir:<29}",
290+
translate!("pinky-directory-label")
291+
)?;
292+
writeln!(stdout, "{} {user_shell}", translate!("pinky-shell-label"))?;
276293
}
277294
if self.include_project {
278295
let mut p = PathBuf::from(&user_dir);
279296
p.push(".project");
280297
if let Ok(f) = File::open(p) {
281-
print!("{} ", translate!("pinky-project-label"));
282-
read_to_console(f);
298+
write!(stdout, "{} ", translate!("pinky-project-label"))?;
299+
read_to_console(f)?;
283300
}
284301
}
285302
if self.include_plan {
286303
let mut p = PathBuf::from(&user_dir);
287304
p.push(".plan");
288305
if let Ok(f) = File::open(p) {
289-
println!("{}:", translate!("pinky-plan-label"));
290-
read_to_console(f);
306+
writeln!(stdout, "{}:", translate!("pinky-plan-label"))?;
307+
read_to_console(f)?;
291308
}
292309
}
293-
println!();
310+
writeln!(stdout)?;
294311
} else {
295-
println!(" ???");
312+
writeln!(stdout, " ???")?;
296313
}
297314
}
315+
Ok(())
298316
}
299317
}
300318

301-
fn read_to_console<F: Read>(f: F) {
319+
fn read_to_console<F: Read>(f: F) -> UResult<()> {
302320
let mut reader = BufReader::new(f);
303321
let mut iobuf = Vec::new();
322+
let mut stdout = stdout().lock();
304323
if reader.read_to_end(&mut iobuf).is_ok() {
305-
print!("{}", String::from_utf8_lossy(&iobuf));
324+
write!(stdout, "{}", String::from_utf8_lossy(&iobuf))?;
306325
}
326+
327+
Ok(())
307328
}

0 commit comments

Comments
 (0)