Skip to content

Commit

Permalink
refactor: move login and su to the common executable
Browse files Browse the repository at this point in the history
  • Loading branch information
llenotre committed Jul 3, 2024
1 parent cc0f660 commit 1752dab
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 77 deletions.
10 changes: 0 additions & 10 deletions login/Cargo.toml

This file was deleted.

2 changes: 1 addition & 1 deletion src/insmod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! The `insmod` command loads a module from a file.
use crate::error;
use std::env::ArgsOs;
use std::ffi::c_long;
use std::fs::File;
use std::io::Error;
use std::os::fd::AsRawFd;
use std::process::exit;
use std::ptr::null;
use utils::error;

/// The ID of the `finit_module` system call.
const FINIT_MODULE_ID: c_long = 0x15e;
Expand Down
7 changes: 2 additions & 5 deletions login/src/main.rs → src/login.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! `login` prompts a username/password to authenticate on a new session.
#![feature(never_type)]
#![feature(os_str_display)]

use std::env::ArgsOs;
use std::ffi::{CString, OsString};
use std::fmt::Formatter;
use std::os::unix::ffi::OsStrExt;
Expand Down Expand Up @@ -100,8 +98,7 @@ impl fmt::Display for LoginPrompt {
}
}

fn main() {
let _args = env::args(); // TODO Parse and use
pub fn main(_args: ArgsOs) {
let login_prompt = LoginPrompt(get_hostname());
loop {
println!();
Expand Down
2 changes: 1 addition & 1 deletion src/lsmod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! The `lsmod` command allows to list loaded kernel modules.
use crate::error;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use utils::error;

/// The path to the modules file.
const MODULES_PATH: &str = "/proc/modules";
Expand Down
22 changes: 21 additions & 1 deletion src/main-suid.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
//! Main of all commands that **require** the SUID flag.
#![feature(never_type)]
#![feature(os_str_display)]

mod login;
mod su;

use std::env;
use utils::error;

fn main() {
// TODO
let mut args = env::args_os();
let bin = args
.next()
.and_then(|s| s.into_string().ok())
.unwrap_or_else(|| {
error("mutils", "missing binary name");
});
match bin.as_str() {
"login" => login::main(args),
"su" => su::main(args),
_ => error("mutils", "invalid binary name"),
}
}
10 changes: 2 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@ mod nologin;
mod ps;
mod rmmod;

use std::process::exit;
use std::{env, fmt};

/// Writes an error to stderr, then exits.
fn error<M: fmt::Display>(bin: &str, msg: M) -> ! {
eprintln!("{bin}: error: {msg}");
exit(1);
}
use std::env;
use utils::error;

fn main() {
let mut args = env::args_os();
Expand Down
2 changes: 1 addition & 1 deletion src/rmmod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! The `rmmod` command unloads a module.
use crate::error;
use std::env::ArgsOs;
use std::ffi::c_long;
use std::ffi::CString;
use std::io::Error;
use std::os::unix::ffi::OsStrExt;
use std::process::exit;
use utils::error;

/// The ID of the `delete_module` system call.
const DELETE_MODULE_ID: c_long = 0x81;
Expand Down
72 changes: 31 additions & 41 deletions su/src/main.rs → src/su.rs
Original file line number Diff line number Diff line change
@@ -1,86 +1,76 @@
//! `su` is a command allowing to run another command with a substitute user and group ID.
use std::env;
use std::env::ArgsOs;
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
use std::process::exit;
use std::process::Command;
use utils::error;

use utils::prompt::prompt;

/// The command's arguments.
#[derive(Default)]
struct Args<'s> {
struct Args {
/// The user which executes the command. If None, using root.
user: Option<&'s str>,
user: Option<OsString>,
/// The group which executes the command. If None, using root.
group: Option<&'s str>,

group: Option<OsString>,
/// The shell to execute. If None, using the default.
shell: Option<&'s str>,

shell: Option<OsString>,
/// Arguments for the command to execute.
args: Vec<&'s str>,
args: Vec<OsString>,
}

/// Parses the given CLI arguments `args` and returns their representation in the `Args` structure.
fn parse_args(args: &Vec<String>) -> Args<'_> {
fn parse_args(args: ArgsOs) -> Args {
let mut args = args.peekable();
let mut result = Args::default();
// Iterating on arguments, skipping binary's name
let mut iter = args.iter().skip(1).peekable();

// Tells whether arguments contain initial options
let has_options = {
iter.peek()
.map(|first_arg| {
first_arg
.chars()
.peekable()
.peek()
.map(|first_char| *first_char == '-')
.unwrap_or(false)
})
.unwrap_or(false)
};

// Parsing options if present
let has_options = args
.peek()
.map(|first_arg| first_arg.as_bytes().first().cloned() == Some(b'-'))
.unwrap_or(false);
// Parse options if present
if has_options {
for arg in iter.by_ref() {
for arg in args.by_ref() {
if arg == "-" {
break;
}
// TODO
}
}

result.user = iter.next().map(String::as_str);
result.args = iter.map(String::as_str).collect();
result.user = args.next();
result.args = args.collect();
result
}

fn main() {
let args: Vec<String> = env::args().collect();
let args = parse_args(&args);
pub fn main(args: ArgsOs) {
let args = parse_args(args);

let _user = args.user.unwrap_or("root");
let _user = args.user.as_deref().unwrap_or(OsStr::new("root"));
// TODO Read user's entry
let shell = args.shell.unwrap_or("TODO");
let shell = args.shell.as_deref().unwrap_or(OsStr::new("TODO"));

let _pass = prompt("Password: ", true);
let correct = false; // TODO Check password against user's

if correct {
// TODO Change user

// Running the shell
// TODO use `execve` instead
// Run the shell
let status = Command::new(shell)
.args(args.args)
// TODO Set env
.status()
.unwrap_or_else(|_| {
eprintln!("su: Failed to run shell `{shell}`");
exit(1);
.unwrap_or_else(|e| {
error(
"su",
format_args!("Failed to run shell `{}`: {e}", shell.display()),
);
});

// Exiting with the shell's status
// Exit with the shell's status
exit(status.code().unwrap());
} else {
eprintln!("su: Authentication failure");
Expand Down
9 changes: 9 additions & 0 deletions src/utils/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
//! Features utils to several commands.
use std::fmt;
use std::process::exit;

pub mod disk;
pub mod prompt;
pub mod user;
pub mod util;

/// Writes an error to stderr, then exits.
pub fn error<M: fmt::Display>(bin: &str, msg: M) -> ! {
eprintln!("{bin}: error: {msg}");
exit(1);
}
9 changes: 0 additions & 9 deletions su/Cargo.toml

This file was deleted.

0 comments on commit 1752dab

Please sign in to comment.