Compare commits

...

6 commits

Author SHA1 Message Date
finga ecd5ee5a36 Add functions to print information about SysV mqs
Not needed yet but maybe useful..
2021-07-09 00:31:51 +02:00
finga 9666e0788d Implement info command for SysV IPC mqs
The `list` command was refactored a little bit as well and the man
page and readme were updated.
2021-07-09 00:29:13 +02:00
finga 4c82d41f8e Implement printing a list of SysV IPC mqs
What could be improved is when printing the information to use a
better human readable format.

As usual the readme and the man page are both updated.
2021-07-08 14:46:10 +02:00
finga f4796e7da6 Refactor sysvmq::unlink_* and check for error
Use `sysvmq::id_from_key(key)` to receive the id of a queue identified
with `key`. Here an error check is added as well. Adapt
`Sysv::Unlink::run()` to comply with that change.
2021-07-08 14:20:53 +02:00
finga 8d127d840e Minor fixes in readme and clap help 2021-07-08 14:14:25 +02:00
finga f726083759 Remove unneccessary pub declarations 2021-07-08 14:13:59 +02:00
12 changed files with 237 additions and 44 deletions

View file

@ -1,5 +1,6 @@
# mqrs
`mqrs` is a small cli application to handle POSIX message queues.
`mqrs` is a small cli application to handle different kinds of message
queues.
## Install `mqrs`
For information about how to build, install and run `mqrs` please see
@ -8,8 +9,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`: Uses POSIX message queues
- `sysv`: Uses SysV IPC message queues
- `posix`: Use POSIX message queues
- `sysv`: Use SysV IPC message queues
If a command is clearly distinguishable from all the others,
it does not have to be completed further.
@ -66,6 +67,16 @@ 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:

68
mqrs.1
View file

@ -41,7 +41,7 @@ The POSIX backend supports six commands:
and
.B recv
.
.SS create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
.SS posix create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
Create a new POSIX message queue.
.TP 8
.SS ARGS
@ -72,7 +72,7 @@ Message size in bytes
.B \-m, \-\-mode \fI<mode>\fP
Permissions (octal) to create the queue with
.RE
.SS help [SUBCOMMAND]
.SS posix 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<SUBCOMMAND>\fP
Show help for \fISUBCOMMAND\fP
.RE
.SS info [FLAGS] \fI<QUEUE>\fP
.SS posix info [FLAGS] \fI<QUEUE>\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 list [FLAGS]
.SS posix 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 recv [FLAGS] [OPTIONS] \fI<QUEUE>\fP
.SS posix recv [FLAGS] [OPTIONS] \fI<QUEUE>\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<timeout>\fP
Timeout as for example in "5h 23min 42ms"
.RE
.SS send [FLAGS] [OPTIONS] \fI<QUEUE>\fP \fI<MESSAGE>\fP
.SS posix send [FLAGS] [OPTIONS] \fI<QUEUE>\fP \fI<MESSAGE>\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<timeout>\fP
Timeout as for example in "5h 23min 42ms"
.RE
.SS unlink [FLAGS] \fI<QUEUE>\fP
.SS posix unlink [FLAGS] \fI<QUEUE>\fP
Delete an existing POSIX message queue.
.TP 8
.SS ARGS
@ -211,12 +211,16 @@ Prints help information
Produce verbose output
.RE
.SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS
The SysV IPC backend supports two commands:
The SysV IPC backend supports four commands:
.B create\
,
.B info\
,
.B list
and
.B unlink\
.
.SS create [FLAGS] [OPTIONS] \fI<KEY>\fP
.SS sysv create [FLAGS] [OPTIONS] \fI<KEY>\fP
Create a new SysV IPC message queue.
.TP 8
.SS ARGS
@ -241,7 +245,51 @@ Produce verbose output
.B \-m, \-\-mode \fI<mode>\fP
Permissions (octal) to create the queue with (default: 0644)
.RE
.SS unlink [FLAGS] [OPTIONS]
.SS sysv help [SUBCOMMAND]
Prints this message or the help of the given subcommand.
.TP 8
.SS ARGS
.RS
.TP 8
.B \fI<SUBCOMMAND>\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<id>\fP
Id of the queue
.TP 8
.B \-k, \-\-key \fI<key>\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]
Delete an existing SysV IPC message queue. It is mandatory to pass
exactly one OPTION.
.TP 8

View file

@ -25,6 +25,8 @@ enum PosixCommand {
#[derive(Clap, Debug)]
enum SysvCommand {
Create(sysv::Create),
Info(sysv::Info),
List(sysv::List),
Unlink(sysv::Unlink),
}
@ -69,6 +71,8 @@ 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()?,
},
}

View file

@ -7,7 +7,7 @@ use posixmq::PosixMq;
pub struct Info {
/// Name of the queue
#[clap(value_name = "QUEUE")]
pub queue: String,
queue: String,
}
impl Info {

View file

@ -4,7 +4,7 @@ use clap::Clap;
use log::warn;
use std::{fs, os::unix::fs::PermissionsExt};
/// Print information about an existing message queue
/// Print a list of existing message queues
#[derive(Clap, Debug)]
pub struct List {
/// Show all parameters

View file

@ -11,22 +11,22 @@ use std::str;
pub struct Recv {
/// Do not block
#[clap(short, long)]
pub non_blocking: bool,
non_blocking: bool,
/// Print messages as they are received
#[clap(short, long)]
pub follow: bool,
follow: bool,
/// Print a timestamp before each message
#[clap(short, long)]
pub timestamp: bool,
timestamp: bool,
/// Timeout, example "5h 23min 42ms"
#[clap(short = 'o', long, conflicts_with = "deadline")]
pub timeout: Option<String>,
timeout: Option<String>,
/// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
#[clap(short, long, conflicts_with = "timeout")]
pub deadline: Option<String>,
deadline: Option<String>,
/// Name of the queue
#[clap(value_name = "QUEUE")]
pub queue: String,
queue: String,
}
fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) {

View file

@ -9,22 +9,22 @@ use log::info;
pub struct Send {
/// Set a different priority, priority >= 0
#[clap(short, long, default_value = "0")]
pub priority: u32,
priority: u32,
/// Do not block
#[clap(short, long)]
pub non_blocking: bool,
non_blocking: bool,
/// Timeout, example "5h 23min 42ms"
#[clap(short = 'o', long, conflicts_with = "deadline")]
pub timeout: Option<String>,
timeout: Option<String>,
/// Deadline until messages are sent (format: "%Y-%m-%d %H:%M:%S")
#[clap(short, long, conflicts_with = "timeout")]
pub deadline: Option<String>,
deadline: Option<String>,
/// Name of the queue
#[clap(value_name = "QUEUE")]
pub queue: String,
queue: String,
/// Message to be sent to the queue
#[clap(value_name = "MESSAGE")]
pub msg: String,
msg: String,
}
impl Send {

View file

@ -1,5 +1,9 @@
mod create;
mod info;
mod list;
mod unlink;
pub use create::Create;
pub use info::Info;
pub use list::List;
pub use unlink::Unlink;

53
src/sysv/info.rs Normal file
View file

@ -0,0 +1,53 @@
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<i32>,
/// Key of the queue
#[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")]
key: Option<i32>,
}
fn print_line(line: &str) {
for field in line.split_whitespace().collect::<Vec<&str>>() {
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::<Vec<&str>>()[1].parse::<i32>()? {
print_line(&line);
break;
}
} else if let Some(key) = self.key {
if key == line.split_whitespace().collect::<Vec<&str>>()[0].parse::<i32>()? {
print_line(&line);
break;
}
}
}
Ok(())
}
}

24
src/sysv/list.rs Normal file
View file

@ -0,0 +1,24 @@
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::<Vec<&str>>() {
print!("{0: <10}", field);
}
println!();
}
Ok(())
}
}

View file

@ -7,15 +7,15 @@ use log::info;
pub struct Unlink {
/// Id of the queue
#[clap(
long,
short,
long,
required_unless_present_any = &["key"],
conflicts_with = "key"
)]
pub id: Option<i32>,
id: Option<i32>,
/// Key of the queue
#[clap(long, short, required_unless_present_any = &["id"], conflicts_with = "id")]
pub key: Option<i32>,
#[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")]
key: Option<i32>,
}
impl Unlink {
@ -25,9 +25,11 @@ impl Unlink {
info!("Removed message queue with id: {}", id);
} else if let Some(key) = self.key {
sysvmq::unlink_key(key)?;
let id = sysvmq::id_from_key(key)?;
info!("Removed message queue key: {}", key);
sysvmq::unlink_id(id)?;
info!("Removed message queue key: {} (id: {})", key, id);
}
Ok(())

View file

@ -1,21 +1,15 @@
use libc::{
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,
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,
};
use nix::errno::{errno, Errno};
use std::{marker::PhantomData, num::ParseIntError, ptr};
use std::{marker::PhantomData, mem::MaybeUninit, 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
@ -69,10 +63,63 @@ pub fn unlink_id(id: i32) -> Result<(), SysvMqError> {
}
}
pub fn unlink_key(key: i32) -> Result<(), SysvMqError> {
pub fn id_from_key(key: i32) -> Result<i32, SysvMqError> {
let id = unsafe { msgget(key, 0) };
unlink_id(id)
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::<msginfo>::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::<msqid_ds>::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::<msginfo>::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(())
}
pub struct SysvMq<T> {