Added doc comments
This commit is contained in:
parent
b401aaad47
commit
c6e162ebc8
1
src/chmod/mod.rs
Normal file
1
src/chmod/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
//! Functions for parsing and managing permissions
|
@ -1,44 +1,45 @@
|
||||
use clap::ArgMatches;
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
pub mod base32;
|
||||
pub mod base64;
|
||||
pub mod basename;
|
||||
pub mod bootstrap;
|
||||
mod base32;
|
||||
mod base64;
|
||||
mod basename;
|
||||
mod bootstrap;
|
||||
mod cat;
|
||||
mod chmod;
|
||||
pub mod clear;
|
||||
mod clear;
|
||||
mod cp;
|
||||
pub mod cut;
|
||||
mod cut;
|
||||
mod date;
|
||||
mod dd;
|
||||
pub mod dirname;
|
||||
pub mod echo;
|
||||
pub mod factor;
|
||||
pub mod r#false;
|
||||
pub mod fold;
|
||||
mod dirname;
|
||||
mod echo;
|
||||
mod factor;
|
||||
mod r#false;
|
||||
mod fold;
|
||||
mod getty;
|
||||
pub mod groups;
|
||||
pub mod head;
|
||||
pub mod hostname;
|
||||
pub mod link;
|
||||
mod groups;
|
||||
mod head;
|
||||
mod hostname;
|
||||
mod link;
|
||||
mod ln;
|
||||
mod ls;
|
||||
pub mod mountpoint;
|
||||
mod mountpoint;
|
||||
mod mv;
|
||||
pub mod nologin;
|
||||
pub mod nproc;
|
||||
mod nologin;
|
||||
mod nproc;
|
||||
mod pwd;
|
||||
pub mod rev;
|
||||
mod rev;
|
||||
mod rm;
|
||||
mod rmdir;
|
||||
pub mod shitbox;
|
||||
pub mod sleep;
|
||||
pub mod sync;
|
||||
pub mod r#true;
|
||||
pub mod which;
|
||||
pub mod whoami;
|
||||
pub mod yes;
|
||||
mod shitbox;
|
||||
mod sleep;
|
||||
mod sync;
|
||||
mod r#true;
|
||||
mod unlink;
|
||||
mod which;
|
||||
mod whoami;
|
||||
mod yes;
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub use {
|
||||
@ -46,15 +47,24 @@ pub use {
|
||||
bootstrap::Bootstrap, clear::Clear, cut::Cut, dirname::Dirname, echo::Echo, factor::Factor,
|
||||
fold::Fold, groups::Groups, head::Head, link::Link, mountpoint::Mountpoint, nologin::Nologin,
|
||||
nproc::Nproc, r#false::False, r#true::True, rev::Rev, shitbox::Shitbox, sleep::Sleep,
|
||||
sync::Sync as SyncCmd, which::Which, whoami::Whoami, yes::Yes,
|
||||
sync::Sync as SyncCmd, unlink::Unlink, which::Which, whoami::Whoami, yes::Yes,
|
||||
};
|
||||
|
||||
/// Defines a command or applet, it's cli interface, and it's installation directory
|
||||
/// relative to the binary
|
||||
pub trait Cmd: fmt::Debug + Sync {
|
||||
/// Defines the cli of the applet
|
||||
fn cli(&self) -> clap::Command;
|
||||
/// Runs the applet
|
||||
/// # Errors
|
||||
/// Bubbles up any errors to the caller
|
||||
fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box<dyn Error>>;
|
||||
/// Returns the path relative to the binary where the link to this applet
|
||||
/// will be installed
|
||||
fn path(&self) -> Option<crate::Path>;
|
||||
}
|
||||
|
||||
/// Parses a string into a command to run
|
||||
#[must_use]
|
||||
#[allow(clippy::box_default)]
|
||||
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||
@ -81,6 +91,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||
"sleep" => Some(Box::new(Sleep::default())),
|
||||
"sync" => Some(Box::new(SyncCmd::default())),
|
||||
"true" => Some(Box::new(True::default())),
|
||||
"unlink" => Some(Box::new(Unlink::default())),
|
||||
"which" => Some(Box::new(Which::default())),
|
||||
"whoami" => Some(Box::new(Whoami::default())),
|
||||
"yes" => Some(Box::new(Yes::default())),
|
||||
@ -88,7 +99,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub static COMMANDS: [&str; 26] = [
|
||||
pub static COMMANDS: [&str; 27] = [
|
||||
"base32",
|
||||
"base64",
|
||||
"basename",
|
||||
@ -112,6 +123,7 @@ pub static COMMANDS: [&str; 26] = [
|
||||
"shitbox",
|
||||
"sync",
|
||||
"true",
|
||||
"unlink",
|
||||
"which",
|
||||
"whoami",
|
||||
"yes",
|
||||
|
50
src/cmd/unlink/mod.rs
Normal file
50
src/cmd/unlink/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
use std::{io, ffi::CString, process};
|
||||
use super::Cmd;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Unlink;
|
||||
|
||||
impl Cmd for Unlink {
|
||||
fn cli(&self) -> clap::Command {
|
||||
Command::new("unlink")
|
||||
.about("call the unlink function to remove the specified file")
|
||||
.author("Nathan Fisher")
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.args([
|
||||
Arg::new("verbose")
|
||||
.help("display user feedback upon success")
|
||||
.short('v')
|
||||
.long("verbose")
|
||||
.action(ArgAction::SetTrue),
|
||||
Arg::new("file")
|
||||
.value_name("FILE")
|
||||
.required(true)
|
||||
.num_args(1..),
|
||||
])
|
||||
}
|
||||
|
||||
fn run(&self, matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let Some(matches) = matches else {
|
||||
return Err(Box::new(io::Error::new(io::ErrorKind::Other, "no input")));
|
||||
};
|
||||
if let Some(files) = matches.get_many::<String>("file") {
|
||||
for f in files {
|
||||
let fname = CString::new(f.as_str())?;
|
||||
let ret = unsafe { libc::unlink(fname.as_ptr()) };
|
||||
if matches.get_flag("verbose") && ret == 0 {
|
||||
println!("unlink: {f}");
|
||||
} else if ret != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
eprintln!("unlink: cannot unlink {f}: {err}");
|
||||
process::exit(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path(&self) -> Option<crate::Path> {
|
||||
Some(crate::Path::UsrBin)
|
||||
}
|
||||
}
|
14
src/lib.rs
14
src/lib.rs
@ -1,17 +1,22 @@
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
use std::{env, path::PathBuf, process, string::ToString};
|
||||
|
||||
pub mod cmd;
|
||||
pub mod chmod;
|
||||
mod cmd;
|
||||
pub use cmd::Cmd;
|
||||
pub mod math;
|
||||
/// User and group related functionality
|
||||
pub mod pw;
|
||||
|
||||
/// Defines the location relative to the binary where a command will be installed
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Path {
|
||||
/// /bin
|
||||
Bin,
|
||||
/// /sbin
|
||||
Sbin,
|
||||
/// /usr/bin
|
||||
UsrBin,
|
||||
/// /usr/sbin
|
||||
UsrSbin,
|
||||
}
|
||||
|
||||
@ -27,6 +32,7 @@ impl Path {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the basename of the command as it was called
|
||||
#[must_use]
|
||||
pub fn progname() -> Option<String> {
|
||||
env::args()
|
||||
@ -39,6 +45,9 @@ pub fn progname() -> Option<String> {
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Returns the path to the binary, if called as "shitbox". Used in the bootstrap
|
||||
/// applet to find the binary location in order to install it into it's permanent
|
||||
/// location
|
||||
#[must_use]
|
||||
pub fn progpath() -> Option<PathBuf> {
|
||||
match progname() {
|
||||
@ -47,6 +56,7 @@ pub fn progpath() -> Option<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The entry point of the program
|
||||
pub fn run() {
|
||||
if let Some(progname) = progname() {
|
||||
if let Some(command) = cmd::get(&progname) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
//! Math related functions not included in std
|
||||
#[must_use]
|
||||
pub fn is_prime(num: u64) -> bool {
|
||||
match num {
|
@ -1,9 +1,13 @@
|
||||
//! Wraps certain libc functions around groups and users
|
||||
use std::{
|
||||
error::Error,
|
||||
ffi::{c_int, CStr, CString},
|
||||
io, num,
|
||||
};
|
||||
|
||||
/// Gets the current username of this process
|
||||
/// # Errors
|
||||
/// The user name must be valid utf8
|
||||
pub fn get_username<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
let user = unsafe {
|
||||
let uid = libc::getuid();
|
||||
@ -14,6 +18,9 @@ pub fn get_username<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
user.to_str()
|
||||
}
|
||||
|
||||
/// Gets the current effective user name of this process
|
||||
/// # Errors
|
||||
/// The user name must be valid utf8
|
||||
pub fn get_eusername<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
let user = unsafe {
|
||||
let uid = libc::geteuid();
|
||||
@ -24,6 +31,7 @@ pub fn get_eusername<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
user.to_str()
|
||||
}
|
||||
|
||||
/// Gets the uid associated with the given name
|
||||
#[must_use]
|
||||
pub fn get_uid_for_name(name: &str) -> Option<u32> {
|
||||
let Ok(user) = CString::new(name.as_bytes()) else { return None };
|
||||
@ -37,6 +45,7 @@ pub fn get_uid_for_name(name: &str) -> Option<u32> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the gid for the main group associated with the given user
|
||||
#[must_use]
|
||||
pub fn get_pgid_for_name(name: &str) -> Option<u32> {
|
||||
let Ok(user) = CString::new(name.as_bytes()) else { return None };
|
||||
@ -50,6 +59,9 @@ pub fn get_pgid_for_name(name: &str) -> Option<u32> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the main group name for the current process
|
||||
/// # Errors
|
||||
/// The name must be valid utf8
|
||||
pub fn get_grpname<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
let group = unsafe {
|
||||
let gid = libc::getgid();
|
||||
@ -60,6 +72,9 @@ pub fn get_grpname<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
group.to_str()
|
||||
}
|
||||
|
||||
/// Gets the effective group for the current process
|
||||
/// # Errors
|
||||
/// The name must be valid utf8
|
||||
pub fn get_egrpname<'a>() -> Result<&'a str, std::str::Utf8Error> {
|
||||
let group = unsafe {
|
||||
let gid = libc::getegid();
|
||||
|
Loading…
Reference in New Issue
Block a user