86 lines
1.9 KiB
Rust
Executable File
86 lines
1.9 KiB
Rust
Executable File
#!/usr/bin/env runrs
|
|
|
|
//! ```cargo
|
|
//! [dependencies]
|
|
//! rand = "0.8.5"
|
|
//! clap = { version = "4.1.8", features = ["derive"] }
|
|
//! ```
|
|
|
|
use clap::{arg, Parser};
|
|
use rand::RngCore;
|
|
use std::process::exit;
|
|
|
|
const ENGLISH_LOWER: &'static str = "abcdefghijklmnopqrstuvwxyz";
|
|
const ENGLISH_UPPER: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
const NUMBER: &'static str = "0123456789";
|
|
const SPECIAL: &'static str = ".,/<>;:[]{}-=_+!@#$%^&*()~";
|
|
|
|
#[derive(Parser, Debug)]
|
|
#[command(author, version, about, long_about = None, bin_name = "makepassword.rs")]
|
|
struct Args {
|
|
/// Password length
|
|
#[arg(short, long)]
|
|
length: Option<u32>,
|
|
|
|
/// Chars (e.g. a - lower case alphabet, A - UPPER CASE ALPHABET, n|N|# - number, * - special)
|
|
#[arg(short, long)]
|
|
chars: Option<String>,
|
|
}
|
|
|
|
fn main() {
|
|
let args: Args = Args::parse();
|
|
|
|
let mut a = false;
|
|
let mut A = false;
|
|
let mut n = false;
|
|
let mut s = false;
|
|
match args.chars {
|
|
None => {
|
|
a = true;
|
|
A = true;
|
|
n = true;
|
|
}
|
|
Some(chars) => {
|
|
for c in chars.chars() {
|
|
match c {
|
|
'a' => a = true,
|
|
'A' => A = true,
|
|
'n' | 'N' | '#' => n = true,
|
|
'*' => s = true,
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if !a && !A && !n && !s {
|
|
eprintln!("No chars selected.");
|
|
exit(1);
|
|
}
|
|
|
|
let mut str = "".to_string();
|
|
if a {
|
|
str += ENGLISH_LOWER;
|
|
}
|
|
if A {
|
|
str += ENGLISH_UPPER;
|
|
}
|
|
if n {
|
|
str += NUMBER;
|
|
}
|
|
if s {
|
|
str += SPECIAL;
|
|
}
|
|
let chars = str.chars().collect::<Vec<_>>();
|
|
|
|
let mut rng = rand::thread_rng();
|
|
let mut pass = String::new();
|
|
|
|
let len = args.length.unwrap_or(18);
|
|
for _ in 0..len {
|
|
pass.push(chars[rng.next_u32() as usize % chars.len()]);
|
|
}
|
|
|
|
println!("{}", pass);
|
|
}
|