Compare commits

..

11 commits

Author SHA1 Message Date
8f93d2d6c8 Fix clippy and remove borrows
Fix clippy lints and remove unneded borrows when logging or printing
macros.
2021-12-03 14:57:38 +01:00
1aab989000 Update build dependencies and edition
Use the 2021 Rust edition. To use current version of clap changes were
adapted.
2021-12-03 14:50:23 +01:00
d5ef64171a Cargo update and fix clap changes
To support the latest beta version of clap (v3.0.0-beta.4) small
changes were necessary.
2021-10-10 01:23:17 +02:00
8150e30ef5 Update descriptions and manpage
Reflect coping with different message queues.
2021-10-10 01:19:00 +02:00
90a3a5eb52 Use mod files
To have things more self contained.
2021-10-10 01:17:48 +02:00
ecd5ee5a36 Add functions to print information about SysV mqs
Not needed yet but maybe useful..
2021-07-09 00:31:51 +02:00
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
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
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
8d127d840e Minor fixes in readme and clap help 2021-07-08 14:14:25 +02:00
f726083759 Remove unneccessary pub declarations 2021-07-08 14:13:59 +02:00
18 changed files with 322 additions and 122 deletions

81
Cargo.lock generated
View file

@ -13,9 +13,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.41" version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]] [[package]]
name = "atty" name = "atty"
@ -42,9 +42,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.68" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -67,9 +67,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "3.0.0-beta.2" version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142" checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
dependencies = [ dependencies = [
"atty", "atty",
"bitflags", "bitflags",
@ -80,15 +80,14 @@ dependencies = [
"strsim", "strsim",
"termcolor", "termcolor",
"textwrap", "textwrap",
"unicode-width", "unicase",
"vec_map",
] ]
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "3.0.0-beta.2" version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error", "proc-macro-error",
@ -158,9 +157,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.98" version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
[[package]] [[package]]
name = "log" name = "log"
@ -173,9 +172,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
@ -202,9 +201,9 @@ dependencies = [
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.21.0" version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c3728fec49d363a50a8828a190b379a446cc5cf085c06259bbbeb34447e4ec7" checksum = "77d9f3521ea8e0641a153b3cddaf008dcbf26acd4ed739a2517295e0760d12c7"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cc", "cc",
@ -234,9 +233,12 @@ dependencies = [
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "2.4.0" version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "posixmq" name = "posixmq"
@ -273,18 +275,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.27" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.9" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -314,9 +316,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.73" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -343,27 +345,27 @@ dependencies = [
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.12.1" version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
dependencies = [ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.26" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.26" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -381,6 +383,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.8.0" version = "1.8.0"
@ -389,9 +400,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.8" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@ -399,12 +410,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.3" version = "0.9.3"

View file

@ -2,11 +2,11 @@
name = "mqrs" name = "mqrs"
version = "0.1.1" version = "0.1.1"
authors = ["finga <mqrs@onders.org>"] authors = ["finga <mqrs@onders.org>"]
edition = "2018" edition = "2021"
repository = "https://git.onders.org/finga/mqrs" repository = "https://git.onders.org/finga/mqrs"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
readme = "README.md" readme = "README.md"
description = "A CLI program for interacting with Posix Message Queues." description = "A CLI program for interacting with different kinds of message queues."
keywords = ["message_queue", "mq", "mqueue", "queue"] keywords = ["message_queue", "mq", "mqueue", "queue"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
@ -24,7 +24,7 @@ sysvmq = { path = "sysvmq" }
members = ["sysvmq"] members = ["sysvmq"]
[package.metadata.deb] [package.metadata.deb]
extended-description = "`mqrs` is a small cli application to handle POSIX message queues." extended-description = "`mqrs` is a small cli application to handle different kinds of message queues."
assets = [ assets = [
["target/release/mqrs", "usr/bin/", "755"], ["target/release/mqrs", "usr/bin/", "755"],
["README.md", "usr/share/doc/cargo-deb/README.md", "644"], ["README.md", "usr/share/doc/cargo-deb/README.md", "644"],

View file

@ -1,5 +1,6 @@
# mqrs # 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` ## Install `mqrs`
For information about how to build, install and run `mqrs` please see 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` ## Using `mqrs`
Depending on which backend you want to use there are different subsets Depending on which backend you want to use there are different subsets
of subcommands. Following backends are supported: of subcommands. Following backends are supported:
- `posix`: Uses POSIX message queues - `posix`: Use POSIX message queues
- `sysv`: Uses SysV IPC message queues - `sysv`: Use SysV IPC message queues
If a command is clearly distinguishable from all the others, If a command is clearly distinguishable from all the others,
it does not have to be completed further. 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 - `-m`, `--mode`: Permissions (octal) to create the queue
with. Default: 0644. 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 #### Delete a message queue
Use the `unlink` command to delete a message queue. This can either be Use the `unlink` command to delete a message queue. This can either be
done by providing a `key` or an `id` of the queue: done by providing a `key` or an `id` of the queue:

70
mqrs.1
View file

@ -41,7 +41,7 @@ The POSIX backend supports six commands:
and and
.B recv .B recv
. .
.SS create [FLAGS] [OPTIONS] \fI<QUEUE>\fP .SS posix create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
Create a new POSIX message queue. Create a new POSIX message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -72,7 +72,7 @@ Message size in bytes
.B \-m, \-\-mode \fI<mode>\fP .B \-m, \-\-mode \fI<mode>\fP
Permissions (octal) to create the queue with Permissions (octal) to create the queue with
.RE .RE
.SS help [SUBCOMMAND] .SS posix help [SUBCOMMAND]
Prints this message or the help of the given subcommand. Prints this message or the help of the given subcommand.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -81,7 +81,7 @@ Prints this message or the help of the given subcommand.
.B \fI<SUBCOMMAND>\fP .B \fI<SUBCOMMAND>\fP
Show help for \fISUBCOMMAND\fP Show help for \fISUBCOMMAND\fP
.RE .RE
.SS info [FLAGS] \fI<QUEUE>\fP .SS posix info [FLAGS] \fI<QUEUE>\fP
Print further information about an existing message queue. Print further information about an existing message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -100,7 +100,7 @@ Prints help information
.B \-v, \-\-verbose .B \-v, \-\-verbose
Produce verbose output Produce verbose output
.RE .RE
.SS list [FLAGS] .SS posix list [FLAGS]
Print a list of all existing POSIX message queues. Print a list of all existing POSIX message queues.
.TP 8 .TP 8
.SS FLAGS .SS FLAGS
@ -115,7 +115,7 @@ Produce verbose output
.B \-a, \-\-all .B \-a, \-\-all
Print all available information Print all available information
.RE .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. Receive and print one or more messages message from a message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -153,7 +153,7 @@ Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
.B \-o, \-\-timeout \fI<timeout>\fP .B \-o, \-\-timeout \fI<timeout>\fP
Timeout as for example in "5h 23min 42ms" Timeout as for example in "5h 23min 42ms"
.RE .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. Send a message to a message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -191,7 +191,7 @@ Set a different priority than default, priority >= 0 [default: 0]
.B \-o, \-\-timeout \fI<timeout>\fP .B \-o, \-\-timeout \fI<timeout>\fP
Timeout as for example in "5h 23min 42ms" Timeout as for example in "5h 23min 42ms"
.RE .RE
.SS unlink [FLAGS] \fI<QUEUE>\fP .SS posix unlink [FLAGS] \fI<QUEUE>\fP
Delete an existing POSIX message queue. Delete an existing POSIX message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -211,12 +211,16 @@ Prints help information
Produce verbose output Produce verbose output
.RE .RE
.SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS .SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS
The SysV IPC backend supports two commands: The SysV IPC backend supports four commands:
.B create\ .B create\
,
.B info\
,
.B list
and and
.B unlink\ .B unlink\
. .
.SS create [FLAGS] [OPTIONS] \fI<KEY>\fP .SS sysv create [FLAGS] [OPTIONS] \fI<KEY>\fP
Create a new SysV IPC message queue. Create a new SysV IPC message queue.
.TP 8 .TP 8
.SS ARGS .SS ARGS
@ -241,7 +245,51 @@ Produce verbose output
.B \-m, \-\-mode \fI<mode>\fP .B \-m, \-\-mode \fI<mode>\fP
Permissions (octal) to create the queue with (default: 0644) Permissions (octal) to create the queue with (default: 0644)
.RE .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 Delete an existing SysV IPC message queue. It is mandatory to pass
exactly one OPTION. exactly one OPTION.
.TP 8 .TP 8
@ -271,7 +319,7 @@ Id of the queue
Key of the queue Key of the queue
.RE .RE
.SH SEE ALSO .SH SEE ALSO
mq_overview(7) mq_overview(7), sysvipc(7)
.SH BUGS .SH BUGS
No known bugs. No known bugs.
.SH AUTHOR .SH AUTHOR

View file

@ -1,18 +1,20 @@
use anyhow::Result; use anyhow::Result;
use clap::{crate_authors, crate_version, AppSettings, Clap}; use clap::{crate_authors, crate_version, AppSettings, Parser};
mod posix; mod posix;
mod sysv; mod sysv;
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
enum Backend { enum Backend {
/// Handle POSIX message queues /// Handle POSIX message queues
#[clap(subcommand)]
Posix(PosixCommand), Posix(PosixCommand),
/// Handle SysV message queues /// Handle SysV message queues
#[clap(subcommand)]
Sysv(SysvCommand), Sysv(SysvCommand),
} }
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
enum PosixCommand { enum PosixCommand {
Create(posix::Create), Create(posix::Create),
Info(posix::Info), Info(posix::Info),
@ -22,18 +24,20 @@ enum PosixCommand {
Recv(posix::Recv), Recv(posix::Recv),
} }
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
enum SysvCommand { enum SysvCommand {
Create(sysv::Create), Create(sysv::Create),
Info(sysv::Info),
List(sysv::List),
Unlink(sysv::Unlink), Unlink(sysv::Unlink),
} }
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
#[clap( #[clap(
version = crate_version!(), version = crate_version!(),
author = crate_authors!(", "), author = crate_authors!(", "),
setting = AppSettings::SubcommandRequiredElseHelp, setting = AppSettings::SubcommandRequiredElseHelp,
global_setting = AppSettings::VersionlessSubcommands, global_setting = AppSettings::PropagateVersion,
global_setting = AppSettings::InferSubcommands, global_setting = AppSettings::InferSubcommands,
)] )]
struct Opts { struct Opts {
@ -69,6 +73,8 @@ fn main() -> Result<()> {
}, },
Backend::Sysv(s) => match s { Backend::Sysv(s) => match s {
SysvCommand::Create(c) => c.run()?, SysvCommand::Create(c) => c.run()?,
SysvCommand::Info(i) => i.run()?,
SysvCommand::List(l) => l.run()?,
SysvCommand::Unlink(u) => u.run()?, SysvCommand::Unlink(u) => u.run()?,
}, },
} }

View file

@ -1,11 +1,11 @@
use anyhow::Result; use anyhow::Result;
use clap::Clap; use clap::Parser;
use log::{info, log_enabled, Level::Info}; use log::{info, log_enabled, Level::Info};
use posixmq::PosixMq; use posixmq::PosixMq;
use std::fs; use std::fs;
/// Create a POSIX message queue /// Create a POSIX message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Create { pub struct Create {
/// Permissions (octal) to create the queue with /// Permissions (octal) to create the queue with
#[clap(short, long)] #[clap(short, long)]
@ -40,7 +40,7 @@ impl Create {
let mq = &mut posixmq::OpenOptions::readonly(); let mq = &mut posixmq::OpenOptions::readonly();
if let Some(m) = &self.mode { if let Some(m) = &self.mode {
mq.mode(u32::from_str_radix(&m, 8)?); mq.mode(u32::from_str_radix(m, 8)?);
} }
mq.max_msg_len(self.msgsize.unwrap_or_else(msgsize_default)) mq.max_msg_len(self.msgsize.unwrap_or_else(msgsize_default))
@ -53,10 +53,10 @@ impl Create {
let attributes = mq.attributes()?; let attributes = mq.attributes()?;
info!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}", info!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}",
&self.queue, self.queue,
&attributes.max_msg_len, attributes.max_msg_len,
&attributes.capacity, attributes.capacity,
&attributes.current_messages); attributes.current_messages);
} }
Ok(()) Ok(())

View file

@ -1,13 +1,13 @@
use anyhow::Result; use anyhow::Result;
use clap::Clap; use clap::Parser;
use posixmq::PosixMq; use posixmq::PosixMq;
/// Print information about an existing message queue /// Print information about an existing message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Info { pub struct Info {
/// Name of the queue /// Name of the queue
#[clap(value_name = "QUEUE")] #[clap(value_name = "QUEUE")]
pub queue: String, queue: String,
} }
impl Info { impl Info {
@ -16,7 +16,7 @@ impl Info {
println!( println!(
"Message queue: {}, msg_max: {}, msgsize_max: {}, current_messages: {}", "Message queue: {}, msg_max: {}, msgsize_max: {}, current_messages: {}",
&self.queue, &attrs.capacity, &attrs.max_msg_len, &attrs.current_messages self.queue, attrs.capacity, attrs.max_msg_len, attrs.current_messages
); );
Ok(()) Ok(())

View file

@ -1,11 +1,11 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use clap::Clap; use clap::Parser;
use log::warn; use log::warn;
use std::{fs, os::unix::fs::PermissionsExt}; use std::{fs, os::unix::fs::PermissionsExt};
/// Print information about an existing message queue /// Print a list of existing message queues
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct List { pub struct List {
/// Show all parameters /// Show all parameters
#[clap(short, long)] #[clap(short, long)]

View file

@ -1,32 +1,32 @@
use anyhow::Result; use anyhow::Result;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use clap::Clap; use clap::Parser;
use humantime::Duration; use humantime::Duration;
use log::info; use log::info;
use posixmq::PosixMq; use posixmq::PosixMq;
use std::str; use std::str;
/// Receive and print a message from a message queue /// Receive and print a message from a message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Recv { pub struct Recv {
/// Do not block /// Do not block
#[clap(short, long)] #[clap(short, long)]
pub non_blocking: bool, non_blocking: bool,
/// Print messages as they are received /// Print messages as they are received
#[clap(short, long)] #[clap(short, long)]
pub follow: bool, follow: bool,
/// Print a timestamp before each message /// Print a timestamp before each message
#[clap(short, long)] #[clap(short, long)]
pub timestamp: bool, timestamp: bool,
/// Timeout, example "5h 23min 42ms" /// Timeout, example "5h 23min 42ms"
#[clap(short = 'o', long, conflicts_with = "deadline")] #[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") /// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
#[clap(short, long, conflicts_with = "timeout")] #[clap(short, long, conflicts_with = "timeout")]
pub deadline: Option<String>, deadline: Option<String>,
/// Name of the queue /// Name of the queue
#[clap(value_name = "QUEUE")] #[clap(value_name = "QUEUE")]
pub queue: String, queue: String,
} }
fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) { fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) {

View file

@ -1,30 +1,30 @@
use anyhow::Result; use anyhow::Result;
use chrono::DateTime; use chrono::DateTime;
use clap::Clap; use clap::Parser;
use humantime::Duration; use humantime::Duration;
use log::info; use log::info;
/// Send a message to a message queue /// Send a message to a message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Send { pub struct Send {
/// Set a different priority, priority >= 0 /// Set a different priority, priority >= 0
#[clap(short, long, default_value = "0")] #[clap(short, long, default_value = "0")]
pub priority: u32, priority: u32,
/// Do not block /// Do not block
#[clap(short, long)] #[clap(short, long)]
pub non_blocking: bool, non_blocking: bool,
/// Timeout, example "5h 23min 42ms" /// Timeout, example "5h 23min 42ms"
#[clap(short = 'o', long, conflicts_with = "deadline")] #[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") /// Deadline until messages are sent (format: "%Y-%m-%d %H:%M:%S")
#[clap(short, long, conflicts_with = "timeout")] #[clap(short, long, conflicts_with = "timeout")]
pub deadline: Option<String>, deadline: Option<String>,
/// Name of the queue /// Name of the queue
#[clap(value_name = "QUEUE")] #[clap(value_name = "QUEUE")]
pub queue: String, queue: String,
/// Message to be sent to the queue /// Message to be sent to the queue
#[clap(value_name = "MESSAGE")] #[clap(value_name = "MESSAGE")]
pub msg: String, msg: String,
} }
impl Send { impl Send {
@ -38,24 +38,24 @@ impl Send {
if let Some(timeout) = &self.timeout { if let Some(timeout) = &self.timeout {
mq.open(&self.queue)?.send_timeout( mq.open(&self.queue)?.send_timeout(
self.priority, self.priority,
&self.msg.as_bytes(), self.msg.as_bytes(),
*timeout.parse::<Duration>()?, *timeout.parse::<Duration>()?,
)?; )?;
info!("Sent message: \"{}\" to queue: {}", &self.msg, &self.queue); info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
} else if let Some(deadline) = &self.deadline { } else if let Some(deadline) = &self.deadline {
mq.open(&self.queue)?.send_deadline( mq.open(&self.queue)?.send_deadline(
self.priority, self.priority,
&self.msg.as_bytes(), self.msg.as_bytes(),
DateTime::parse_from_str(deadline, "%Y-%m-%d %H:%M:%S")?.into(), DateTime::parse_from_str(deadline, "%Y-%m-%d %H:%M:%S")?.into(),
)?; )?;
info!("Sent message: \"{}\" to queue: {}", &self.msg, &self.queue); info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
} else { } else {
mq.open(&self.queue)? mq.open(&self.queue)?
.send(self.priority, &self.msg.as_bytes())?; .send(self.priority, self.msg.as_bytes())?;
info!("Sent message: \"{}\" to queue: {}", &self.msg, &self.queue); info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
} }
Ok(()) Ok(())

View file

@ -1,9 +1,9 @@
use anyhow::Result; use anyhow::Result;
use clap::Clap; use clap::Parser;
use log::info; use log::info;
/// Delete a message queue /// Delete a message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Unlink { pub struct Unlink {
/// Name of the queue /// Name of the queue
#[clap(value_name = "QUEUE")] #[clap(value_name = "QUEUE")]
@ -14,7 +14,7 @@ impl Unlink {
pub fn run(&self) -> Result<()> { pub fn run(&self) -> Result<()> {
posixmq::remove_queue(&self.queue)?; posixmq::remove_queue(&self.queue)?;
info!("Removed message queue: {}", &self.queue); info!("Removed message queue: {}", self.queue);
Ok(()) Ok(())
} }

View file

@ -1,10 +1,10 @@
use anyhow::Result; use anyhow::Result;
use clap::Clap; use clap::Parser;
use log::info; use log::info;
use sysvmq::SysvMq; use sysvmq::SysvMq;
/// Create a SysV message queue /// Create a SysV message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Create { pub struct Create {
/// Permissions (octal) to create the queue with (default: 0644) /// Permissions (octal) to create the queue with (default: 0644)
#[clap(short, long)] #[clap(short, long)]
@ -19,7 +19,7 @@ impl Create {
let mut mq = SysvMq::<String>::new(); let mut mq = SysvMq::<String>::new();
if let Some(m) = &self.mode { if let Some(m) = &self.mode {
mq.mode(i32::from_str_radix(&m, 8)?); mq.mode(i32::from_str_radix(m, 8)?);
} }
mq.create(self.key)?; mq.create(self.key)?;

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

@ -0,0 +1,53 @@
use anyhow::Result;
use clap::Parser;
use std::{
fs::File,
io::{BufRead, BufReader},
};
/// Print information about an existing message queue
#[derive(Debug, Parser)]
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.next().unwrap_or_else(|| 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::Parser;
use std::{
fs::File,
io::{BufRead, BufReader},
};
/// Print a list of existing message queues
#[derive(Debug, Parser)]
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

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

View file

@ -1,21 +1,21 @@
use anyhow::Result; use anyhow::Result;
use clap::Clap; use clap::Parser;
use log::info; use log::info;
/// Delete a message queue /// Delete a message queue
#[derive(Clap, Debug)] #[derive(Debug, Parser)]
pub struct Unlink { pub struct Unlink {
/// Id of the queue /// Id of the queue
#[clap( #[clap(
long,
short, short,
long,
required_unless_present_any = &["key"], required_unless_present_any = &["key"],
conflicts_with = "key" conflicts_with = "key"
)] )]
pub id: Option<i32>, id: Option<i32>,
/// Key of the queue /// Key of the queue
#[clap(long, short, required_unless_present_any = &["id"], conflicts_with = "id")] #[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")]
pub key: Option<i32>, key: Option<i32>,
} }
impl Unlink { impl Unlink {
@ -25,9 +25,11 @@ impl Unlink {
info!("Removed message queue with id: {}", id); info!("Removed message queue with id: {}", id);
} else if let Some(key) = self.key { } 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(()) Ok(())

View file

@ -1,21 +1,15 @@
use libc::{ use libc::{
msgctl, msgget, msqid_ds, IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_NOWAIT, IPC_PRIVATE, IPC_RMID, msgctl, msgget, msginfo, msqid_ds, IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_NOWAIT, IPC_PRIVATE,
IPC_SET, IPC_STAT, MSG_COPY, MSG_EXCEPT, MSG_INFO, MSG_NOERROR, MSG_STAT, IPC_RMID, IPC_SET, IPC_STAT, MSG_COPY, MSG_EXCEPT, MSG_INFO, MSG_NOERROR, MSG_STAT,
}; };
use nix::errno::{errno, Errno}; use nix::errno::{errno, Errno};
use std::{marker::PhantomData, num::ParseIntError, ptr}; use std::{marker::PhantomData, mem::MaybeUninit, ptr};
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum SysvMqError { pub enum SysvMqError {
#[error("SysV message queue: {0}")] #[error("SysV message queue: {0}")]
ErrnoError(&'static str), 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 /// 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) }; 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> { pub struct SysvMq<T> {