diff --git a/README.md b/README.md index 9e73663..e7251f7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # mqrs -`mqrs` is a small cli application to handle different kinds of message -queues. +`mqrs` is a small cli application to handle POSIX message queues. ## Install `mqrs` For information about how to build, install and run `mqrs` please see @@ -9,8 +8,8 @@ For information about how to build, install and run `mqrs` please see ## Using `mqrs` Depending on which backend you want to use there are different subsets of subcommands. Following backends are supported: -- `posix`: Use POSIX message queues -- `sysv`: Use SysV IPC message queues +- `posix`: Uses POSIX message queues +- `sysv`: Uses SysV IPC message queues If a command is clearly distinguishable from all the others, it does not have to be completed further. @@ -67,16 +66,6 @@ queue. Following optional arguments are supported: - `-m`, `--mode`: Permissions (octal) to create the queue with. Default: 0644. -#### Print information about a message queue -Use the `info` command to print further information about a message -queue. Exactly of the following arguments is mandatory: -- `-i`, `--id id`: Id of the queue -- `-k`, `--key key`: Key of the queue - -#### List all message queues -Use the `list` command to print a list of all message queues. No -further arguments are supported. - #### Delete a message queue Use the `unlink` command to delete a message queue. This can either be done by providing a `key` or an `id` of the queue: diff --git a/mqrs.1 b/mqrs.1 index 45116a5..eb7b912 100644 --- a/mqrs.1 +++ b/mqrs.1 @@ -41,7 +41,7 @@ The POSIX backend supports six commands: and .B recv . -.SS posix create [FLAGS] [OPTIONS] \fI\fP +.SS create [FLAGS] [OPTIONS] \fI\fP Create a new POSIX message queue. .TP 8 .SS ARGS @@ -72,7 +72,7 @@ Message size in bytes .B \-m, \-\-mode \fI\fP Permissions (octal) to create the queue with .RE -.SS posix help [SUBCOMMAND] +.SS help [SUBCOMMAND] Prints this message or the help of the given subcommand. .TP 8 .SS ARGS @@ -81,7 +81,7 @@ Prints this message or the help of the given subcommand. .B \fI\fP Show help for \fISUBCOMMAND\fP .RE -.SS posix info [FLAGS] \fI\fP +.SS info [FLAGS] \fI\fP Print further information about an existing message queue. .TP 8 .SS ARGS @@ -100,7 +100,7 @@ Prints help information .B \-v, \-\-verbose Produce verbose output .RE -.SS posix list [FLAGS] +.SS list [FLAGS] Print a list of all existing POSIX message queues. .TP 8 .SS FLAGS @@ -115,7 +115,7 @@ Produce verbose output .B \-a, \-\-all Print all available information .RE -.SS posix recv [FLAGS] [OPTIONS] \fI\fP +.SS recv [FLAGS] [OPTIONS] \fI\fP Receive and print one or more messages message from a message queue. .TP 8 .SS ARGS @@ -153,7 +153,7 @@ Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S") .B \-o, \-\-timeout \fI\fP Timeout as for example in "5h 23min 42ms" .RE -.SS posix send [FLAGS] [OPTIONS] \fI\fP \fI\fP +.SS send [FLAGS] [OPTIONS] \fI\fP \fI\fP Send a message to a message queue. .TP 8 .SS ARGS @@ -191,7 +191,7 @@ Set a different priority than default, priority >= 0 [default: 0] .B \-o, \-\-timeout \fI\fP Timeout as for example in "5h 23min 42ms" .RE -.SS posix unlink [FLAGS] \fI\fP +.SS unlink [FLAGS] \fI\fP Delete an existing POSIX message queue. .TP 8 .SS ARGS @@ -211,16 +211,12 @@ Prints help information Produce verbose output .RE .SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS -The SysV IPC backend supports four commands: +The SysV IPC backend supports two commands: .B create\ -, -.B info\ -, -.B list and .B unlink\ . -.SS sysv create [FLAGS] [OPTIONS] \fI\fP +.SS create [FLAGS] [OPTIONS] \fI\fP Create a new SysV IPC message queue. .TP 8 .SS ARGS @@ -245,51 +241,7 @@ Produce verbose output .B \-m, \-\-mode \fI\fP Permissions (octal) to create the queue with (default: 0644) .RE -.SS sysv help [SUBCOMMAND] -Prints this message or the help of the given subcommand. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\fP -Show help for \fISUBCOMMAND\fP -.RE -.SS sysv info [FLAGS] [OPTIONS] -Print further information about an existing message queue. Exactly of -the OPTION arguments is mandatory. -.TP 8 -.SS FLAGS -.RS -.TP 8 -.B \-h, \-\-help -Prints help information -.TP 8 -.B \-v, \-\-verbose -Produce verbose output -.RE -.TP 8 -.SS OPTIONS -.RS -.TP 8 -.B \-i, \-\-id \fI\fP -Id of the queue -.TP 8 -.B \-k, \-\-key \fI\fP -Key of the queue -.RE -.SS sysv list [FLAGS] -Print a list of all existing SysV IPC message queues. -.TP 8 -.SS FLAGS -.RS -.TP 8 -.B \-h, \-\-help -Prints help information -.TP 8 -.B \-v, \-\-verbose -Produce verbose output -.RE -.SS sysv unlink [FLAGS] [OPTIONS] +.SS unlink [FLAGS] [OPTIONS] Delete an existing SysV IPC message queue. It is mandatory to pass exactly one OPTION. .TP 8 diff --git a/src/main.rs b/src/main.rs index b2dc94b..5e4db83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,8 +25,6 @@ enum PosixCommand { #[derive(Clap, Debug)] enum SysvCommand { Create(sysv::Create), - Info(sysv::Info), - List(sysv::List), Unlink(sysv::Unlink), } @@ -71,8 +69,6 @@ fn main() -> Result<()> { }, Backend::Sysv(s) => match s { SysvCommand::Create(c) => c.run()?, - SysvCommand::Info(i) => i.run()?, - SysvCommand::List(l) => l.run()?, SysvCommand::Unlink(u) => u.run()?, }, } diff --git a/src/posix/info.rs b/src/posix/info.rs index abf9641..0fd1e76 100644 --- a/src/posix/info.rs +++ b/src/posix/info.rs @@ -7,7 +7,7 @@ use posixmq::PosixMq; pub struct Info { /// Name of the queue #[clap(value_name = "QUEUE")] - queue: String, + pub queue: String, } impl Info { diff --git a/src/posix/list.rs b/src/posix/list.rs index f9c02b6..54c031a 100644 --- a/src/posix/list.rs +++ b/src/posix/list.rs @@ -4,7 +4,7 @@ use clap::Clap; use log::warn; use std::{fs, os::unix::fs::PermissionsExt}; -/// Print a list of existing message queues +/// Print information about an existing message queue #[derive(Clap, Debug)] pub struct List { /// Show all parameters diff --git a/src/posix/recv.rs b/src/posix/recv.rs index 6d83cef..0b8563a 100644 --- a/src/posix/recv.rs +++ b/src/posix/recv.rs @@ -11,22 +11,22 @@ use std::str; pub struct Recv { /// Do not block #[clap(short, long)] - non_blocking: bool, + pub non_blocking: bool, /// Print messages as they are received #[clap(short, long)] - follow: bool, + pub follow: bool, /// Print a timestamp before each message #[clap(short, long)] - timestamp: bool, + pub timestamp: bool, /// Timeout, example "5h 23min 42ms" #[clap(short = 'o', long, conflicts_with = "deadline")] - timeout: Option, + pub timeout: Option, /// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S") #[clap(short, long, conflicts_with = "timeout")] - deadline: Option, + pub deadline: Option, /// Name of the queue #[clap(value_name = "QUEUE")] - queue: String, + pub queue: String, } fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) { diff --git a/src/posix/send.rs b/src/posix/send.rs index d6feefc..917679b 100644 --- a/src/posix/send.rs +++ b/src/posix/send.rs @@ -9,22 +9,22 @@ use log::info; pub struct Send { /// Set a different priority, priority >= 0 #[clap(short, long, default_value = "0")] - priority: u32, + pub priority: u32, /// Do not block #[clap(short, long)] - non_blocking: bool, + pub non_blocking: bool, /// Timeout, example "5h 23min 42ms" #[clap(short = 'o', long, conflicts_with = "deadline")] - timeout: Option, + pub timeout: Option, /// Deadline until messages are sent (format: "%Y-%m-%d %H:%M:%S") #[clap(short, long, conflicts_with = "timeout")] - deadline: Option, + pub deadline: Option, /// Name of the queue #[clap(value_name = "QUEUE")] - queue: String, + pub queue: String, /// Message to be sent to the queue #[clap(value_name = "MESSAGE")] - msg: String, + pub msg: String, } impl Send { diff --git a/src/sysv.rs b/src/sysv.rs index 7270e78..91ee1a5 100644 --- a/src/sysv.rs +++ b/src/sysv.rs @@ -1,9 +1,5 @@ mod create; -mod info; -mod list; mod unlink; pub use create::Create; -pub use info::Info; -pub use list::List; pub use unlink::Unlink; diff --git a/src/sysv/info.rs b/src/sysv/info.rs deleted file mode 100644 index 42d9fac..0000000 --- a/src/sysv/info.rs +++ /dev/null @@ -1,53 +0,0 @@ -use anyhow::Result; -use clap::Clap; -use std::{ - fs::File, - io::{BufRead, BufReader}, -}; - -/// Print information about an existing message queue -#[derive(Clap, Debug)] -pub struct Info { - /// Id of the queue - #[clap(short, long, required_unless_present_any = &["key"], conflicts_with = "key")] - id: Option, - /// Key of the queue - #[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")] - key: Option, -} - -fn print_line(line: &str) { - for field in line.split_whitespace().collect::>() { - print!("{0: <10}", field); - } - - println!(); -} - -impl Info { - pub fn run(&self) -> Result<()> { - let mut lines = BufReader::new(File::open("/proc/sysvipc/msg")?).lines(); - - print_line(&lines.nth(0).unwrap_or(Ok(String::new()))?); - - for line in lines { - let line = line?; - - if let Some(id) = self.id { - if id == line.split_whitespace().collect::>()[1].parse::()? { - print_line(&line); - - break; - } - } else if let Some(key) = self.key { - if key == line.split_whitespace().collect::>()[0].parse::()? { - print_line(&line); - - break; - } - } - } - - Ok(()) - } -} diff --git a/src/sysv/list.rs b/src/sysv/list.rs deleted file mode 100644 index 9f66951..0000000 --- a/src/sysv/list.rs +++ /dev/null @@ -1,24 +0,0 @@ -use anyhow::Result; -use clap::Clap; -use std::{ - fs::File, - io::{BufRead, BufReader}, -}; - -/// Print a list of existing message queues -#[derive(Clap, Debug)] -pub struct List {} - -impl List { - pub fn run(&self) -> Result<()> { - for line in BufReader::new(File::open("/proc/sysvipc/msg")?).lines() { - for field in line?.split_whitespace().collect::>() { - print!("{0: <10}", field); - } - - println!(); - } - - Ok(()) - } -} diff --git a/src/sysv/unlink.rs b/src/sysv/unlink.rs index 8723d20..277edb6 100644 --- a/src/sysv/unlink.rs +++ b/src/sysv/unlink.rs @@ -7,15 +7,15 @@ use log::info; pub struct Unlink { /// Id of the queue #[clap( - short, long, + short, required_unless_present_any = &["key"], conflicts_with = "key" )] - id: Option, + pub id: Option, /// Key of the queue - #[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")] - key: Option, + #[clap(long, short, required_unless_present_any = &["id"], conflicts_with = "id")] + pub key: Option, } impl Unlink { @@ -25,11 +25,9 @@ impl Unlink { info!("Removed message queue with id: {}", id); } else if let Some(key) = self.key { - let id = sysvmq::id_from_key(key)?; + sysvmq::unlink_key(key)?; - sysvmq::unlink_id(id)?; - - info!("Removed message queue key: {} (id: {})", key, id); + info!("Removed message queue key: {}", key); } Ok(()) diff --git a/sysvmq/src/lib.rs b/sysvmq/src/lib.rs index 298a48e..bb2c21d 100644 --- a/sysvmq/src/lib.rs +++ b/sysvmq/src/lib.rs @@ -1,15 +1,21 @@ use libc::{ - msgctl, msgget, msginfo, msqid_ds, IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_NOWAIT, IPC_PRIVATE, - IPC_RMID, IPC_SET, IPC_STAT, MSG_COPY, MSG_EXCEPT, MSG_INFO, MSG_NOERROR, MSG_STAT, + msgctl, msgget, msqid_ds, IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_NOWAIT, IPC_PRIVATE, IPC_RMID, + IPC_SET, IPC_STAT, MSG_COPY, MSG_EXCEPT, MSG_INFO, MSG_NOERROR, MSG_STAT, }; use nix::errno::{errno, Errno}; -use std::{marker::PhantomData, mem::MaybeUninit, ptr}; +use std::{marker::PhantomData, num::ParseIntError, ptr}; use thiserror::Error; #[derive(Debug, Error)] pub enum SysvMqError { #[error("SysV message queue: {0}")] ErrnoError(&'static str), + #[error("No message queue found with key {0}")] + KeyNotFound(i32), + #[error("IO Error: {0}")] + IoError(#[from] std::io::Error), + #[error("Parse Error: {0}")] + ParserError(#[from] ParseIntError), } /// IPC bit flags @@ -63,63 +69,10 @@ pub fn unlink_id(id: i32) -> Result<(), SysvMqError> { } } -pub fn id_from_key(key: i32) -> Result { +pub fn unlink_key(key: i32) -> Result<(), SysvMqError> { let id = unsafe { msgget(key, 0) }; - match id { - -1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())), - id => Ok(id), - } -} - -pub fn ipc_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl( - id, - ControlCommands::IpcInfo as i32, - msginfo.as_mut_ptr() as *mut msqid_ds, - ); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) -} - -pub fn stat_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl(id, ControlCommands::Stat as i32, msginfo.as_mut_ptr()); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) -} - -pub fn msg_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl( - id, - ControlCommands::MsgInfo as i32, - msginfo.as_mut_ptr() as *mut msqid_ds, - ); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) + unlink_id(id) } pub struct SysvMq {