|
| 1 | +//! Command line argument parsing for mailx |
| 2 | +
|
| 3 | +#[derive(Debug, Clone)] |
| 4 | +pub enum Mode { |
| 5 | + Send, |
| 6 | + CheckMail, |
| 7 | + HeadersOnly, |
| 8 | + Receive, |
| 9 | +} |
| 10 | + |
| 11 | +#[derive(Debug, Clone)] |
| 12 | +pub struct Args { |
| 13 | + pub mode: Mode, |
| 14 | + pub subject: Option<String>, |
| 15 | + pub addresses: Vec<String>, |
| 16 | + pub file: Option<String>, |
| 17 | + pub read_mbox: bool, |
| 18 | + pub record_to_recipient: bool, |
| 19 | + pub no_header_summary: bool, |
| 20 | + pub ignore_interrupts: bool, |
| 21 | + pub no_init: bool, |
| 22 | + pub user: Option<String>, |
| 23 | +} |
| 24 | + |
| 25 | +impl Args { |
| 26 | + pub fn parse(args: Vec<String>) -> Result<Self, String> { |
| 27 | + let mut result = Args { |
| 28 | + mode: Mode::Receive, |
| 29 | + subject: None, |
| 30 | + addresses: Vec::new(), |
| 31 | + file: None, |
| 32 | + read_mbox: false, |
| 33 | + record_to_recipient: false, |
| 34 | + no_header_summary: false, |
| 35 | + ignore_interrupts: false, |
| 36 | + no_init: false, |
| 37 | + user: None, |
| 38 | + }; |
| 39 | + |
| 40 | + let mut i = 0; |
| 41 | + let mut check_mail = false; |
| 42 | + let mut headers_only = false; |
| 43 | + |
| 44 | + while i < args.len() { |
| 45 | + let arg = &args[i]; |
| 46 | + |
| 47 | + if arg.starts_with('-') && arg.len() > 1 { |
| 48 | + let mut chars = arg[1..].chars().peekable(); |
| 49 | + |
| 50 | + while let Some(c) = chars.next() { |
| 51 | + match c { |
| 52 | + 'e' => { |
| 53 | + check_mail = true; |
| 54 | + } |
| 55 | + 'f' => { |
| 56 | + result.read_mbox = true; |
| 57 | + // Check if next argument is a file (not starting with -) |
| 58 | + if chars.peek().is_none() && i + 1 < args.len() { |
| 59 | + let next = &args[i + 1]; |
| 60 | + if !next.starts_with('-') { |
| 61 | + result.file = Some(next.clone()); |
| 62 | + i += 1; |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + 'F' => { |
| 67 | + result.record_to_recipient = true; |
| 68 | + } |
| 69 | + 'H' => { |
| 70 | + headers_only = true; |
| 71 | + } |
| 72 | + 'i' => { |
| 73 | + result.ignore_interrupts = true; |
| 74 | + } |
| 75 | + 'n' => { |
| 76 | + result.no_init = true; |
| 77 | + } |
| 78 | + 'N' => { |
| 79 | + result.no_header_summary = true; |
| 80 | + } |
| 81 | + 's' => { |
| 82 | + // Subject - get the value |
| 83 | + let rest: String = chars.collect(); |
| 84 | + if !rest.is_empty() { |
| 85 | + result.subject = Some(rest); |
| 86 | + } else if i + 1 < args.len() { |
| 87 | + i += 1; |
| 88 | + result.subject = Some(args[i].clone()); |
| 89 | + } else { |
| 90 | + return Err("option requires an argument -- s".to_string()); |
| 91 | + } |
| 92 | + break; |
| 93 | + } |
| 94 | + 'u' => { |
| 95 | + // User mailbox |
| 96 | + let rest: String = chars.collect(); |
| 97 | + if !rest.is_empty() { |
| 98 | + result.user = Some(rest); |
| 99 | + } else if i + 1 < args.len() { |
| 100 | + i += 1; |
| 101 | + result.user = Some(args[i].clone()); |
| 102 | + } else { |
| 103 | + return Err("option requires an argument -- u".to_string()); |
| 104 | + } |
| 105 | + break; |
| 106 | + } |
| 107 | + _ => { |
| 108 | + return Err(format!("illegal option -- {}", c)); |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + } else { |
| 113 | + // Non-option argument - must be an address |
| 114 | + result.addresses.push(arg.clone()); |
| 115 | + } |
| 116 | + |
| 117 | + i += 1; |
| 118 | + } |
| 119 | + |
| 120 | + // Determine mode |
| 121 | + if check_mail { |
| 122 | + result.mode = Mode::CheckMail; |
| 123 | + } else if headers_only { |
| 124 | + result.mode = Mode::HeadersOnly; |
| 125 | + } else if !result.addresses.is_empty() { |
| 126 | + result.mode = Mode::Send; |
| 127 | + } else { |
| 128 | + result.mode = Mode::Receive; |
| 129 | + } |
| 130 | + |
| 131 | + // If -u was specified, set up to read that user's mailbox |
| 132 | + if let Some(ref user) = result.user { |
| 133 | + result.file = Some(format!("/var/mail/{}", user)); |
| 134 | + } |
| 135 | + |
| 136 | + Ok(result) |
| 137 | + } |
| 138 | +} |
0 commit comments