use super::Cmd; use crate::mode::Parser; use clap::{Arg, ArgAction, ArgMatches, Command}; use std::{error::Error, ffi::CString, io}; #[derive(Debug, Default)] pub struct MkFifo; impl Cmd for MkFifo { fn cli(&self) -> clap::Command { Command::new("mkfifo") .about("make FIFO special files") .author("Nathan Fisher") .version(env!("CARGO_PKG_VERSION")) .args([ Arg::new("mode") .help( "Set the file permission bits of the newly-created \ FIFO to the specified mode value.", ) .long_help( "Set the file permission bits of the newly-created \ FIFO to the specified mode value. The mode option-argument \ shall be the same as the mode operand defined for the \ chmod utility. In the symbolic_mode strings, the op \ characters '+' and '-' shall be interpreted relative to \ an assumed initial mode of a=rw.", ) .short('m') .long("mode") .value_name("MODE") .num_args(1), Arg::new("verbose") .help("print a diagnostic for every pipe created") .short('v') .long("verbose") .action(ArgAction::SetTrue), Arg::new("file").num_args(1..).required(true), ]) } fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box> { let Some(matches) = matches else { return Err(io::Error::new(io::ErrorKind::Other, "no input").into()); }; let mode = if let Some(m) = matches.get_one::("mode") { Parser::new(0o666).parse(m)? } else { 0o666 }; if let Some(files) = matches.get_many::("file") { for f in files { let fname = CString::new(f.as_str())?; let res = unsafe { libc::mkfifo(fname.as_ptr(), mode) }; if res != 0 { return Err(io::Error::last_os_error().into()); } if matches.get_flag("verbose") { println!( "{}: created pipe '{f}' with mode {mode:o}", self.cli().get_name() ); } } } Ok(()) } fn path(&self) -> Option { Some(crate::Path::UsrBin) } }